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::getline
和string
、std::getline
是不同的。但我想知道到底发生了什么。
我猜测对于string
、std::getline
,它会提取第一次、第二次的字符串,当它尝试提取第三次时,它会看到 eof
因此它会在 eof
之前提取。
下次我们尝试提取它时,只是遇到了 eof
,因此它没有提取任何内容并设置了 fail-bit
。
string str
没有被修改,因此当我们尝试打印它时,只会打印最后提取的字符串。
不知道我的想法是否正确...
此外,我无法对 istream::getline()
、C 风格字符数组
做出任何此类情况。
最佳答案
引用标准,第 21.3.3.4 节插入器和提取器 [string.io]:
第 6 条:
[…] After constructing a
sentry
object, if thesentry
converts totrue
, callsstr.erase()
and then extracts characters fromis
and appends them tostr
[…] until any of the following occurs:
- end-of-file occurs on the input sequence (in which case, the
getline
function callsis.setstate(ios_base::eofbit))
.- […]
第 29.7.4.1.3 节类 basic_istream::sentry
:
explicit sentry(basic_istream<charT, traits>& is, bool noskipws = false);
Effects: Ifis.good()
isfalse
, callsis.setstate(failbit)
[…] If, after any preparation is completed,is.good()
istrue
,ok_ != false
otherwise,ok_ == false
. During preparation, the constructor may callsetstate(failbit)
[…]
explicit operator bool() const;
Returns:ok_
那么,字符串版本发生了什么:
- 您提取最后一个字符串。这设置了eofbit,但不设置failbit
- 您再次接通
- getline 构造一个哨兵
- 哨兵检查
is.good()
。这是错误的,因为 eofbit 已设置 - 哨兵设置失败位并将其成员 ok_ 设置为 false
- getline 函数检查哨兵是否为真(operator bool)。这是错误的
- getline 函数在清除旧字符串之前返回
第 29.7.4.3 节无格式输入函数
第 21 条(这是关于 C 字符串版本):
In any case, if
n
is greater than zero, it then stores a null character (usingcharT()
) 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/