我正在尝试编写一小段代码来响应箭头键。我知道 up 由 ^[[A] 表示,我有以下代码来检查该序列:
while( 1 )
{
input_char = fgetc( stdin );
if( input_char == EOF || input_char == 'n' )
{
break;
}
/* Escape sequence */
if( input_char == 27 )
{
input_char = getc( stdin );
if( input_char == '[' )
{
switch( getc( stdin ) )
{
case 'A':
printf("Move upn");
break;
}
}
}
}
每当我按"向上"时,转义序列 (^[[A) 都会出现在屏幕上,但在我按回车键之前不会出现"向上移动"。
最终目标是用其他一些数据替换当前行上的文本,所以我尝试这样做
printf("r%s", "New Text");
代替"上移",但在按下 Enter 之前它仍然不显示。
我阅读字符的方式有问题吗?
谢谢!
编辑 快速说明,它适用于 *nix 系统。
溶液谢谢大家的指点。我选择了stepanbujnak的解决方案,因为它相当简单。我注意到的一件事是,修改字符串(退格等)的键的许多行为与您预期的不同。它将通过在线的任何内容(包括 printf'd 的东西)退格,我必须考虑到这一点。在那之后,让其他人排队也不错:)
stdin
是行缓冲的,因此getc(stdin)
或fgetc(stdin)
在按 Enter 之前看不到这些字符 有关更多详细信息,请参阅此链接
编辑:如果您不想进入ncurses
还有其他有用的方法,例如将终端设置为原始模式等来克服此限制。检查这个不错的SO帖子
从标准输入中捕获字符,无需等待按回车
您实际上只需要使用 termios 禁用线路缓冲
下面是执行此操作的示例:
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
int main() {
struct termios old_term, new_term;
char c;
/* Get old terminal settings for further restoration */
tcgetattr(0, &old_term);
/* Copy the settings to the new value */
new_term = old_term;
/* Disable echo of the character and line buffering */
new_term.c_lflag &= (~ICANON & ~ECHO);
/* Set new settings to the terminal */
tcsetattr(0, TCSANOW, &new_term);
while ((c = getchar()) != 'q') {
printf("You pressed: %cn", c);
}
/* Restore old settings */
tcsetattr(0, TCSANOW, &old_term);
return 0;
}
查看用于捕获转义序列(如箭头键)的curses
库。
http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/keys.html
在大多数系统上,键(如箭头键、主页、向上翻页、中断等)是转义键,它们使用转义序列来辨别自己。 类似于 0x1B + Sequence,如果要捕获原始数据,则需要直接从文件描述符读取输入并侦听序列。 另一种方法是使用ncurses。
除了使用curses之外,下面说明了如何使用系统调用(例如read
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd = 0x0; /* STDIN */
size_t bytes_read;
char buf[12];
bytes_read = read(fd, buf, 3);
printf("%02x %02x %02xn", buf[0], buf[1], buf[2]);
return 0;
}
按 UP 后输出
Lukes-ASA-Macbook:tmp luke$ gcc -o out test.c
Lukes-ASA-Macbook:tmp luke$ ./out
^[[A
1b 5b 41
这应该让你上路。
您可以缓冲输入以查找0x1b
,然后启用分析标志以查找字符的转义序列,而不是单个字符分析。