2017-03-16 5 views
0

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がきれいでないと思われるので、fgetsの後にfflush(stdin)を使用しますが、同じ結果になります。

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

使用newterminout作品をリダイレクトします。

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は、実際には 'fgets'メソッドではなく、POSIXの' read'システムコールです。私はそれが問題のどこにあるとは思わない。問題は、端末が「rawモード」ではないということです。私は端末をrawモードに設定する方法を覚えていません。端末によって異なると思います.ncursesには、そのようなことを処理する初期化関数があります。 –

+0

print_menu()に "refresh()"が表示されません。 ncursesアプリケーションの作成の詳細については、こちらをご覧ください:http://invisible-island.net/ncurses/ncurses-intro.html – TonyB

+0

@TonyBありがとう!これはコピー&ペーストのエラーです...コード構造を変更して明確にしましたが、 'refresh()'の追加は忘れてしまいました。 – delta

答えて

1

あなたがそのように呪いに標準入力から切り替えるするつもりなら、あなたは、例えば、端末装置を開く必要があります、/dev/ttyあなたは標準入力を読み終わっています。ターミナルを開いたら、newterminitscrとは異なり、入出力ストリームのパラメータを持つ)を使ってcursesを初期化することができます。

たとえば、ncurses test-programまたはdialogを参照してください。

+0

ありがとう!プログラムをもう少し更新したので、cursesライブラリには関係しません。しかし、まだ問題は残っています。入力がパイプされている間に入力を得るのが間違っていますか? – delta

+0

ありがとうThomas!私はついにあなたが意味するものを得ました。 'newterm'は複数の端末がある場合に動作します。 – delta

+0

はい、そうですが、ほとんどの場合、このような状況で使用されます。 –

-1

cursesはstdinの代替品です。

Cモデルは、ユーザーがコンソールにラインを作成することで、ライン編集機能を提供します。彼はそれを喜ぶまで、矢印キーをバックスペースにして使用することができます。そして、彼は入力を押し、プログラムは行全体を取得します。プログラムはそれを処理し、通常、次の行の入力を求めます。

cursesはキーパッドとして使用できるようにキーボードを引き継ぎます。「z」は「left」を意味し、「x」は「right」を意味する小さなスペース侵略ゲームを持つことができます。したがって、stdinから同時に読み込もうとするべきではありません。あなたは文字を取得しますが、cursesシステムはそれらと奇妙なやり方で対話します。排他的に呪いを読む。

最後のプログラムでは、EOFまで入力を読み込みます。したがって、その後の入力はEOFです。

関連する問題