我想在C中编写类似sgtpep/pmenu的应用程序。
然后我开始查看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();
答案 0 :(得分:1)
如果您要以这种方式从 stdin 切换到curses,则必须打开终端设备,例如,当您阅读完标准后,/dev/tty
输入。打开终端后,可以使用newterm
初始化curses(其中包含与initscr
不同的输入/输出流参数。)
例如,请参阅ncurses test-program或dialog。
答案 1 :(得分:0)
curses是stdin的替代品。
C模型是用户在控制台中编写一行,这为他提供了行编辑功能。他可以退格并使用箭头键在线上移动,直到他对它感到满意为止。然后他按下回车,程序得到整行。程序然后处理它,通常会提示下一行。
curses接管键盘以便它可以用作键盘 - 你可以有一个小的太空入侵者游戏,“z”表示“左”,“x”表示“右”。因此,您不应该同时尝试从stdin读取,您将获得字符,但是curses系统将以奇怪的方式与它们进行交互。通过诅咒独家阅读。
在上一个程序中,您读取的输入最多为EOF。因此,后续输入是EOF。