当我们尝试在文件中提取带有 istream::getline() 和 std::getline() 的 `eof` 字符的行时,实际发生了什么
What's actually happens when we try to extract line in file after which `eof` character is present with istream::getline() and std::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
Code-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-style char array
、istream::getline
和string
、std::getline
是不一样的。但我想知道到底发生了什么。
我猜测对于 string
、std::getline
,它会提取第 1 次、第 2 次的字符串,当它尝试提取第 3 次时它会看到 eof
,因此它会在之前提取eof
.
下次我们尝试提取它时,正好遇到 eof
所以它没有提取任何东西并设置 fail-bit
.
string str
没有被修改,所以当我们尝试打印它时,只会打印最后提取的字符串。
不知道我的想法对不对...
此外,关于 istream::getline()
、C-style char array
、
,我也无法提出任何此类案例
引用标准,第 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 节 Class 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_
那么,字符串版本发生了什么:
- 您提取了最后一个字符串。这会设置 eofbit,但不会设置 failbit
- 你又上线了
- getline构造哨兵
- 哨兵检查
is.good()
。这是错误的,因为设置了 eofbit
- 哨兵设置failbit并将其成员ok_设置为false
- getline 函数检查哨兵是否为真(运算符 bool)。这是假的
- 清除旧字符串之前的 getline 函数 returns
第 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 字符串版本总是存储一个 '[=33=]'
字符,即使它失败了。 std::string
版本没有,大概是因为如果您忘记检查故障位,它不会引入与 C 版本相同的内存安全问题。
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
Code-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-style char array
、istream::getline
和string
、std::getline
是不一样的。但我想知道到底发生了什么。
我猜测对于 string
、std::getline
,它会提取第 1 次、第 2 次的字符串,当它尝试提取第 3 次时它会看到 eof
,因此它会在之前提取eof
.
下次我们尝试提取它时,正好遇到 eof
所以它没有提取任何东西并设置 fail-bit
.
string str
没有被修改,所以当我们尝试打印它时,只会打印最后提取的字符串。
不知道我的想法对不对...
此外,关于 istream::getline()
、C-style char array
、
引用标准,第 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 节 Class 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 - 哨兵设置failbit并将其成员ok_设置为false
- getline 函数检查哨兵是否为真(运算符 bool)。这是假的
- 清除旧字符串之前的 getline 函数 returns
第 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 字符串版本总是存储一个 '[=33=]'
字符,即使它失败了。 std::string
版本没有,大概是因为如果您忘记检查故障位,它不会引入与 C 版本相同的内存安全问题。