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)
,但这也行不通。
答案 0 :(得分:1)
在戴维斯的患者帮助下,我了解了用 Ctrl + D 完成的键入输入与我不知道的here文档之间的区别。 (我向戴维斯·鲱鱼致敬。)
一次,我明白了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()
是恕我直言。它将丢弃重新启用的标准输入的第一个字符,从而使随后的处理错误(不计算第一个字符)。
戴维斯(再次)做了一个简短但显而易见的解释,我用我的话说:
使用 Ctrl D ,标准输入将在下次尝试读取时收到EOF;并在其内部标志中存储它。但是,该标志可以重置。如果没有其他输入,则下一次读取尝试将失败,但否则,可以继续输入。
也许值得强调一下std::ios
中的内部EOF标志。如果没有std::cin.clear()
,则即使有更多输入可用,读取尝试也会失败。只要内部std::stream
标志不会处于良好状态,即使可能成功,也不会在较低级别上执行读取尝试。