2011-07-27 1 views
13

기본적으로 stdin에 입력이 있는지 테스트하고 싶습니다 (에코와 파이프처럼). 나는 작동하는 해결책을 찾았지만 추악하고 솔루션이 깨끗하다고 ​​생각합니다. 리눅스에stdin에 C++ (윈도우 및/또는 리눅스)에 대한 입력이 있는지 테스트하십시오.

내가 이것을 사용

bool StdinOpen() { 
    FILE* handle = popen("test -p /dev/stdin", "r"); 
    return pclose(handle) == 0; 
} 

내가 더 오류 처리를 추가해야한다고 알고 있지만,이 점 외에입니다. 창에

나는 이것을 사용 : 리눅스에 대한 괜찮지 만, 내가 파이프를 사용하지 않고 호출 할 수있는 해당 API를 (test -f $file에 대한 같은 당신이 fopen($file, "r") != NULL을)이 무엇인지 알고 싶어

bool StdinOpen() { 
    static HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); 
    DWORD bytes_left; 
    PeekNamedPipe(handle, NULL, 0, NULL, &bytes_left, NULL); 
    return bytes_left; 
} 

. 나는 내가 할 수있는 암시가 open("/dev/stdin", "r")이고 같은 일을하지만, 나는 그것을하는 가장 좋은 방법을 알고 싶다.

요약 : 당신은 창을위한 더 나은 솔루션을 알고 있다면, 나는 리눅스에 대한 test -p /dev/stdin를 대체하는 데 사용할 수있는 API를 알고 싶어합니다.

+0

표준 입력이 파이프가 아닌 파일 핸들 인 경우 'PeekNamedPipe' 솔루션이 실패합니다. 또한,'handle' 변수는 정적이어서는 안됩니다. 앱이 실행되는 동안 핸들이 리디렉션되면 나중에 자신을 놀라게 할 것입니다. –

+0

@Billy : 핸들을 임의로 리디렉션 할 수 있다고 생각하지 않습니다. 물론, 당신은 당신이 stdin으로 생각하는 것을 바꿀 수도 있지만 오래된 손잡이는 여전히 거기에 있습니다. 그러나 나는 첫 번째 부분에 동의한다. – Mehrdad

+0

Lionel B는 Linux 용 코드를 http://bytes.com/topic/c/answers/841283-how-make-non-blocking-call-cin에서 제공합니다. 토론의 가치도 있습니다. –

답변

13

다음은 POSIX (Linux)를위한 해결책입니다. Windows에서 poll()과 같은 것이 무엇인지 모르겠습니다. Unix에서 숫자 0을 가진 파일 설명자가 표준 입력입니다.

#include <stdio.h> 
#include <sys/poll.h> 

int main(void) 
{ 
     struct pollfd fds; 
     int ret; 
     fds.fd = 0; /* this is STDIN */ 
     fds.events = POLLIN; 
     ret = poll(&fds, 1, 0); 
     if(ret == 1) 
       printf("Yep\n"); 
     else if(ret == 0) 
       printf("No\n"); 
     else 
       printf("Error\n"); 
     return 0; 
} 

테스트 :

$ ./stdin 
No 
$ echo "foo" | ./stdin 
Yep 
+0

이것은 정확히 내가 원했던 것입니다. 이제 입력 버퍼 크기를 측정하는 방법을 알려 주시면 감사하겠습니다.하지만 질문 호그처럼 들리고 싶지는 않습니다. – norcalli

+0

read()를 사용하여 입력을 얻을 수 있습니다. 먼저 파일 디스크립터 0을 fcntl()을 사용하여 non-blocking으로 설정하면 read()는 읽은 바이트 수를 반환하거나 들어오는 데이터가 없을 때 0을 반환합니다. – Antti

+2

+1. 일반적으로 사용되는 또 다른 대안은'select()'입니다 - 개념적으로 비슷한 사용법. 디스크립터에서 새로운 데이터가 있는지를 운영체제에 문의하는 것이 중요하다. 만약 당신이 그 레벨에서 작동한다면, 디스크립터에서 직접'read()'를 사용해야한다. stdin 스트림이나'std :: cin' (새로운 버퍼 구현을 제공하지 않는 한). –

1

확실하지 않지만 _kbhit()은 필요한 것을 처리합니까?

1

이 작동하지 않을까요?

std::cin.rdbuf()->in_avail();