2017-03-16 69 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。