2009-08-14 8 views
3

私はコンソールからのユーザー入力を受け取り、別のスレッドでプリントアウトするプログラムに取り組んでいます。私は、ユーザーが途中で何かを入力してprintfが来て、カーソルでそれ自身を印刷する状況を避けたい。ノンブロッキングstdio

コンソールウィンドウからcで非ブロッキングioを実行する方法はありますか?理想的には、ユーザーが入力した内容が画面に表示されないように、キーの押下などをキャプチャします。私はUbuntuで開発していますが、ncursesのようなものを使う必要がなければ最高です。ここで

答えて

2

は(と私は個人的にそれをテストしていない)an HP forumから直接取られ、Cからのエコーをオフにする方法の例です:

オーケー、これはエコーをオフにする簡単な例 次のようになります。

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <termios.h> 

#define STDIN_FDES 0 

struct termios save; 

int main(int argc, char *argv[]) 
{ 
int cc = 0; 
char s_tmp[80],*p = NULL; 
struct termios work; 

cc = tcgetattr(STDIN_FDES,&save); 
work = save; 
work.c_lflag &= ~(ECHO); 
cc = tcsetattr(STDIN_FDES,TCSANOW,&work); 
(void) printf("\nEnter value: "); 
(void) fflush(stdout); 
p = fgets(s_tmp,sizeof(s_tmp),stdin); 
if (p != NULL) (void) printf("Out -> %s\n",p); 
cc = tcsetattr(STDIN_FDES,TCSANOW,&save); 
return(cc); 
} 

注:あなたがSIGINT、SIGTERM 、...をキャッチし、元のtermiosを使用して、端末 をリセットするシグナルハンドラを持っている ことが非常に重要であるため、 最後のtcsetattr()が勝利し、 というプロセスが単に端末デバイスに適用されます。 エコーをオフにしてプロセスを終了すると、シェル内ではオフになります 。

そうでなければ、Bashが適切な方法であれば、明らかにstty -echoを実行できます。

if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { 
    /* handle error */ 
} 
4

私はあなたの質問を正しく理解していれば答えではありません。むしろ、バックグラウンドスレッドがユーザ入力スレッドを妨害しないようにしたいのですか?

このため、ラインバッファされた入力ではなく、生のキー押しにアクセスする必要があります。なぜあなたがncursesや類似の図書館にアレルギーがあるのか​​わかりません。それが彼らのためだ!ミューテックスを作成します)

1:私はあなたがこれを行うことができ、それはあなたが転がる方法です場合

......、あなたはtermiosのかioctl呼び出しでそれを行うことができると思います。しかし、あなたのマルチスレッドTTY出力の問題を解決するために、メッセージ出力に、バックグラウンドスレッドでコンソール

にアクセスできるユーザーを制御します

グラブミューテックス。メッセージを書く。ミューテックスをリリースする。眠りに戻る!ユーザ入力スレッドで

グラブ新しい入力が検出されたミューテックス。ユーザーが入力を押すまで排他的なアクセスを維持してから、 を呼び出し、mutexを解放し、バックグラウンドスレッドに話す機会を与えます。

これは役に立ちますか?

+0

ありがとうございます。なぜ 'ECHONL'ですか? –

0

エコーをオフにするか、I/O非ブロックを使用して:あなたは、端末を復元する必要があります(atexitを使用)、終了する前に、次に

#include <termios.h> 

struct termios oflags, nflags; 
tcgetattr(fileno(stdin), &oflags); 
nflags = oflags; 
nflags.c_lflag &= ~ECHO; 
nflags.c_lflag |= ECHONL; 

if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { 
    /* handle error */ 
} 

:あなたはターミナルエコーを無効にすることができtermiosを使用して

+0

raw端末モードについてはcfmakeraw()を見てください。この関数を呼び出す前に必ずtermios構造体を保存して、完了したら復元するようにしてください。 –

関連する問題