从文件中读取整数输入到动态数组中并打印它

Reading integer input from file into a dynamic array and printing it

本文关键字:数组 打印 动态 输入 文件 读取 整数      更新时间:2023-10-16

我正在尝试编写一个程序,从输入文件中读取整数并输出动态数组。这个数组就是输入的大小。为了验证,我还想打印数组。输出将被传递给一个函数来创建一个排序的链表。

我尝试了以下操作,但没有成功:

istringstream input(R"inp(
23 43 12 67 
18 15 22
12 xxx 23 12 xx 34556 11 11 www
)inp");
int get, count = 0;
while (input >> get)
    count++;
cout << "Number of integers: " << count << endl;
int *array = new int [count];

for (int i = 0; i < count; i++)
{
    input >> array[i];
}
for (int i = 0; i < count; i++)
{
    cout << *(array+i) << endl;
}
delete[] array;

这是我的代码的在线示例。

问题是输出显示了一些奇怪的数字,与输入完全无关:

整数个数:8
-1217944384
-1217944384
1
538976266
540226080
824193844

我哪里做错了?

正如π α ντα ρ ε ν所指出的,我所提供的解决方案并不完全安全,这就是为什么我将提供第三个例子,使用boost::spirit。

参见快速修复好的解决方案,以及π ντα ρ ε ε>的答案,使其在不使用boost的情况下工作。

我个人最喜欢的解决方案: 注意,这个例子确实需要将文本文件读入字符串。

#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
template<typename Iterator>
bool
parse_numbers(Iterator first, Iterator last, std::vector<int>& v)
{
    bool r =
    boost::spirit::qi::parse(first, last,
    //  Begin grammar
        (boost::spirit::qi::int_[boost::phoenix::push_back(
            boost::phoenix::ref(v), _1)]
            % *(boost::spirit::qi::char_("a-zA-Z")
                | boost::spirit::ascii::space)));
    if (first != last) // fail if we did not get a full match
       return false;
    return r;
}
const std::string s = "23 43 12 67 n18 15 22n12 xxx 23 12 xx 34556 11 11 www";
std::string::const_iterator start = s.begin(), stop = s.end();
std::vector<int> results;
parse_numbers(start, stop, results)));
for(int i : results)
    std::cout << value << ' '; 
如预期的那样,结果将是:
23 43 12 67 18 15 22 12 23 12 34556 11 11

上面的示例部分是基于boost::spirit文档中给出的示例构建的。

input >> get移动当前光标位置,因此在while循环之后,您没有剩余的内容可读。

快速解决办法:

ifstream input;
input.open("file.txt");
int get, count = 0;
while (input >> get)
    count++;
input.close();
input.open("file.txt");    
int *array = new int [count];    
for (int i = 0; i < count; i++)
{
    input >> array[i];
}
for (int i = 0; i < count; i++)
{
    cout << *(array+i) << endl;
}
input.close();
delete[] array;

关闭并重新打开流应该可以工作,但是还有更有效的解决方案…

好的解决方案:

例如,可以对动态增长的向量进行读取和插入操作。参考文档
std::vector<int> dataArray;
while (input >> get)
{
    dataArray.insert(dataArray.end(), get);
}
for(auto&& value : dataArray)
{
    std::cout << value << std::endl; 
}

这样做有很多好处:

  1. 在堆栈上分配向量可以防止强制调用delete。另一种选择是标准的智能指针。
  2. for每个循环即使不计算元素也能工作。如果你需要元素的数量,你可以直接询问vector的大小。

你的代码有几个误解和缺陷:

(1)应用此循环计算输入

 while (input >> get)
    count++;

输入流的状态是上次提取操作(input >> get)失败后的结果。因此,如果不完全重置流,则无法读取进一步的输入。

(2)显示的第二个循环

for (int i = 0; i < count; i++) {
    input >> array[i];
}

在无效状态下使用input流(整个流已经被读取到input.eof()),因此从它读取会导致'奇怪的值'(换句话说:此时未定义行为)。


我将编写下面经过验证的代码来解决这个

// Your literal input file formatting goes here
istringstream input(R"inp(
23 43 12 67 
18 15 22
12 xxx 23 12 xx 34556 11 11 www
)inp");
int current;
vector<int> allIntInputs;
while (input >> current || !input.eof()) {
    if(input.fail()) {
        input.clear();
        string crap;
        input >> crap; // read anything up to the next 
                       // whitespace delimiter (the default deleimiters)
        continue; // with the next item
    }
    // Everything's fine we'll add another number
    allIntInputs.push_back(current);
}
// Print all integer values extracted
cout << "Integer values read from input:" << endl;
for(vector<int>::iterator it = allIntInputs.begin();
    it != allIntInputs.end();
    ++it) {
    if(it != allIntInputs.begin()) {
        cout << ' ';
    }
    cout << *it;    
}
cout << endl;

输出
Integer values read from input:
23 43 12 67 18 15 22 12 23 12 34556 11 11