c++ - 当我们尝试使用 istream::getline() 和 std::getline() 提取文件中出现 `eof` 字符的行时,实际会发生什么

标签 c++ string file-handling eof getline

roha.txt

I really love to spend time with you.
Let's go for coffee someday.
Enjoy whole day and cherish the memories.

代码1

#include <iostream>
#include <fstream>


int main()
{
    char str[100];

    std::ifstream fin;
    fin.open("roha.txt", std::ios::in);

   for(int i=0; i<=3; i++)
   {
        std::cout<<bool(fin.getline(str,100) )<<" "<<str<<fin.fail()<<"\n";
   }

}

输出

1 I really love to spend time with you.0
1 Let's go for coffee someday.0
1 Enjoy whole day and cherish the memories.0
0 1

代码2

#include <iostream>
#include <fstream>
#include <string>
using std::string;

int main()
{
   string str;

    std::ifstream fin;
    fin.open("roha.txt", std::ios::in);

    for(int i=0; i<=3; i++)
    {
        std::cout<<bool(std::getline(fin,str) )<<" "<<str<<fin.fail()<<"\n";
    }

}

输出

1 I really love to spend time with you.0
1 Let's go for coffee someday.0
1 Enjoy whole day and cherish the memories.0
0 Enjoy whole day and cherish the memories.1

我知道C风格的字符数组istream::getlinestringstd::getline是不同的。但我想知道到底发生了什么。

我猜测对于stringstd::getline,它会提取第一次、第二次的字符串,当它尝试提取第三次时,它会看到 eof 因此它会在 eof 之前提取。

下次我们尝试提取它时,只是遇到了 eof,因此它没有提取任何内容并设置了 fail-bit

string str 没有被修改,因此当我们尝试打印它时,只会打印最后提取的字符串。

不知道我的想法是否正确...

此外,我无法对 istream::getline()C 风格字符数组做出任何此类情况。

最佳答案

引用标准,第 21.3.3.4 节插入器和提取器 [string.io]:

第 6 条:

[…] After constructing a sentry object, if the sentry converts to true, calls str.erase() and then extracts characters from is and appends them to str […] until any of the following occurs:

  • end-of-file occurs on the input sequence (in which case, the getline function calls is.setstate(ios_base::eofbit)).
  • […]

第 29.7.4.1.3 节类 basic_istream::sentry :

explicit sentry(basic_istream<charT, traits>& is, bool noskipws = false); Effects: If is.good() is false, calls is.setstate(failbit) […] If, after any preparation is completed, is.good() is true, ok_ != false otherwise, ok_ == false. During preparation, the constructor may call setstate(failbit) […]

explicit operator bool() const; Returns: ok_

那么,字符串版本发生了什么:

  1. 您提取最后一个字符串。这设置了eofbit,但不设置failbit
  2. 您再次接通
  3. getline 构造一个哨兵
  4. 哨兵检查is.good() 。这是错误的,因为 eofbit 已设置
  5. 哨兵设置失败位并将其成员 ok_ 设置为 false
  6. getline 函数检查哨兵是否为真(operator bool)。这是错误的
  7. getline 函数在清除旧字符串之前返回

第 29.7.4.3 节无格式输入函数

第 21 条(这是关于 C 字符串版本):

In any case, if n is greater than zero, it then stores a null character (using charT()) into the next successive location of the array

其余的措辞与字符串版本类似。换句话说,getline 的 C 字符串版本始终存储 '\0'性格,即使失败了。 std::string版本没有,大概是因为如果您忘记检查故障位,它不会引入与 C 版本相同的内存安全问题。

关于c++ - 当我们尝试使用 istream::getline() 和 std::getline() 提取文件中出现 `eof` 字符的行时,实际会发生什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69696504/

相关文章:

c - 我如何使用指针来使用 malloc 存储多个字符串

c++ - 在 C++ 中访问重载运算符

c++ - 如何在mfc项目中创建新窗口

c++ - 为什么这个访问冲突

java - 在 Java 中将字符串分成多个部分的安全方法是什么?

c - 运行以下文件处理 C 程序时,为什么输出不符合预期?

C 文件处理 - 整数值 13 不能写入文件

C++11 如何在其他类或源文件中引用类方法

r - 使用 grepl 创建基于另一列的列

java - 从字符串中删除除特殊单词外的所有内容