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

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

本文关键字:cin 缓冲区 是否 std 何检查 检查 C++      更新时间:2023-10-16

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

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

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

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

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

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

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

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

^你需要这个头文件。我想这是作者自己写的。

编辑:我确实在网上寻找了一些解决方案,但说实话,这些解决方案对我来说都没有任何意义。我学习C++已经4天了,而且我的编程背景很差,所以有时甚至在谷歌上搜索也有点困难。。

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

C++库

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

int n;
std::cin >> n;

假设完成此操作并结束时,n包含数字42。实际上,std::cin很可能只读取了两个字符"4"answers"2",但除此之外,std::cin流中还可以读取任何其他字符。剩下的字符存储在std::streambuf中,在实际读取底层文件之前,下一个输入操作将读取它们。

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

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

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

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

基础文件

您确定std::cin没有足够的输入来满足您的下一次输入操作。现在,您需要知道std::cin上是否有可用的输入。

这现在成为操作系统特定的主题。这不再包含在标准C++库中。

结论

这是可行的,但在所有实际情况下,最好的解决方案是使用特定于操作系统的方法,而不是C++输入流,并自己读取和缓冲输入。例如,在Linux上,经典的方法是将fd 0设置为非阻塞模式,这样read()就不会阻塞,要确定是否有可用的输入,只需尝试read()即可。如果你确实读到了一些内容,请将其放入缓冲区,稍后再查看。一旦您消耗了所有以前读取缓冲的输入,并且确实需要等待更多的输入被读取,那么poll()就是文件描述符,直到它出现为止。