提问人:mavenor 提问时间:9/26/2021 最后编辑:mavenor 更新时间:10/7/2021 访问量:235
如何在 C++?... 下推广“clearerr()”
How would one generalise `clearerr()` under C++?…
问:
TL的;博士
我知道,如果一个程序侦听 EOF(例如)作为停止接受输入的符号,例如依靠条件,如 while (std::cin) {...}
,则需要调用 cin.clear()
才能再次读取标准输入(想知道更多信息的读者,请参阅此表)。^D
我最近了解到这是不够的,并且底层 C 文件描述符(包括 stdin
)需要运行 clearerr()
才能忘记 EOF 状态。
由于需要一个 C 样式的文件描述符,并且 C++ 主要使用 s 等操作(例如),我想通用一些代码(见下文)以在任何相关的 C 样式文件描述符上运行,即使它可能不是。clearerr()
std::basic_streambuf
cin
clearerr()
streambuf
stdin
编辑 (1&2):我想知道 stdin
是否是唯一行为如下的文件描述符(需要 clearerr()
才能运行)......?
如果不是,那么下面的代码应该结束泛化问题(zkoza 在他们的回答中指出的想法)
正如 zkoza 在下面的评论中指出的那样,从逻辑上讲,是唯一需要这种处理的文件描述符(即)。只需检查给定的 C++ 流是否真的附加到:stdin
clearerr()
*std::cin.rdbuf()
std::istream theStream /* some stream with some underlying streambuf */
if (theStream.rdbuf() == std::cin.rdbuf())
clearerr(stdin);
背景
我正在用 C++ 编写一个工具,我需要两次获取多行用户输入。
我知道有多种方法可以获取多行输入(例如等待双换行符),但我想使用 EOF 作为用户的信号,表明他们已经完成了——就像你或 .gpg -s
-e
经过多次咨询(这里、这里和 cppreference.com),我决定使用......(我引用第三个):
惯用的C++输入循环,例如 [...]
while(std::getline(stream, string)){...}
由于它们依赖于 std::basic_ios::operator bool
来完成它们的工作,因此我确保在第一个和第二个用户输入指令之间清除 cin.rdstate()(
使用 )。cin.clear()
我的代码要点如下:
std::istream& getlines (std::basic_istream<char> &theStream,
std::vector<std::string> &stack) {
std::ios::iostate current_mask (theStream.exceptions());
theStream.exceptions(std::ios::badbit);
std::string &_temp (*new std::string);
while (theStream) {
if (std::getline(theStream, _temp))
stack.push_back(_temp); // I'd really like the input broken...
// ... into a stack of `\n`-terminated...
// ... strings each time
}
// If `eofbit` is set, clear it
// ... since std::basic_istream::operator bool needs `goodbit`
if (theStream.eof())
theStream.clear(theStream.rdstate()
& (std::ios::failbit | std::ios::badbit));
// Here the logical AND with
// ... (failbit OR badbit) unsets eofbit
// std::getline sets failbit if nothing was extracted
if (theStream.fail() && !stack.size()) {
throw std::ios::failure("No input recieved!");
}
else if (theStream.fail() && stack.size()) {
theStream.clear(theStream.rdstate() & std::ios::badbit);
clearerr(stdin); // 👈 the part which I want to generalise
}
delete &_temp;
theStream.exceptions(current_mask);
return theStream;
}
答:
这将满足您的需求:
#include <iostream>
int main()
{
std::cin.sync_with_stdio(true);
char c = '1', d = '1';
std::cout << "Enter a char: \n";
std::cin >> c;
std::cout << (int)c << "\n";
std::cout << std::cin.eof() << "\n";
std::cin.clear();
clearerr(stdin);
std::cout << std::cin.eof() << "\n";
std::cout << "Enter another char: \n";
std::cin >> d;
std::cout << (int)d << "\n";
std::cout << std::cin.eof() << "\n";
}
它之所以有效,是因为默认情况下,C++ 与 C 绑定(因此,实际上不需要第一行)。您必须修改代码以检查流是否是,如果是,请执行std::cin
stdin
std::cin
clearerr(stdin);
编辑:
实际上,仅确保 C 和 C++ 接口之间的同步,但在内部,它们在相同的文件描述符上工作,这可能就是无论接口是否绑定的原因sync_with_stdio
clearerr(stdin);
sync_with_stdio
编辑2:这些能回答你的问题吗?从 std::fstream https://www.ginac.de/~kreckel/fileno/ 获取 FILE* ?
评论
std::istream&
std::cin
theStream.rdbuf() == std::cin.rdbuf()
clearerr()
的方法。现在我怀疑一个人会遇到另一个,而不是与那个同步的人需要......仍然喜欢概括 😅streambuf
stdin
clearerr()
stdin
clearerr()
clearerr()
std::streambuf
std::cin
cin
ctrl+C
ctrl+Z
ctrl+U
ctrl+W
ctrl+D
ctrl+D
评论
cin.clear()
clearerr(stdin)