我正在尝试编写一个简单的小代码片段来响应箭头按键。 我知道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 up\n");
break;
}
}
}
}
每当我点击“向上”时,转义序列(^ [[A]会出现在屏幕上,但在我按下回车之前不会出现“向上移动”)。
最终目标是将当前行上的文本替换为其他一些数据,因此我尝试了
printf("\r%s", "New Text");
取代“向上移动”,但在按下输入后仍然不显示。
我在读字的方式有问题吗?
谢谢!
编辑快速说明,它适用于* nix系统。
的解 的 感谢大家的指点。我选择了stepanbujnak的解决方案,因为它非常简单。我注意到的一件事是修改字符串(退格等)的键的很多行为与你期望的不同。它会在线上退出任何东西(包括printf'd的东西),我不得不考虑到这一点。在那之后,让其他人排成一行并不太糟糕:)
答案 0 :(得分:10)
stdin
是行缓冲的,因此getc(stdin)
或fgetc(stdin)
无法看到这些字符,直到您按 ENTER 查看此link了解更多详情
编辑:如果您不想进入ncurses
,还有其他有用的方法,例如将终端设置为原始模式等来克服此限制。检查这个好的SO帖子
Capture characters from standard input without waiting for enter to be pressed
答案 1 :(得分:3)
您实际上只需要使用 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: %c\n", c);
}
/* Restore old settings */
tcsetattr(0, TCSANOW, &old_term);
return 0;
}
答案 2 :(得分:1)
查看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 %02x\n", 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
,然后启用解析标志以查找转义字符序列,而不是单个字符解析。