1

重複の可能性:
C / C ++:Enterキーが押されるのを待たずに、標準入力から文字をキャプチャします

char ch;

キャラクターを手に入れたいと思います。私は2つの異なる方法を知っています。

1-iostreamヘッダーファイルでcinコマンドを使用します。

cin >> ch;

ユーザーが何かを入力するのを待ってから、ユーザーはEnterキーを押してch変数に入力を送信する必要があります。

2-conio.hヘッダーファイルのgetch()コマンド。

ch = _getch();

ユーザーが何かを入力するのを待ちます。文字を入力するとすぐにch変数に保存され、ユーザーはEnterキーを押す必要がありません。ところで、このコードはプログラムを停止し、入力を待ちます。

ここで、Enterキーを押す必要がなく、何かを押すためのプログラムを停止しないコマンドを書きたいと思います。プログラムを1秒間遅らせると想像してみてください。ユーザーが何かを押すと、それがch変数に保存されます。何もない場合でも、プログラムは続行され、何かを押しても停止しません。これはピッカーコマンドのようなもので、何かがある場合はそれをピックアップし、そうでない場合は続行します。

はっきりしているといいのですが。それで、それをどのように行うのですか?

4

2 に答える 2

2

Windowsでは、次のことができます。

  1. CreateFileファイル名を使用します"CONIN$"。これにより、コンソールへのWin32ハンドルが提供されます。
  2. WaitForSingleObject、コンソールハンドルとタイムアウトを渡します。
  3. 待機が成功した場合は、を使用ReadConsoleInputして何が起こったかを判断します。
  4. 待機が失敗した場合、タイムアウトが発生しました。

他のアクションを実行するループでポーリングしている場合は、を使用できますPeekConsoleInput。これは、入力キューにイベントがあるかどうかを確認し、常にすぐに戻ります。


Unixでは、同様のアプローチが機能します。注意してください:

  1. stdinは常にファイル記述子であるため、ファイルを開く必要はありません0
  2. selectまたはを使用pollして、タイムアウトのある入力のアクティビティをテストします。

最終的な違い:Windowsでは、マウスのアクティビティは同じ方法でキャプチャされます。Unixでは、通常、ttyからキーボード入力を読み取ることになり、マウスのものは完全に分離されます。

于 2012-05-27T18:35:09.877 に答える
1

まず、ノンブロッキング入力をオンまたはオフにする関数が必要です。

void nonblock(const bool state){

    struct termios ttystate;

    //get the terminal state
    tcgetattr(STDIN_FILENO, &ttystate);

    if (state){
        //turn off canonical mode
        ttystate.c_lflag &= ~ICANON;
        //minimum of number input read.
        ttystate.c_cc[VMIN] = 1;
    }
    else{
        //turn on canonical mode
        ttystate.c_lflag |= ICANON;
    }

    //set the terminal attributes.
    tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
}

ここで、キーが押されたかどうかをテストおよび確認する関数が必要です。

int keypress(void){
    struct timeval tv;
    fd_set fds;
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds);
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
    return FD_ISSET(STDIN_FILENO, &fds);
}

2つのことを並行してチェックします。ユーザーがキーを押しましたか、それとも時間がなくなりましたか?指定した秒数後にブール値を変更する関数は次のとおりです。

void SleepForNumberOfSeconds(const int & numberofSeconds,bool & timesUp){

    timespec delay = {numberofSeconds,0};
    timespec delayrem;

    nanosleep(&delay, &delayrem);
    timesUp = true;

    return;
}

呼び出すことができる主な関数は次のとおりです。

void WaitForTimeoutOrInterrupt(int const& numberofSeconds){

    bool timesUp = false;

    std::thread t(SleepForNumberOfSeconds, numberofSeconds, std::ref(timesUp));
    nonblock(1);
    while (!timesUp && !keypress()){

    }

    if (t.joinable()){
        t.detach();
    }
    nonblock(0);

    return;
}

テストするコードは次のとおりです。
コンパイル:

g ++ -std = c ++ 0x -o rand rand.cpp -lpthread

の上:

gcc(Ubuntu / Linaro 4.6.1-9ubuntu3)4.6.1

これは1つの解決策にすぎず、うまくいかない場合があります。
ncursesも調べることを検討してください。

于 2012-05-27T19:16:57.220 に答える