2017-03-16 155 views
0

我想写一个像sgtpep/pmenu在C的应用程序。如何正确读取C中的stdin?

然后我开始看看ncurses库。我第一次尝试可以选择菜单。比如当我做ls | ./a.out时,应该可以显示所有文件,并突出显示第一个,当我按UPDOWN时,它会相应地改变高亮不同的项目。

完整的代码是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.outch不断出现-1


UPD2

使用newterm重定向inout作品。

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

我怀疑这是一个ncurses问题,实际上并不是一个C问题。用于在POSIX系统上读取C的最低级API实际上不是C'fgets'方法,而是POSIX'read'系统调用。不过,我认为这不是问题所在。我认为问题是终端不处于“原始模式”。我不记得如何将终端设置为原始模式,我认为这取决于终端,我非常确定ncurses有一个初始化函数来处理这种事情。 –

+0

我在print_menu()中看不到“refresh()”。有关编写ncurses应用程序的详细信息,请看这里:http://invisible-island.net/ncurses/ncurses-intro.html – TonyB

+0

@TonyB谢谢!这是一个复制和粘贴错误...我改变了代码结构来清除它,但忘记添加'refresh()'。 – delta

回答

1

如果你打算从标准输入切换以这种方式来诅咒,你就必须打开终端设备,例如,/dev/tty当你读完标准输入。打开终端后,您可以使用newterm(与initscr不同,它具有输入/输出流的参数)初始化诅咒。

例如,请参阅ncurses test-programdialog

+0

谢谢!我已经更新了一些程序,所以它与curses lib无关。但问题依然存在。我在输入输入时获取输入的方式错误吗? – delta

+0

谢谢Thomas!我终于明白你的意思了。当有多个终端时,'newterm'有效。 – delta

+0

是的,尽管它主要用于这种情况。 –

-1

curses是stdin的替代品。

C模型是用户在控制台中编写一行,这使他具有行编辑功能。他可以退格并使用箭头键在线上移动,直到他满意为止。然后他按下输入键,程序就可以看到整条线。程序然后处理它,通常会提示下一行。诅咒接管键盘,使它可以用作键盘 - 你可以有一个空间入侵者游戏与“z”意思是“左”和“x”意思是“正确的”。因此,你不应该试图同时从stdin读取,你会得到角色,但是curses系统会以奇怪的方式与它们交互。通过curses完全阅读。

在上一个程序中,您将输入读入EOF。因此后续输入是EOF。