为什么 std::ios_base::ignore() 设置 EOF 位?
Why does std::ios_base::ignore() set the EOF bit?
当我从一个流中读取所有数据,但没有尝试读取它的末尾时,没有设置该流的 EOF。这就是 C++ 流的工作方式,对吧?这就是它起作用的原因:
#include <sstream>
#include <cassert>
char buf[255];
int main()
{
std::stringstream ss("abcdef");
ss.read(buf, 6);
assert(!ss.eof());
assert(ss.tellg() == 6);
}
但是,如果我 ignore()
不是 read()
ing 数据,则设置 EOF:
#include <sstream>
#include <cassert>
int main()
{
std::stringstream ss("abcdef");
ss.ignore(6);
assert(!ss.eof()); // <-- FAILS
assert(ss.tellg() == 6); // <-- FAILS
}
这是在 GCC 4.8 和 GCC trunk (Coliru) 上。
它还有一个不幸的副作用,那就是 tellg()
return -1
(因为那是 tellg()
所做的),这让我很恼火做。
这个标准是强制性的吗?如果有,是哪一段以及为什么?为什么 ignore()
会尝试阅读比我告诉它的更多的内容?
我在 cppreference's ignore()
page 上找不到这种行为的任何原因。我可能可以 .seekg(6, std::ios::cur)
代替,对吧?但我还是想知道是怎么回事。
我认为这是一个 libstdc++ 错误 (42875, h/t NathanOliver)。 [istream.unformatted]中ignore()
的要求是:
Characters are extracted until any
of the following occurs:
— n != numeric_limits<streamsize>::max()
(18.3.2) and n
characters have been extracted so far
— end-of-file occurs on the input sequence (in which case the function calls setstate(eofbit)
,
which may throw ios_base::failure
(27.5.5.4));
— traits::eq_int_type(traits::to_int_type(c), delim)
for the next available input character
c (in which case c is extracted).
Remarks: The last condition will never occur if traits::eq_int_type(delim, traits::eof())
.
所以我们有两个条件(最后一个被忽略)——我们要么读取 n
个字符,要么在某个时候到达文件末尾,在这种情况下我们设置 eofbit
。但是,在这种情况下,我们能够从流中读取 n
个字符(实际上您的流中有 6 个字符),因此我们不会在输入序列上到达文件末尾。
在 libc++ 中,eof()
未设置,tellg()
设置 return 6.
当我从一个流中读取所有数据,但没有尝试读取它的末尾时,没有设置该流的 EOF。这就是 C++ 流的工作方式,对吧?这就是它起作用的原因:
#include <sstream>
#include <cassert>
char buf[255];
int main()
{
std::stringstream ss("abcdef");
ss.read(buf, 6);
assert(!ss.eof());
assert(ss.tellg() == 6);
}
但是,如果我 ignore()
不是 read()
ing 数据,则设置 EOF:
#include <sstream>
#include <cassert>
int main()
{
std::stringstream ss("abcdef");
ss.ignore(6);
assert(!ss.eof()); // <-- FAILS
assert(ss.tellg() == 6); // <-- FAILS
}
这是在 GCC 4.8 和 GCC trunk (Coliru) 上。
它还有一个不幸的副作用,那就是 tellg()
return -1
(因为那是 tellg()
所做的),这让我很恼火做。
这个标准是强制性的吗?如果有,是哪一段以及为什么?为什么 ignore()
会尝试阅读比我告诉它的更多的内容?
我在 cppreference's ignore()
page 上找不到这种行为的任何原因。我可能可以 .seekg(6, std::ios::cur)
代替,对吧?但我还是想知道是怎么回事。
我认为这是一个 libstdc++ 错误 (42875, h/t NathanOliver)。 [istream.unformatted]中ignore()
的要求是:
Characters are extracted until any of the following occurs:
—n != numeric_limits<streamsize>::max()
(18.3.2) andn
characters have been extracted so far
— end-of-file occurs on the input sequence (in which case the function callssetstate(eofbit)
, which may throwios_base::failure
(27.5.5.4));
—traits::eq_int_type(traits::to_int_type(c), delim)
for the next available input character c (in which case c is extracted).
Remarks: The last condition will never occur iftraits::eq_int_type(delim, traits::eof())
.
所以我们有两个条件(最后一个被忽略)——我们要么读取 n
个字符,要么在某个时候到达文件末尾,在这种情况下我们设置 eofbit
。但是,在这种情况下,我们能够从流中读取 n
个字符(实际上您的流中有 6 个字符),因此我们不会在输入序列上到达文件末尾。
在 libc++ 中,eof()
未设置,tellg()
设置 return 6.