我想写一个像sgtpep/pmenu在C的应用程序。如何正确读取C中的stdin?
然后我开始看看ncurses
库。我第一次尝试可以选择菜单。比如当我做ls | ./a.out
时,应该可以显示所有文件,并突出显示第一个,当我按UP或DOWN时,它会相应地改变高亮不同的项目。
完整的代码是here。
该程序没有收到任何按键。 mvprintw(n+1, 0, "%d\n", ch);
循环内总是打印-1
。
然后我删除无关的代码,并得到最小的例子。
#include <stdio.h>
char buf[100];
int main(int argc, char **argv) {
int ch;
while (fgets(buf, sizeof(buf), stdin)) puts(buf);
ch = getch();
printf("%d\n", ch);
ch = getch();
printf("%d\n", ch);
ch = getch();
printf("%d\n", ch);
ch = getch();
printf("%d\n", ch);
return 0;
}
ch
总是-1
。我怀疑stdin
不干净,所以我使用fflush(stdin)
后fgets
,但它的结果相同。
那么从stdin
读什么正确的方法?
UPD1
#include <stdio.h>
char buf[100];
int main(int argc, char **argv) {
int ch;
while (fgets(buf, sizeof(buf), stdin)) puts(buf);
fflush(stdin);
ch = getchar();
printf("%d\n", ch);
ch = getchar();
printf("%d\n", ch);
ch = getchar();
printf("%d\n", ch);
ch = getchar();
printf("%d\n", ch);
return 0;
}
我已经修改了程序,所以它是不相关的ncurses
了,但运行时ls | ./a.out
,ch
不断出现-1
。
UPD2
使用newterm
重定向in
和out
作品。
FILE *fd = fopen("/dev/tty", "r+");
set_term(newterm(NULL, fd, fd)); // instead of initscr()
noecho();
cbreak();
keypad(stdscr, TRUE);
print_menu(cur, n);
while (true) {
ch = getch();
if (ch == KEY_UP || ch == 'k') --cur;
else if (ch == KEY_DOWN || ch == 'j') ++cur;
cur = (cur + n) % n;
print_menu(cur, n);
}
endwin();
我怀疑这是一个ncurses问题,实际上并不是一个C问题。用于在POSIX系统上读取C的最低级API实际上不是C'fgets'方法,而是POSIX'read'系统调用。不过,我认为这不是问题所在。我认为问题是终端不处于“原始模式”。我不记得如何将终端设置为原始模式,我认为这取决于终端,我非常确定ncurses有一个初始化函数来处理这种事情。 –
我在print_menu()中看不到“refresh()”。有关编写ncurses应用程序的详细信息,请看这里:http://invisible-island.net/ncurses/ncurses-intro.html – TonyB
@TonyB谢谢!这是一个复制和粘贴错误...我改变了代码结构来清除它,但忘记添加'refresh()'。 – delta