gpt4 book ai didi

c - 非阻塞获取字符

转载 作者:IT王子 更新时间:2023-10-29 00:06:46 25 4
gpt4 key购买 nike

  • 平台:Linux 3.2.0 x86 (Debian 7)
  • 编译器:GCC 4.7.2 (Debian 4.7.2-5)

我正在编写一个函数,如果某个字符已经存在于标准输入中,它会从标准输入中读取单个字符。如果 stdin 为空,则该函数假定什么都不做并返回 -1。我用谷歌搜索了非阻塞输入并被指向 poll()select() .首先,我尝试使用 select() 但我无法让它工作,所以我尝试了 poll() 并得出了相同的结论。我不确定这些函数到底做了什么,但是根据我对 poll() 文档的理解,如果我这样调用它的话:

struct pollfd pollfds;
pollfds = STDIN_FILENO;
pollfds.events = POLLIN;
poll(pollfds, 1, 0);

if(pollfds.revents & POLLIN) 如果“可以无阻塞地读取除高优先级数据以外的数据”为真。但是在我的测试情况下 poll() 总是超时。我如何测试功能可能是问题所在,但我想要的功能正是我正在测试的。这是目前的功能和测试情况。

#include <poll.h>
#include <stdio.h>
#include <unistd.h>

int ngetc(char *c)
{
struct pollfd pollfds;
pollfds.fd = STDIN_FILENO;
pollfds.events = POLLIN;

poll(&pollfds, 1, 0);

if(pollfds.revents & POLLIN)
{
//Bonus points to the persons that can tell me if
//read() will change the value of '*c' if an error
//occurs during the read
read(STDIN_FILENO, c, 1);
return 0;
}
else return -1;
}

//Test Situation:
//Try to read a character left in stdin by an fgets() call
int main()
{
int ret = 0;
char c = 0;
char str[256];

//Make sure to enter more than 2 characters so that the excess
//is left in stdin by fgets()
fgets(str, 2, stdin);

ret = ngetc(&c);

printf("ret = %i\nc = %c\n", ret, c);

return 0;
}

最佳答案

你做的 IO 不正确,POSIX 手册和所有其他相关文档明确表示永远不要混合在 FILE * 和文件描述符上完成的 IO。你已经非常公然地违反了这条规则。之所以制定这条规则,是因为 FILE * 使用了 buffering,这意味着在调用 fgets 之后read 将没有任何东西可以获取,因为 fgets 已经将所有未决数据读入保存在 FILE * 结构中的缓冲区中。

因此,由于无法检查 ISO C IO 方法是否会阻塞,因此我们只能使用文件描述符。

因为我们知道 STDIN_FILENO 只是数字 0,所以我们可以使用

fcntl (0, F_SETFL, O_NONBLOCK);

这将把所有 read s 在文件描述符 0 到非阻塞模式,如果你想使用不同的文件描述符以便你可以单独留下 0 那么只需使用 dup复制它。

这样,你就可以远离poll完全并将 ngetc 实现为

ssize_t 
ngetc (char *c)
{
return read (0, c, 1);
}

或者更好的是,一个宏

#define ngetc(c) (read (0, (c), 1))

因此,您可以获得所需内容的简单实现。

编辑:如果您仍然担心终端缓冲输入,您可以随时更改终端的设置,请参阅 How to disable line buffering of input in xterm from program?有关如何执行此操作的更多信息。

编辑: 不能使用 fgetc 而不是 read 的原因与使用 fgets 将不起作用。当其中一个 FILE * IO 函数运行时,它会从关联的文件描述符中读取所有数据。但是一旦发生这种情况,poll 将永远不会返回,因为它正在等待一个始终为空的文件描述符,而 read 也会发生同样的事情。因此,我建议您遵循文档的建议,永远不要混合使用 streams(IO 使用 fgetsfgetc等)和文件描述符(使用readwrite等的IO)

关于c - 非阻塞获取字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20588002/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com