Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C-如何在没有缓冲的情况下轮询()输入?_C_Io_Buffer_Stdin - Fatal编程技术网

C-如何在没有缓冲的情况下轮询()输入?

C-如何在没有缓冲的情况下轮询()输入?,c,io,buffer,stdin,C,Io,Buffer,Stdin,我试图检测任何输入到stdin的字符(没有换行符) 我试过: setvbuf(stdin, NULL, _IONBF); //This returns 0 struct pollfd pfd = {STDIN_FILENO, POLLIN}; while (!poll(pfd, 1, ms)) { /* do some thing, e.g. printf("n\n"); */ } 当我键入q时,它似乎并没有停止打印,但在我按enter键后它确实停止了打印。我正在使用的系统是arch l

我试图检测任何输入到stdin的字符(没有换行符)

我试过:

setvbuf(stdin, NULL, _IONBF); //This returns 0
struct pollfd pfd = {STDIN_FILENO, POLLIN};

while (!poll(pfd, 1, ms)) {
  /* do some thing, e.g. printf("n\n"); */
}

当我键入q时,它似乎并没有停止打印,但在我按enter键后它确实停止了打印。我正在使用的系统是arch linux,编译器是gcc。

内核的TTY层驱动程序/缓冲区中的
q
被挂起,因为它处于“熟”模式

