【问题标题】:C++ how to check if the std::cin buffer is emptyC ++如何检查std :: cin缓冲区是否为空
【发布时间】:2017-01-22 01:13:06
【问题描述】:

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

我是 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 天了,而且我的编程背景很薄,所以有时甚至谷歌搜索都有些困难..

【问题讨论】:

  • 用棍子戳它,看它是否咆哮。
  • 在这种情况下,您可以使用std::getline 一次读取整行,并在每行之后显示提示
  • “标题具有误导性,因为我对寻找替代解决方案更感兴趣。” - 为什么要故意选择具有误导性的标题?
  • @ChristianHackl 我不知道如何为我的问题命名,同时有效地解决我的所有观点。 (也不希望它太长)。尽管具有误导性,但并非完全无关紧要;我想知道如何检查缓冲区是否为空,只是 希望 知道替代解决方案,因为我是 C++ 新手。

标签: c++ cin


【解决方案1】:

正如您所发现的,这是一项看似复杂的任务。这是因为这里存在多个问题,包括 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 中的下一个字符是什么。它可以是空格或换行符,在这种情况下,您从 >> 运算符中得到的只是 4。或者,下一个字符可能是 '2',在这种情况下,>> 至少会吞下 '42' ,可能还有更多的数字。

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

基础文件

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

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

结论

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

【讨论】:

    猜你喜欢
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 2010-12-23
    • 1970-01-01
    • 2012-02-03
    • 1970-01-01
    • 2011-12-08
    • 2020-12-12
    相关资源
    最近更新 更多