将整数输入从文件读入动态数组并打印出来

时间:2014-07-08 18:38:34

标签: c++ dynamic-arrays

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

我尝试了以下操作,但它不起作用:

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;

Here's an online example我的代码。

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

  

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

我哪里出错了?

2 个答案:

答案 0 :(得分:1)

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

查看点快速修复良好解决方案,以及πάνταῥεῖ的答案,让它在不使用提升的情况下运行。

我个人最喜欢的解决方案: 请注意,此示例确实需要将文本文件读取为字符串。

#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 22\n12 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文档中的example given

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;

关闭并重新打开流应该有效,但有更有效的解决方案......

良好的解决方案:

例如,可以是读取并插入到动态增长的向量中。有关详细信息,请参阅the documentation

std::vector<int> dataArray;
while (input >> get)
{
    dataArray.insert(dataArray.end(), get);
}
for(auto&& value : dataArray)
{
    std::cout << value << std::endl; 
}

这将有多重优势:

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

答案 1 :(得分:1)

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

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

 while (input >> get)
    count++;

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

(2)你正在展示的第二个循环

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

使用处于无效状态的input流(整个流已经读取到input.eof()),因此从中读取会导致'奇怪的值'(在其他情况下)单词:此时 未定义的行为 。)


我会写following proven code来解决这个问题

// 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