检测按键输入

6

我需要检测按键,但不需要用户按下回车键。最优雅的方法是什么?

例如,如果用户按下字母 Q,而不按下 enter,程序会执行某些操作。


3
那取决于环境。这是 Windows 平台的按键窗口消息吗?Linux 控制台可以尝试使用 getch,或者使用 ncurses 库。还是 Linux 的 Gnome/KDE 环境?或是 Java 应用程序? - Rup
它被标记和命名为C,所以我认为它可能是Windows、Linux或GTK。 - alternative
1
尝试在Mac OS X上使用setvbuffcntl的组合来实现这一点后,我现在很想去阅读ncurses源代码了... - dmckee --- ex-moderator kitten
@mathepic,也可能是嵌入式系统,所以将uC/OS-II、iTRON和其他许多系统添加到列表中;-) - RBerteig
它是基于Linux的,具体来说是Ubuntu。 - Dominic Bou-Samra
3个回答

7
在Unix/Posix中,标准的做法是使用tcsetattr将输入设置为非规范模式:
#include <termios.h>
#include <unistd.h>
    :
struct termios attr;
tcgetattr(0, &attr);
attr.c_lflag &= ~ICANON;
tcsetattr(0, TCSANOW, &attr);

请参阅termios(3)手册以获取更多详细信息(可能比您想知道的信息还要多)。

3
在Windows中,<conio.h>提供了函数_getch(void),可以用于读取按键而不会回显它们(如果需要,可以自己打印)。
#include <conio.h>
#include <stdio.h>

int main( void )
{
   int ch;

   puts( "Type '@' to exit : " );
   do
   {
      ch = _getch();
      _putch( ch );
   } while( ch != '@' );

   _putch( '\r' );    // Carriage return
   _putch( '\n' );    // Line feed  
}

这里不需要 #include <stdio.h>,我想。 - alternative

1

据我所知,除了使用像 ncurses 这样的库提供的 getch(void) 函数之外,没有好的可移植方法来实现这一点。

注意:从 stdio.h 中调用的 getchar(void) 函数似乎会等待直到按下回车键,然后再将字符传递给您,因此它无法起作用。


2
是的,但您可以使用raw()/cbreak()关闭行缓冲,从而允许字符立即返回程序。有关更多信息,请参见http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/init.html#RAWCBREAK。 - brennie
我提到的是 getchar,而不是 ncurses 函数 getch。如果他仔细阅读 ncurses 和 raw mode,getch 就可以正常工作,但 getchar 不行。 - alternative
在*nix系统中,如果stdin连接到tty,则默认为行缓冲,如果是文件或管道,则完全缓冲。如果它是tty,则可以对其模式进行操作,但这通常与stdio交互不良。ncurses知道如何以某种平台无关的方式执行此操作。 - RBerteig
@RBerteig:行缓冲、无缓冲和全缓冲只对stdio输出有影响,对输入没有影响。 - Chris Dodd
@Chris,我们最终都是正确的,但我在细节上错了。终端输入几乎肯定是行缓冲的,但由tty设备驱动程序而不是stdio完成缓冲,这将影响read(2)以及任何构建在其上的库,如stdio。您确实需要礼貌地要求tty驱动程序停止缓冲,这种方法不太便携(甚至不能跨越各种*nix变体,更不用说Windows),以获取单个按键。 - RBerteig
@RBerteig:termios 在任何不到 20 年的 *nix 变种上都应该能正常工作... - Chris Dodd

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