C++ 如何检查 std::cin 缓冲区是否为空

C++ how to check if the std::cin buffer is empty

标题具有误导性,因为我对寻找替代解决方案更感兴趣。我的直觉是检查缓冲区是否为空并不是最理想的解决方案(至少在我的情况下)。

我是 C++ 的新手,一直在遵循 Bjarne Stroustrup 的使用 C++ 的编程原则和实践。我目前正在学习第 7 章,其中 "refining" 第 6 章的计算器。(我将在问题的末尾放置源代码的链接。)

基本上,计算器可以接受用户的多个输入,由 semi-colons 分隔。

> 5+2; 10*2; 5-1;
          = 7
>         = 20
>         = 4
> 

但我想去掉最后两个答案的提示字符('>'),只有在要求用户输入时才再次显示。我的第一直觉是找到一种方法来检查缓冲区是否为空,如果是,则计算字符,如果不是,则继续计算答案。但经过一番谷歌搜索后,我意识到这项任务并不像我最初想象的那么容易......而且这也许不是一个好主意。

我想我的问题本质上是如何在有多个输入时去掉最后两个答案的“>”字符。但是如果检查 cin 缓冲区 可能并且 不是 毕竟是一个坏主意,我很想知道如何去做。

源代码:https://gist.github.com/Spicy-Pumpkin/4187856492ccca1a24eaa741d7417675

Header 文件:http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h

^ 您需要这个 header 文件。估计是作者自己写的

编辑:我确实在网上寻找了一些解决方案,但老实说 none 对我来说很有意义。我学习 C++ 已经 4 天了,我的编程背景非常薄弱,所以有时甚至谷歌搜索都有点困难..

如您所见,这是一项看似复杂的任务。这是因为这里有多个问题,包括 C++ 库和实际的底层文件。

C++ 库

std::cin,和 C++ 输入流,使用一个中间缓冲区,std::streambuf。来自底层文件或交互式终端的输入不是逐个字符地读取,而是尽可能以中等大小的块读取。比方说:

int n;

std::cin >> n;

假设完成此操作后,n 包含数字 42。好吧,实际发生的情况是 std::cin 很可能不只读取两个字符,“4”和“2”,但是 std::cin 流中还有任何其他字符可用.剩余的字符存储在std::streambuf中,下一个输入操作将在实际读取底层文件之前读取它们。

同样有可能上面的 >> 实际上并没有从文件中读取任何内容,而是从 std::streambuf 中获取了 '4' 和 '2' 字符,即上次输入操作后留在那里。

可以检查底层 std::streambuf,并确定那里是否有任何未读内容。但这并不能真正帮助你。

如果您要执行上面的 >> 运算符,您会查看底层的 std::streambuf,并发现它包含一个字符“4”,这也没有告诉您很多。您需要知道 std::cin 中的下一个字符是什么。它可以是 space 或换行符,在这种情况下,您将从 >> 运算符得到的全部是 4。或者,下一个字符可能是“2”,在这种情况下 >> 将吞下至少“42”,可能还有更多数字。

你当然可以自己实现所有这些逻辑,查看底层std::streambuf,并确定它是否满足你即将进行的输入操作。恭喜:您刚刚重新发明了 >> 运算符。您也可以自己解析输入,一次一个字符。

底层文件

您确定 std::cin 没有足够的输入来满足您的下一个输入操作。现在,您需要知道 std::cin.

上的输入是否可用

这现在成为一个运营 system-specific 主题。这不再包含在标准 C++ 库中。

结论

这是可行的,但在所有实际情况下,这里最好的解决方案是使用操作 system-specific 方法,而不是 C++ 输入流,并自行读取和缓冲您的输入。例如在Linux上,经典的做法是将fd 0设置为non-blocking模式,这样read()就不会阻塞,判断是否有可用输入,只需尝试read()它。如果您确实阅读了某些内容,请将其放入缓冲区中,以便稍后查看。一旦你消耗了所有 previously-read 缓冲输入,你真的需要等待更多的输入被读取,poll() 文件描述符,直到它在那里。