在这种模式下,只有当驱动程序看到换行符时,才会向应用程序返回某些内容。然后它返回:
q\n
(即
q

要让它在任何字符上立即返回,必须使用
ioctl
调用将TTY层置于“原始”模式

您需要使用[推荐]的
termios
调用:
tcgetattr
tcsetattr


更新:


ioctl单独起作用吗?哪个命令对应将终端更改为原始模式

查看
人工术语
。它有关于如何设置原始模式(手册页中称为“非规范”模式)的完整文档

我已经有一段时间没有这样做了,但这里有一个骨架函数

虽然函数在最后恢复原始状态,但您可能希望在程序启动时设置一次非规范模式

但是,对于程序中需要常规行编辑的其他部分,您必须自己处理所有行编辑(例如,支持退格等)

#include <termios.h>
#include <unistd.h>

void
change_tty(int fd)
{
    struct termios orig;
    struct termios raw;

    // get original cooked/canonical mode values
    tcgetattr(fd,&orig);

    // set options for raw mode
    raw = orig;
#if 0
    raw.c_lflag &= ~ICANON;
    raw.c_cc[VMIN] = ...
    raw.c_cc[VTIME] = ...
#else
    cfmakeraw(&raw);
#endif

    // put unit into raw mode ...
    tcsetattr(fd,TCSANOW,&raw);

    // do stuff in raw mode ...

    // restore original mode
    tcsetattr(fd,TCSANOW,&orig);
}
#包括
#包括
无效的
更改时间(int fd)
{
结构术语来源;
结构termios raw;
//获取原始烹调/规范模式值
tcgetattr(fd和orig);
//设置原始模式的选项
原始=原始;
#如果0
原始c_lflag&=~ICANON;
原始.c_cc[VMIN]=。。。
原始.c_cc[VTIME]=。。。
#否则
cfmakeraw(&raw);
#恩迪夫
//将设备置于原始模式。。。
tcsetattr(fd、TCSANOW和raw);
//在原始模式下做一些事情。。。
//恢复原始模式
tcsetattr(fd、TCSANOW和orig);
}

内核的TTY层驱动程序/缓冲区中的
q
被挂起,因为它处于“煮熟”模式

在这种模式下,只有当驱动程序看到换行符时,才会向应用程序返回某些内容。然后它返回:
q\n
(即
q

要让它在任何字符上立即返回,必须使用
ioctl
调用将TTY层置于“原始”模式

您需要使用[推荐]的
termios
调用:
tcgetattr
tcsetattr


更新:


ioctl单独起作用吗?哪个命令对应将终端更改为原始模式

查看
人工术语
。它有关于如何设置原始模式(手册页中称为“非规范”模式)的完整文档

我已经有一段时间没有这样做了,但这里有一个骨架函数

虽然函数在最后恢复原始状态,但您可能希望在程序启动时设置一次非规范模式

但是,对于程序中需要常规行编辑的其他部分,您必须自己处理所有行编辑(例如,支持退格等)

#include <termios.h>
#include <unistd.h>

void
change_tty(int fd)
{
    struct termios orig;
    struct termios raw;

    // get original cooked/canonical mode values
    tcgetattr(fd,&orig);

    // set options for raw mode
    raw = orig;
#if 0
    raw.c_lflag &= ~ICANON;
    raw.c_cc[VMIN] = ...
    raw.c_cc[VTIME] = ...
#else
    cfmakeraw(&raw);
#endif

    // put unit into raw mode ...
    tcsetattr(fd,TCSANOW,&raw);

    // do stuff in raw mode ...

    // restore original mode
    tcsetattr(fd,TCSANOW,&orig);
}
#包括
#包括
无效的
更改时间(int fd)
{
结构术语来源;
结构termios raw;
//获取原始烹调/规范模式值
tcgetattr(fd和orig);
//设置原始模式的选项
原始=原始;
#如果0
原始c_lflag&=~ICANON;
原始.c_cc[VMIN]=。。。
原始.c_cc[VTIME]=。。。
#否则
cfmakeraw(&raw);
#恩迪夫
//将设备置于原始模式。。。
tcsetattr(fd、TCSANOW和raw);
//在原始模式下做一些事情。。。
//恢复原始模式
tcsetattr(fd、TCSANOW和orig);
}

这对我有效,但可能取决于您的系统/终端

#include <stdio.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>

int main() {
    int i = 0;
    struct termios ts;
    tcgetattr(0, &ts);
    ts.c_lflag &= ~ICANON;
    tcsetattr(0, TCSANOW, &ts);
    while (!ioctl(0, FIONREAD, &i) && !i) {
        printf("x");
        fflush(stdout);
        sync();
        usleep(100);
    }
    printf("\n");
    return 0;
}
#包括
#包括
#包括
#包括
int main(){
int i=0;
结构术语;
tcgetattr(0和ts);
ts.c_lflag&=~ICANON;
tcsetattr(0、TCSANOW和ts);
而(!ioctl(0,FIONREAD,&i)和&!i){
printf(“x”);
fflush(stdout);
sync();
usleep(100);
}
printf(“\n”);
返回0;
}
克雷格真的为你回答了这个问题。我只是好奇地找到了一个实现。ioctl(0,FIONREAD,&i)获取缓冲区中的字符数并将其放入i。termios和ioctl_tty的手册页包含了提出此解决方案所需的所有详细信息


不过,老实说,如果您想让这样的东西具有交互性,ncurses会让它变得更简单。

这对我来说很有效,但可能取决于您的系统/终端

#include <stdio.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>

int main() {
    int i = 0;
    struct termios ts;
    tcgetattr(0, &ts);
    ts.c_lflag &= ~ICANON;
    tcsetattr(0, TCSANOW, &ts);
    while (!ioctl(0, FIONREAD, &i) && !i) {
        printf("x");
        fflush(stdout);
        sync();
        usleep(100);
    }
    printf("\n");
    return 0;
}
#包括
#包括
#包括
#包括
int main(){
int i=0;
结构术语;
tcgetattr(0和ts);
ts.c_lflag&=~ICANON;
tcsetattr(0、TCSANOW和ts);
而(!ioctl(0,FIONREAD,&i)和&!i){
printf(“x”);
fflush(stdout);
sync();
usleep(100);
}
printf(“\n”);
返回0;
}
克雷格真的为你回答了这个问题。我只是好奇地找到了一个实现。ioctl(0,FIONREAD,&i)获取缓冲区中的字符数并将其放入i。termios和ioctl_tty的手册页包含了提出此解决方案所需的所有详细信息


老实说,如果你想让这样的东西具有交互性,ncurses会让它变得更简单。

“尝试使用setvbuf(stdin,NULL,_IONBF)然后poll(…)”-->Post这段代码,@chux我认为这很明显,但我现在确实让它更完整了。当代码不能按预期工作时,早期调试是检查函数的返回值,如
int setvbuf()
。它是否为您返回了0?由于
poll()
不是标准的C语言,所以对像Linux一样使用的扩展进行post/tag?返回什么?@chux是的,setvbuf返回0,应该可以。poll在不“enter”时返回0。“尝试使用setvbuf(stdin,NULL,_IONBF)然后poll(…)”-->发布该代码,a@chux我认为这很明显,b