2012-03-16 7 views
3

問題:を選択し、STD :: CINとstd :: getlineのはよく一緒に遊んでいない

私のプログラムはで、 'STD :: cinを< < ...' とstd :: getlineのミックスしようとしています「選択」のダッシュ。それは奇妙な動作をしますが、典型的な "あなたはstd :: cin.ignoreが必要です"という状況ではありません。

所望の動作:

意図がのstd :: cinを(もしあれば)トークン「停止」までのトークンを読むことですが遭遇しています。 std :: cinに残っているものは、後で質問への応答として読み込まれます。例えば:

$ echo 'one two stop y' | ./a.out 
read 'one' 
read 'two' 
Question? y 
read 'y' 
$ 

「1」と「2」トークンが読み込まれ、次いで「停止」が「Y」が読み出され防止する遭遇します。質問が尋ねられるときだけ、「y」を読むべきです。

実際の作動:

read 'one two stop y' 
Question? read '' 
Question? read '' 
Question? read '' 
... 

プログラムを呼び出して、待機中のトークンが存在するかどうかを確認するために、最初の '選択' は、それがのstd :: cinを、その後のstd :: getlineのを使用しています。通常、これは、std :: getlineが読んでいない保留中の '\ n'を読む必要があると思われる場所です。しかし、selectは待っている入力があることを示していないので、std :: cinはそれを見逃し、std :: getlineはそれをすべて取得します。

タイムアウトが追加された場合は、それが完璧に動作します:

最後に
tv.tv_usec = 1000; 

、質問:

何が起こっていますか?そして、私は何の愚かな間違いをしましたか?

コード:混合CINとcin.getlineの

#include <iostream> 
#include <sys/select.h> 

int main (int argc, char* argv[]) 
{ 
    // Step 1, read until 'stop'. 
    struct timeval tv; 
    tv.tv_sec = 0; 
    tv.tv_usec = 0; 

    fd_set fds; 
    FD_ZERO (&fds); 
    FD_SET (STDIN_FILENO, &fds); 

    int result = select (STDIN_FILENO + 1, &fds, NULL, NULL, &tv); 
    if (result && result != -1) 
    { 
    if (FD_ISSET (0, &fds)) 
    { 
     std::string token; 
     while (std::cin >> token) 
     { 
     if (token == "stop") 
      break; 

     std::cout << "read '" << token << "'\n"; 
     } 
    } 
    } 

    // Step 2, ask a question. 
    std::string answer; 
    do 
    { 
    std::cout << "Question? "; 
    std::getline (std::cin, answer); 
    std::cout << "read '" << answer << "'\n"; 
    } 
    while (answer != "y"); 

    return 0; 
} 
+0

入力セットの予測された予想出力と実際の出力を加算できませんか? –

答えて

3

tv.tv_usec = 0の場合は、ポーリングして何かがあるかどうかを確認するだけです。ファイル文が0以外の何かを返すために何かが存在しなければなりません(これは、利用可能な入力なしで時間に達したことを示します)。

私が観察した他の問題は、tv.tv_usecとtv.tv_sec = 0では、処理できるデータがあるかどうかを一度だけチェックすることです。 selectに到達したときに入力FDが設定されていない場合、入力FDはそのまま通過し(結果はゼロ)、プログラムを終了します。私は、テレビで時間を設定すると、あなたに記述子を設定する何かを入力する機会が与えられると思う。私はループ内に入力が発生するのを待つために選択を配置します。プログラムが現在書かれている方法では、selectは入力があるかどうかを1回だけチェックします。私は以下のループの例を持っています。

while (1) 
{ 
    FD_ZERO (&fds); 
    FD_SET (STDIN_FILENO, &fds); 
    tv.tv_sec = 0; 
    tv.tv_usec = 100; 
    result = select (STDIN_FILENO + 1, &fds, NULL, NULL, &tv); 
    // Code here to read in line if result is not zero 

} 

私はしばらく待ってみるか、ループを非常に速く回転させます。入力があるときに選択が戻り、残りの時間がテレビに表示されます。

+1

stdinの入力はオプションであるため、while(1)は機能しません。それらの「1つ」と「2つ」のトークンは存在しないかもしれません。選択はそれをチェックすることです。 –

1

ほとんどの問題は、結果やフラッシング問題の副作用です。私はこのシナリオでも違うと思います。

EDIT:はい、peekを使用して、ストリームから抽出することなく文字をチェックする必要があります。

+0

はい、フラッシュする必要はありません。私はそれをシミュレートすることができます。 –

関連する問題