setvbuf无法使stdin无缓冲

12

我的主要意图是使getchar在获取到字符后立即返回,而不是等待ENTER键。我尝试了以下方法:

int main()
{
    setvbuf(stdin,NULL,_IONBF,0);
    getchar();

    return 0;
}

将此与setvbuf的原型进行比较

setvbuf ( FILE * stream, char * buffer, int mode, size_t size );

它应该将 stdin 设置为无缓冲模式。

但是, getchar()仍然会等待 ENTER

我看过类似这样的相关帖子

在C语言中读取字符时打印

这些帖子提出了替代方法来使 stdin 无缓冲。 但我想知道为什么 setvbuf 方法不起作用


在流上进行任何“移动”之前,必须调用setvbuf()...因此,在main()中首先要做的事情就是调用它。 - pmg
@pmg 我更新了我的帖子以反映我尝试过的内容。但仍然不起作用。 - Pavan Manjunath
我认为问题不在于setvbuf()。我使用了你的程序,有使用和没有使用setvbuf()都尝试过了,行为不同。没有使用setvbuf()时,包括 ENTER 在内的所有字符都被消耗(即使是在键入 ENTER 后才消耗);使用setvbuf()时,只有第一个字符被消耗,其余字符被用作后续的 bash 命令。 - pmg
2个回答

21

终端驱动程序在你按下回车之前不会返回任何东西,即使read()操作可以接受已经存在的内容。

要从终端获取逐个字符输入,您必须将其从规范模式切换到原始模式或cbreak模式,并且这需要完全不同的操作。请参阅POSIX手册上的“通用终端接口”了解如何控制终端。或者考虑使用curses库。

另请参见:规范与非规范终端输入


setvbuf(stdin,NULL,_IONBF,0); 这样做应该没问题吧?我的意思是 setvbuf 对于所有文件指针都有效,但对于 stdin 却无效? - Pavan Manjunath
7
setvbuf()函数仅仅是告诉程序中的标准I/O库不使用缓冲区,而并不会对终端驱动程序产生影响。 - Jonathan Leffler

1

如果您正在Linux或其他类Unix系统下尝试此操作,那么是终端缓冲输入并仅传递整行。您可以使用ncurses来规避这个问题:

#include <ncurses.h>

int main()
{
    initscr();
    getch();
    endwin();

    return 0;
}

使用以下命令进行编译:

gcc -o main main.c -lncurses

谢谢回复。我看到了这些替代方法,但我很好奇为什么 setvbuf 不起作用。 - Pavan Manjunath

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