【问题标题】:How to tell if fgets(stdin) will block on Windows?如何判断 fgets(stdin) 是否会在 Windows 上阻塞?
【发布时间】:2019-04-01 17:20:51
【问题描述】:

我如何判断下一次对fgets(stdin, ...) 的调用是否会阻塞?换句话说,我如何判断stdin 缓冲区是否有换行符等待读取?

在 Unix 上,我知道我可以像这样使用 select()

    fd_set reads;
    FD_ZERO(&reads);
    FD_SET(fileno(stdin), &reads);
    int s = select(fileno(stdin)+1, &reads, 0, 0, 0);
    if (s) {
        //fgets is ready
    }

但是,Windows 上的select() 仅适用于套接字,不适用于“stdin”,因此我无法使用它。

我还知道在 Unix 上我可以使用 poll()ioctl(0, I_NREAD...),可能还有很多其他解决方案。这些都不适用于 Windows。

我试过kbhit()WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), ))。问题是这两个都表明只要敲击第一个键就可以输入。我需要知道整行是否可用,因为fgets() 会阻塞整行。

也许我的问题是 Unix shell 倾向于缓冲整个输入行,而 Windows 没有?

我应该只使用fgetc() 建立一个缓冲区,直到我看到换行符吗?

我进行了研究以寻找其他答案,但没有一个对我有用。他们要么使用 C++,而我需要 C 解决方案。或者他们专注于将fgets() 与套接字一起使用,而我需要将其与stdin 一起使用。

非常感谢任何帮助。谢谢!

【问题讨论】:

  • 在 Linux 上,学习更喜欢 poll(2) 而不是旧的 select(2)...顺便说一句,fileno(stdin) 可以替换为 STDIN_FILENO,恰好是 0。此外,在病理情况下 @ 987654341@ 或 poll 会告诉你标准输入是可读的,但 fgets 仍然可以阻塞
  • 考虑在 Linux 上使用 GNU readline。它已在Readline-GW 中移植到 Windows
  • 感谢 cmets,但我真的想在 Windows 上执行此操作。我也不能引入依赖项,但我会在以后的项目中记住这一点。
  • 由于Readline-GW是免费软件,你可以研究它的源代码

标签: c windows io console-application


【解决方案1】:

如何判断下一次对fgets(stdin, ...) 的调用是否会阻塞?换句话说,我如何判断stdin 缓冲区是否有换行符等待读取?

一般来说,你无法分辨。也不在 POSIX 系统上,不做一些假设。 POSIX 和 Windows API 都定义了用于确定输入是否可用的机制,但这对您来说还不够。您想确定是否可以读取特定数据(即行终止符),而 C 定义的唯一方法是读取数据。

因此,如果您确实需要一次读取一行而不阻塞主线程,那么我建议您异步执行读取。您可以自己滚动,使用与主线程分开的阅读器线程,但您可能会发现Microsoft's existing asynchronous I/O API 支持您的需求。

【讨论】:

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