我知道 C++ 流函数是建立在 C 的 stdio
库之上的。
我必须在 C 中做什么才能获得与 cin.ignore(n)
相同的结果?
例如,我应该使用 stdio
函数 fseek(stdin, n, 0)
还是 cin.ignore
使用的是其他方法?
最佳答案
不,没有。但是让我们看看幕后发生了什么cin.ignore()
.我们以llvm libcxx sources为例, 我发现它们比 gcc 的浏览起来更快。
extern istream cin;在 iostream 中,但它在应用程序启动时在 iostream.cpp 中初始化使用静态分配的缓冲区和 __stdoutbuf 对象构造自良好的“旧”FILE *
stdin
:
_ALIGNAS_TYPE (istream) char cin [sizeof(istream)];
ios_base::Init::Init() {
istream* cin_ptr = ::new(cin) istream(::new(__cin) __stdinbuf <char>(stdin) );
...
istream::ignore()
函数可以在 istraem 中找到.这很简单,首先我们检查用户是否想清除流中的所有字符或只是其中的一些字符 ( if (__n == numeric_limits<streamsize>::max())
)。然后函数调用this->rdbuf()->sbumpc()
在一个循环中预定义的计数数量(或者无限,如果 __n
等于 numeric_limits<steramsize::max()
)。我们可以找到sbumpc()
成为std::basic_streambuf
的成员, 来自 cppreference :
int_type sbumpc();
Reads one character and advances the input sequence by one character.
If the input sequence read position is not available, returns uflow(). Otherwise returns Traits::to_int_type(*gptr()).
所以我们可以简单地推导出this->rdbuf()
返回 __stdinbuf<char>(stdin)
的句柄.在cin::ignore
函数调用 __stdinbuf<char>(stdin)::sbumpc()
被制作了很多次,因为我们想要忽略的字符很多。所以让我们去sbumpc()
!先来看看streambuf :
int_type sbumpc() {
if (__ninp_ == __einp_)
return uflow();
return traits_type::to_int_type(*__ninp_++);
}
所以 if (__ninp_ == __einp_)
正在 streambuf
中做一些内部缓冲对象,不要打电话 uflow()
如果我们的缓冲区中已经有缓冲字符。 __ninp__
每次读取后指针都会递增,一定是这样。 uflow()
由 __stdinbuf : public basic_streambuf< .... >
重载, 来自 __std_stream :
template <class _CharT>
typename __stdinbuf<_CharT>::int_type
__stdinbuf<_CharT>::uflow()
{
return __getchar(true);
}
噗,我们去__getchar
并找出 true
是什么参数是。它就在 __std_stream 的正下方.
这是一个长函数,具有主要功能,负责一些缓冲。但是我们可以马上发现这个函数的核心:
template <class _CharT>
typename __stdinbuf<_CharT>::int_type
__stdinbuf<_CharT>::__getchar(bool __consume) {
....
int __c = getc(__file_);
if (__c == EOF)
return traits_type::eof();
...
}
让我们从头开始:
-
cin
是一个istraem
对象并从__stdinbuf<char>(stdin)
初始化 -
istream::ignore()
电话basic_streambuf::sbumpc()
预定义的次数,可能在使用stdin
初始化的对象上 -
basic_streambuf::sbumpc()
处理一些缓冲并调用 basic_streambuf::uflow()
如果缓冲区为空。 -
basic_streambuf::uflow()
由__stdinbuf::uflos()
重载并调用__stdinbuf::__getchar()
-
__sinbuf::__getchar()
电话getc(__file__)
所以可能getc(stdin)
从流中读取一个字符
总结一下:
void stdin_ignore(size_t n, int delim)
{
while (n--) {
const int c = getc(stdin);
if (c == EOF)
break;
if (delim != EOF && delim == c) {
break;
}
}
关于c++ - C 中的 cin.ignore() 等价于什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53037333/