0

我的代码有一个错误(问题末尾的代码)。我的 C++ 可执行文件的目的是读取包含数字的文件,将其复制到 std::vector 中,然后仅在 stdout 中打印内容?问题出在哪里?(阿托伊?)

我有一个简单的文本文件,其中包含以下数字(每行有一个数字)

mini01:algorithms ios$ cat numbers.txt 
1
2
3
4
5

当我执行程序时,我又收到一行:

mini01:algorithms ios$ ./a.out 
1
2
3
4
5
0

为什么我在标准输出中得到第 6 行?

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;

void algorithm(std::vector<int>& v) {

    for(int i=0; i < v.size(); i++) {
        cout << v[i] << endl;
    }

}

int main(int argc, char **argv) {

    string line;
    std::vector<int> vector1;
    ifstream myfile("numbers.txt");
    if ( myfile.is_open()) {
        while( myfile.good() )
        {
            getline(myfile, line);
            vector1.push_back(atoi(line.c_str()));
        }
        myfile.close();
    }
    else {
        cout << "Unable to open file" << endl;
    }

    algorithm(vector1);

    return 0;

}
4

4 回答 4

6

您不应该使用while (myfile.good()),因为它会循环一次到多次。

而是使用

while (getline(...))

您不能使用标志来检查循环的原因是,直到输入/输出操作注意到问题(错误或文件结尾)之后才会设置它们。

于 2013-04-10T13:07:28.193 回答
2

不要good()用作提取循环的条件。它不能准确地指示下一次读取是否会成功。将您的电话移至getline以下条件:

while(getline(myfile, line))
{
    vector1.push_back(atoi(line.c_str()));
}

在这种特殊情况下失败的原因是文本文件通常\n在文件末尾有一个(文本编辑器不显示)。读取最后一行时,\n将从流中提取。是的,这可能是文件中的最后一个字符,但getline不关心比\n它提取的更远的地方。完成。它不会设置 EOF 标志或做任何其他事情来导致good()返回 false。

所以在下一次迭代时,good()仍然是true,循环继续并getline尝试从文件中提取。但是,现在没有什么可提取的了,您只需line设置为一个空字符串。然后将其转换为 anint并推入vector1,从而为您提供额外的价值。

事实上,检查提取是否存在问题的唯一可靠方法是在提取后检查流的状态。最简单的方法是使提取本身成为条件。

于 2013-04-10T13:07:59.413 回答
1

您阅读了太多行,因为在while您“阅读错误”之后条件为假。

于 2013-04-10T13:07:42.877 回答
1

欢迎来到 C++ 的美妙世界。在我们首先解决错误之前,我建议您std::在定义或声明 a 之前删除名称空间解析,vector因为您已经拥有

using namespace::std;

第二个建议是在可行的情况下++i使用预增量运算符。i++您可以在此处查看更多详细信息。

解决您的问题本身,问题是在文件末尾读取一个空的新行。避免这种情况的一个简单方法是在使用之前检查行的长度。

getline(myfile, line);
if (line.size()) {
  vector1.push_back(atoi(line.c_str()));
}

这将使您的程序现在可以读取散布有空行的文件。为了更加万无一失,您可以在使用 atoi 之前检查读取的行是否存在任何非数字字符。然而,如上所述的最佳解决方案将用于读取读取到循环评估的行。

于 2013-04-10T13:30:12.217 回答