unix命令wc具有以下功能:
$wc - - -
aaa bbb ccc<EOF>
0 3 11 -
aaa bbb ccc<EOF>
0 3 11 -
aaa bbb ccc<EOF>
0 3 11 -
0 9 33 total
每个< EOF>表示< C-d>将EOF输入stdin的键序列.然后wc能够拿起这个EOF.
我正试图在C中实现这一点.一个常见的建议是clear()和ignore()的组合.
char c;
while (std::cin >> c) { ... }
std::cin.clear();
std::cin.ignore();
while (std::cin >> c) { /* never executed */ }
我也试过std :: cin.peekg(std :: cin.beg),这也行不通.
解决方法:
在戴维斯的耐心帮助下,我了解了使用Ctrl D完成的输入输入与我不知道的此处文档之间的区别. (我向戴维斯鲱鱼致敬.)
有一次,我得到了它在C中的其余部分非常简单,如我的MCVE所示.
line-count.cc:
#include <fstream>
#include <iostream>
#include <string>
unsigned process(const std::string &fileName, std::istream &in)
{
unsigned nLines = 0;
if (in.bad()) {
std::cerr << "ERROR: Cannot open '" << fileName << "'!\n";
return 0;
}
for (std::string buffer; std::getline(in, buffer); ++nLines);
std::cout << "File: '" << fileName << "', " << nLines << " counted.\n";
return nLines;
}
int main(int argc, char **argv)
{
unsigned nLines = 0;
for (int i = 1; i < argc; ++i) {
const std::string arg = argv[i];
if (arg == "-") {
nLines += process(arg, std::cin);
std::cin.clear();
} else {
std::ifstream fIn(arg.c_str());
nLines += process(arg, fIn);
}
}
std::cout << "Total: " << nLines << " counted.\n";
return 0;
}
在cygwin64编译和测试:
$g++ -std=c++11 -o line-count line-count.cc
$./line-count line-count.cc - line-count.cc -
File: 'line-count.cc', 32 counted.
1
2
3
File: '-', 3 counted.
File: 'line-count.cc', 32 counted.
1
2
3
File: '-', 3 counted.
Total: 70 counted.
$
所以,它确实是std::cin.clear()
的技巧,它重置了输入流中的EOF标志,并且可以从/ dev / stdin再次读取.
在OP的情况下,在std :: cin.clear()之后的std::cin.ignore()
是恕我直言.它丢弃重新启用的标准输入的第一个字符,这使得以下处理错误(通过不计算第一个字符).
戴维斯(再次)提出了一个简短而明显的解释,我用我的话说:
使用CtrlD,标准输入在下次尝试读取时接收EOF;并将其记忆在其内部标志中.然而,标志可以重置.如果没有任何进一步的输入,则下一次读取尝试将失败,否则,输入可以继续.
可能是,值得强调std :: ios中的内部EOF标志.如果没有std::cin.clear()
,即使有更多输入,读取尝试也会失败.只要内部std :: stream标志不能产生良好状态,即使可能成功,也不会在较低级别执行读取尝试.