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

4
标题有误导性,因为我更感兴趣的是寻找一种替代解决方案。我的直觉是检查缓冲区是否为空不是最理想的解决方案(至少在我的情况下)。
我是C++ 的新手,并一直在使用 Bjarne Stroustrup 的《C++ 程序设计原理与实践》进行学习。我目前正在第七章,我们正在“改进”第六章的计算器。(我将把源代码的链接放在问题的末尾。)
基本上,计算器可以从用户那里接收多个输入,用分号分隔。
> 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天,我对编程的背景非常薄弱,所以有时甚至在搜索时也会感到困难。

1
用棍子戳一下,看它是否咆哮。 - Captain Obvlious
1
类似问题:https://dev59.com/CHA75IYBdhLWcg3wZ4Jr - M.M
在这种情况下,您可以使用std::getline一次读取整行,并在每行后显示提示符。 - M.M
“标题有误导性,因为我更感兴趣的是寻找替代解决方案。” - 你为什么要故意选择一个误导性的标题呢? - Christian Hackl
@ChristianHackl 我无法想出其他标题来同时有效地解决我所有的问题。(也不想太长)。虽然有些误导,但并非完全无关;我想知道如何检查缓冲区是否为空,只是因为我是C++新手,所以更喜欢知道另一种解决方案。 - spicypumpkin
1个回答

1
As you've discovered, this is a deceptively complicated task. This is because there are multiple issues here at play, both the C++ library, and the actual underlying file.
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中的下一个字符是什么。它可能是一个空格或换行符,在这种情况下,你将只从>>运算符中得到4。或者,下一个字符可能是'2',在这种情况下,>>将至少吞掉'42',可能还有更多数字。
你当然可以自己实现所有这些逻辑,查看底层的std::streambuf,并确定它是否满足即将进行的输入操作。恭喜:你刚刚重新发明了>>运算符。你最好自己一个字符一个字符地解析输入。
底层文件
你确定std::cin没有足够的输入来满足你的下一个输入操作。现在,你需要知道std::cin上是否有可用的输入。
现在,这变成了一个特定于操作系统的主题。这不再是标准C++库所涵盖的内容。

结论

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接