我的代码存在错误(问题末尾的代码)。我的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;
}
答案 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之前检查读取的行是否存在任何非数字字符。然而,所提到的最佳解决方案是用于读取循环评估的读取行。