原始终端模式 – 如何接受输入?

我有一个聊天客户端,它以原始终端模式接收输入,但我不知道在这种模式下处理输入。 我需要知道两件事:

  • 如何逐个字符地读取输入并显示它? 我是否必须有某种读取循环,一次读取一个字符并将其存储在缓冲区中?
  • 如果我希望我的服务器处理新行条目的输入,我是否必须扫描每个字符进入我的缓冲区并查找\n

此外,在\n上刷新的逐个字符读取循环的例子真的很棒。 谢谢!

我建议使用GNU readline库 。 它负责获取输入线的繁琐工作,并允许用户使用退格键,左箭头和右箭头等编辑其行,并使用向上箭头调用旧命令,甚至使用^ R搜索旧命令, Readline安装了类似Linux的典型unix类发行版,但是如果你没有它,你可以在这里找到它

编辑:这是一个最小的readline示例:

 #include  #include  #include  int main(int argc, char ** argv) { while(1) { char * line = readline("> "); if(!line) break; if(*line) add_history(line); /* Do something with the line here */ } } 

使用gcc -o test test.c -lreadline -lncurses进行编译。

如果你不能使用readline,getline是另一种选择:

 #include  int main() { char * line = NULL; size_t len; while(getline(&line, &len, stdin) >= 0) printf("I got: %s", line); } 

如果即使getline是不可接受的,你也可以使用fgets。 它不会动态分配合适大小的缓冲区,因此会截断太长的行。 但至少它是标准C:

 #include  int main() { char buf[1000]; while(fgets(buf, sizeof(buf), stdin) printf("I got: %s, line); } 

在Windows中有一个非常有用的函数kbhit()但不幸的是在linux中没有。 可以有多种方法。 我们将为linux创建自己的kbhit()方法。 当在输入缓冲区中检测到某些内容时,kbhit()将返回非零值,否则它将返回0并传递。 简单来说,它是非阻塞的。 只要结果为true,则调用getch()方法获取该按下的键。

 #include  #include  #include  #include  #include  void changemode(int); int kbhit(void); int main(void) { int ch; changemode(1); while ( !kbhit() ); // Waiting for some keyboard input. // something has been detected. now get that. ch = getchar(); printf("\nGot %c\n", ch); changemode(0); return 0; } void changemode(int dir) { static struct termios oldt, newt; if ( dir == 1 ) { tcgetattr( STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~( ICANON | ECHO ); tcsetattr( STDIN_FILENO, TCSANOW, &newt); } else tcsetattr( STDIN_FILENO, TCSANOW, &oldt); } int kbhit (void) { struct timeval tv; fd_set rdfs; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&rdfs); FD_SET (STDIN_FILENO, &rdfs); select(STDIN_FILENO+1, &rdfs, NULL, NULL, &tv); return FD_ISSET(STDIN_FILENO, &rdfs); }