C++:使用ifstream和getline()函数。

16

请检查这个程序

ifstream filein("Hey.txt");
filein.getline(line,99);
cout<<line<<endl;
filein.getline(line,99);
cout<<line<<endl;
filein.close();

Hey.txt这个文件里有很多字符,远超过1000个。

但我的问题是:为什么第二次尝试打印这一行时,它没有被打印出来?

5个回答

59

从流中读取行的惯用方法是:

std::ifstream filein("Hey.txt");

for (std::string line; std::getline(filein, line); ) 
{
    std::cout << line << std::endl;
}

注意事项:

  • 不需要使用close()方法,当以惯用方式使用时,C++会为您处理资源管理。

  • 请使用免费的std::getline函数,而不是流成员函数。


2
这实际上一点也没有帮助到我的问题。 - Mohamed Ahmed Nabil
第一次打印输出行时,它会打印出前99个字符,但下一次这样做时,它将不会打印任何内容。 - Mohamed Ahmed Nabil
@MohamedAhmedNabil:请看上面。如果您在getline之后不检查错误条件,就不能保证任何情况 - Kerrek SB
6
问题在于,如果在98个字符内没有换行符,则会被认为是失败,并使流处于故障模式,即将设置 std::ios_base::failbit。当此位被设置后,该流将不会提取任何字符。奇怪的是,它会修改字符数组并存储一个空字符到下一个位置,也就是第一个位置。 - Dietmar Kühl
2
这是处理流的最惯用方式。 - ThePrimeagen
显示剩余2条评论

14
根据C++参考(这里),当抽取了count-1个字符时,getline会设置ios::fail。你需要在getline()调用之间调用filein.clear();

2
提供一些解释会更好。ios::fail 是什么,发生了什么:D - Mohamed Ahmed Nabil
3
我喜欢像你这样的人,能够像那样推动我前进。再次感谢。 - Mohamed Ahmed Nabil
在std::ios_base中定义的流有几个位用于跟踪其内部状态:goodbit、badbit、failbit和eofbit。当任何一个“坏”位被设置时,流停止读取并计算为false(例如,用作while条件)。这就是为什么Kerrek SB建议使用while循环的原因。 - Roman Kutlak
比特只影响流。文件实际上没有发生什么变化。 - Roman Kutlak

3
#include<iostream>
using namespace std;
int main() 
{
ifstream in;
string lastLine1;
string lastLine2;
in.open("input.txt");
while(in.good()){
    getline(in,lastLine1);
    getline(in,lastLine2);
}
in.close();
if(lastLine2=="")
    cout<<lastLine1<<endl;
else
    cout<<lastLine2<<endl;
return 0;
}

4
虽然这个代码可能解决了问题,但是附上一个解释说明它如何解决问题以及为什么能解决问题,会更有助于提高你的帖子质量并可能得到更多的赞。请记住,你的回答是为未来的读者而写的,而不仅仅是为现在提问的人。请编辑你的回答,添加解释并指出哪些限制和假设适用。 - Adrian Mole

0

获取一行的更简单的方法是使用ifstream的提取运算符。

    string result;
    //line counter
    int line=1;
    ifstream filein("Hey.txt");
    while(filein >> result)
    { 
      //display the line number and the result string of reading the line
      cout << line << result << endl;
      ++line;
    }

这里的一个问题是,当行中有空格' '时,它将无法工作,因为在ifstream中它被视为字段分隔符。如果您想要实现这种解决方案,请将字段分隔符更改为例如- /或任何其他您喜欢的字段分隔符。

如果您知道有多少个空格,则可以使用ifstream的提取器运算符中的其他变量来吃掉所有空格。考虑文件包含名字和姓氏。

    //file content is: FirstName LastName
    int line=1;
    ifstream filein("Hey.txt");
    string firstName;
    string lastName;
    while(filein>>firstName>>lastName)
    {
      cout << line << firstName << lastName << endl;
    }

0
正如Kerrek SB所说,有两种可能性: 1)第二行是空行 2)没有第二行,所有超过1000个字符的内容都在一行中,因此第二个getline无法获取任何内容。

实际上,即使只有一行,getline也应该从它上次结束的地方继续。 - Mohamed Ahmed Nabil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接