使用C ++读取和打印文本文件时出错

时间:2013-04-10 13:06:01

标签: c++

我的代码存在错误(问题末尾的代码)。我的C ++可执行文件的目的是读取包含数字的文件,将其复制到std :: vector中 然后只打印标准输出中的内容?问题出在哪儿? (的atoi?)

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

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 个答案:

答案 0 :(得分:6)

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

改为使用

while (getline(...))

您无法使用标志检查循环的原因是,在输入/输出操作后注意到问题(错误或文件结束)之前,它们不会被设置)。

答案 1 :(得分: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设置为空字符串。然后将其转换为int并推入vector1,为您提供额外的价值。

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

欢迎来到精彩的C ++世界。在我们首先讨论错误之前,我建议您在定义或声明std::之前删除vector命名空间解析

using namespace::std;

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

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

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

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