C++ 我怎样才能冲水?(环境:Mingw编译器,在xterm或Cygwin的mintty中运行)

C++ 我怎样才能冲水?(环境:Mingw编译器,在xterm或Cygwin的mintty中运行),c++,windows,cygwin,C++,Windows,Cygwin,我知道有两种方法可以刷新stdin: (一) (二) 但是,在我的环境中: Compiler: MinGW g++ Running in: Windows, Cygwin xterm or Cygwin mintty 它们都不起作用 我能做什么 注意:FlushConsoleInputBuffer()如果我的程序在dos提示窗口下运行,则可以工作。此外,FlushConsoleInputBuffer()在Cygwin xterm或mintty上运行时,很好地返回false --更新-- 我怀

我知道有两种方法可以刷新stdin:

(一) (二)

但是,在我的环境中:

Compiler: MinGW  g++
Running in: Windows, Cygwin xterm or Cygwin mintty
它们都不起作用

我能做什么

注意:
FlushConsoleInputBuffer()
如果我的程序在dos提示窗口下运行,则可以工作。此外,
FlushConsoleInputBuffer()
在Cygwin xterm或mintty上运行时,很好地返回false

--更新--

我怀疑Cygwin与Windows本机stdin分开处理stdin,后者会导致
FlushConsoleInputBuffer()
失败

@沃利克:是的“刷新”意味着删除所有未读的缓冲输入

--更新--(接受最终答案并说明原因)


托尼·D是对的。问题在于Cygwin终端是一个类似unix的终端,它允许在按下“ENTER”键之前进行编辑。因此,任何部分输入都必须缓冲,并且在按下“ENTER”键之前决不会传递给stdin,因为它需要编辑命令。我想应该可以通过将终端设置为原始模式(未经实验)来克服这一问题。但在原始模式下,编辑功能将丢失。

fflush
用于输出流。
fflush(stdin)
的行为未定义。看

如果使用
std::cin
访问
stdin
,则可以使用忽略流的内容,最多忽略给定数量的字符或给定的字符

例如:

// Ignore the rest of the line.
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

工作代码:

仅使用C++标准库功能不支持仅对当前缓冲/可用的数据进行代码丢弃> STDIN < /代码>。 大多数情况下,程序员只是(参见该页底部的示例)处理问题行的其余部分,然后尝试下一个缓冲行。如果您担心可能会有很多问题行-例如,用户可能已经剪切并粘贴了您想要丢弃的无意义页面,但如果您确实想让他们有机会输入更多行,则需要使用操作系统特定的函数来确定读取

stdin
时会被阻止。然后,您将
忽略
行,直到该阻塞条件为

select
poll
这两种操作在大多数操作系统上都适用,但从内存来看,它们仅为Windows上的套接字流定义,因此对您没有任何用处。Cygwin可能会也可能不会以某种方式支持他们;如果您想尝试,只要
stdin
文件描述符(0)测试可读,您就可以
忽略
行。你会发现许多其他问答讨论如何查看是否有可用的输入:例如

请记住,在按ENTER键之前,您的终端程序可能会在内部缓冲您键入的内容,因此您的程序最多只能清除前面的行,而不能清除用户部分键入的行(尽管您可以使用一些启发式方法在发送到程序的
stdin
后丢弃它)

更新

在某些情况下可能足够好的粗糙替代品:

  • 节省时间,然后循环调用
    getline(std::cin,my_string)
    ,直到失败(例如
    stdin上的EOF
    ),或者读取之间的时间大于某个阈值(比如半秒);这样,它可能会消耗已经缓冲但不需要的输入,但在丢弃循环终止后,可能会输入进一步的手写用户输入:您可以提示ala
    std::cout>>“已丢弃的错误输入-如果输入缓冲区包含不需要的文本,您可以按^U清除输入缓冲区…\n”
    Control-U
    适用于许多终端,但请检查您自己的终端)

  • 有一个特定的字符串,如say
    “--reset--”
    ,用户知道可以键入该字符串来停止丢弃行并切换回处理将来的行


  • fscanf
    错误,如果输入仅包含换行符,它将不会刷新,因为
    %[
    失败。更换需要
    int c;
    @MattMcNabb,是的。只有当缓冲输入仅包含一行时,这两种解决方案才有效。如果未读输入超过一行,或没有行尾,则无法工作。刷新指的是“删除程序尚未读取的所有发送的输入”,对吗?您尝试过同时执行1和2吗?如果所有其他操作都失败,您可以创建一个额外的线程,该线程立即读取所有输入并将其缓冲到程序的其余部分。然后您可以轻松添加“放弃所有当前读取的输入”函数…@hyde 1或2都不起作用。额外的线程读取输入可能可以解决问题,但最后一次读取(将被阻止,等待下一次输入)将需要超时和中止,以模拟丢弃函数。这不是一种优雅的方式,但应该可以工作(以及“如何中止stdin读取”)可能还是个问题。)我的评论的意思是,东西被缓冲在两个地方。首先,操作系统中有缓冲区,用于存储应用程序尚未读取的内容。然后是标准库中的缓冲区,其中可能有更多数据(几个击键或行),而不是应用程序代码实际读取的内容。您需要放弃这两种方法中的所有内容。关于线程方法,它不需要超时才能刷新,因为主线程可以放弃缓冲区。输入线程只会阻止读取,并添加到缓冲区(显然,这需要线程安全)实际上,对于这个目的来说,超时可能是有用的(但是一个链接的问题似乎有解决办法)。我知道它不被C++支持,这就是为什么我提到Windows API:<代码> bool FlushConsoleInputBuffer(yin in句柄HCONSOLITEN)。我是专门为Windows Cygwin Xterm/mintty而设计的。不过,如果是命令p,它确实可以工作
    while ( (c = fgetc(stdin)) != '\n' && c != EOF);