2012-03-16 1 views
3

문제 :선택, 표준 : CIN 및 표준 : :의 getline 함께 잘 재생되지

내 프로그램으로, '표준 : CIN < < ...'및 표준 :의 getline을 혼합하려고 '선택'의 대시. 그것은 이상한 행동을하지만 전형적인 "당신은 std :: cin.ignore가 필요합니다"상황이 아닙니다.

원하는 작업 :

의도는 표준 : CIN (있는 경우) 토큰 '정지'까지의 토큰을 읽을 수가 발생합니다. std :: cin에 남아있는 것은 나중에 질문에 대한 응답으로 읽습니다. 예를 들어

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

'일'및 '개의'토큰을 판독하고 'STOP'은 'Y'이 판독되는 것을 방지하는 발생된다. 질문을 할 때만 'y'를 읽어야합니다.

실제 작동 :

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

이 프로그램은 호출 대기 토큰이 있는지 여부를 확인하기 위해, 첫 번째 '선택'다음은 표준 : CIN, 다음 표준 :의 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을 사용하면 처리 할 수있는 데이터가 있는지 한 번만 확인한다는 것입니다. 선택 항목에 도달했을 때 입력 FD가 설정되지 않으면 방금 통과하여 (결과는 0입니다) 프로그램을 종료합니다. 나는 TV에서 시간을 정하는 것이 당신에게 기술자를 설정할 무언가를 입력 할 수있는 기회를 제공한다고 생각한다. 나는 입력을 기다리기 위해 루프 내부에 선택 물을 넣을 것이다. 프로그램이 현재 쓰여지는 방식으로, select는 입력이 있는지 한 번만 검사합니다. 아래 루프의 예가 있습니다.

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 

} 

은 나뿐만 아니라에서 대기하는 시간을 둘 것, 또는 당신은 매우 빠르게 루프를 통해 회전됩니다. 선택하면 입력이 있고 TV에는 남은 시간이 포함됩니다.

+1

stdin의 입력이 선택적이므로 while (1)이 작동하지 않습니다. 그 '하나'와 '두'토큰은 없을 수 있습니다. 선택은 그것을 확인하는 것입니다. –

1

대부분의 문제는 결과 나 플러싱 문제의 부작용이다. 나는이 시나리오에서도 다른 점이있을 것이라고 생각하지 않는다.

편집 : 예. peek을 사용하여 문자를 스트림에서 추출하지 않고 확인하십시오.

+0

예.하지만 플러시 할 필요는 없습니다. 나는 그것을 기다릴 수있다. –