Reuse std::cin after eating an EOF(吃完 EOF 后重用 std::cin)
问题描述
unix 命令 wc
有这个功能:
The unix command wc
has this functionality:
$ 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
输入标准输入的
键序列.然后 wc 能够获取这个 EOF
.
Each <EOF>
indicates a <C-d>
key sequence that enters an EOF
into stdin. wc is then able to pick up this EOF
.
我正在尝试用 C++ 实现它.一个常见的建议是 clear()
和 ignore()
的组合.
I'm trying to implement this in C++. A common suggestion is combination of clear()
and 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)
,它也不起作用.
I've also tried std::cin.peekg(std::cin.beg)
, which also does not work.
推荐答案
在 Davis 的耐心帮助下,我学会了用 Ctrl+D 完成的输入与输入的区别和一份我不知道的 here 文件.(我向戴维斯·赫林致敬.)
With the patient help of Davis, I learned the difference between typed input finished with Ctrl+D and a here document which I was not aware of. (My tribute to Davis Herring.)
有一次,我在 C++ 中得到了它,其余部分非常简单,就像我的 MCVE 中所示.
Once, I got it the rest in C++ was quite simple like shown in my 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 << "'!
";
return 0;
}
for (std::string buffer; std::getline(in, buffer); ++nLines);
std::cout << "File: '" << fileName << "', " << nLines << " counted.
";
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.
";
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
再次读取.
So, it's indeed the trick with std::cin.clear()
which resets the EOF flag in input stream and makes it possible to read again from the /dev/stdin
.
在 OP 的情况下,std::cin.在
恕我直言是错误的.它丢弃重新启用的标准输入的第一个字符,这使得以下处理出错(不计算第一个字符).std::cin.clear()
之后 ignore()
In the case of OP, the std::cin.ignore()
after std::cin.clear()
is IMHO wrong. It discards the first character of the re-enabled standard input which makes the following processing wrong (by not counting the first character).
Davis(再次)提供了一个简短但显而易见的解释,我用我的话来说:
Davis (again) prodived a short but obvious explanation which I give in my words:
使用CtrlD,标准输入在下一次尝试读取时收到一个EOF;并在其内部标志中记住它.然而,该标志可以被重置.如果没有任何进一步的输入,下一次读取尝试将失败,否则,输入可以继续.
With CtrlD, the standard input receives an EOF in the next attempt to read; and memorizes it in its internal flags. Nevertheless, the flag can be reset. If there isn't any further input the next read attempt would fail but otherwise, the input can just be continued.
也许,值得在 std::ios
中强调内部的 EOF 标志.没有 std::cin.clear()
,即使有更多输入可用,读取尝试也会失败.只要内部 std::stream
标志没有导致良好状态,即使可能成功,也不会在较低级别执行读取尝试.
May be, it's worth to emphasize the internal EOF flag in std::ios
. Without std::cin.clear()
, the read attempt would fail even when more input is available. As long as the internal std::stream
flags doesn't result in good state, no read attempt will be performed on lower level even though it might succeed.
这篇关于吃完 EOF 后重用 std::cin的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:吃完 EOF 后重用 std::cin
基础教程推荐
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 从 std::cin 读取密码 2021-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01