2012-11-17 7 views
4

사용자가 키보드의 키를 누를 때까지 (예 : stdin 버퍼에 char이 있음) 무한 루프를 실행하는 작은 C 프로그램을 작성하고 싶습니다. 나는 사용자 입력에 대한 루프를 깨뜨리는 데 어려움을 겪고있다. fgetc을 사용해 보았지만 예상대로 동작하지 않습니다. 아래의 코드는 사용자 입력까지 을 실행하는 대신 사용자 입력을 위해을 기다립니다.C 프로그램을 모든 사용자 입력에서 루프를 멈추게 만드는 방법은 무엇입니까?

샘플 C 코드 :

while((c=fgetc(stdin) == EOF) { 
    /* Does stuff for infinite loop here */ 
    printf("Example work in the loop\n"); 
} 
printf("Out of the loop!\n"); 

가 어떻게 사용자 개입 할 때까지 실행하는 루프를 작성합니까? 아무 키나 특정 키를 누르면 중재 트리거가 될 수 있습니다.

주 1 : 내가 특정 솔루션

주 2 플랫폼의 경우 유닉스 콘솔이 쓰고 :은 사용자 개입 트리거이가 작동하는 것 같다

+0

관련 : http://stackoverflow.com/questions/149860/how-to-prevent-fgets-blocks-when -file-stream-has-no-new-data – tjameson

+0

[C 넌 블로킹 키보드 입력] 가능한 중복 (http://stackoverflow.com/questions/448944/c-non-blocking-keyboard-input) – fvu

+0

프로그램이 stdin을위한 tty를 가지고 있다면, 사용자가 키를 입력하는 것은 프로그램에 어떤 입력도 제공하지 않을 것이다. tty는 사용자가 'enter'를 누르거나^C 또는 ^] 또는^Z를 통해 신호를 보낼 때까지 프로그램에 아무 것도 보내지 않습니다. 귀하의 질문을 명확히하십시오. 입력에 응답 하시겠습니까? 아니면 키보드 이벤트에 응답 하시겠습니까? 둘은 다르다. –

답변

4

Ctrl + C/X/Z을 제안하지 마십시오 나 :

#include <fcntl.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/uio.h> 
#include <unistd.h> 

static void set_non_blocking(int fd) 
{ 
    int flags = fcntl(fd, F_GETFL, 0); 
    flags |= O_NONBLOCK; 
    flags = fcntl(fd, F_SETFL, flags); 
} 


int main(int argc, char ** argv) 
{ 
    int fd = fileno(stdin); 
    char buf[10]; 

    set_non_blocking(fd); 

    while (read(fd, buf, sizeof buf) < 0) { 
     perror("read"); 
     sleep(1); 
    } 
    return 0; 
} 

하거나 사용할 수 select :

int main(int argc, char ** argv) 
{ 
    int fd = fileno(stdin); 
    struct timeval tv = {0,0}; 
    fd_set fdset; 
    int s; 

    do { 
     sleep(1); 
     FD_ZERO(&fdset); 
     FD_SET(fd, &fdset); 

    } while ((s = select(fd+1, &fdset, NULL, NULL, &tv)) == 0); 

    if (s < 0) { 
     perror("select"); 
    } 
    return 0; 
} 

는 설문 조사

int main(int argc, char ** argv) 
{ 
    struct pollfd pfd; 
    int s; 

    pfd.fd = fileno(stdin); 
    pfd.events = POLLRDNORM; 

    while ((s = poll(&pfd, 1, 0)) == 0) { 
     perror("polling"); 
     sleep(1); 
    } 
    if (s < 0) { 
     perror("poll"); 
    } 
    return 0; 
} 

마지막 방법은 '원시'모드에서 터미널을 설정하는 것입니다 너무 :-) 작동합니다. 이것은 \ n 다음에 \ r이 필요하게되면서 (적어도 OS-X의 광산에서) 터미널로 출력을 뒤집는다는 것에주의하십시오. 끝에서 실행 취소해야합니다 (종료 tcsetattr 호출). 이것은 \ n을 필요하지 않는 유일한 하나입니다 (어떤 키를 누를 때 할 것 예)

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


static void set_non_blocking(int fd) 
{ 
    int flags = fcntl(fd, F_GETFL, 0) | O_NONBLOCK; 

    if (fcntl(fd, F_SETFL, flags) < 0) { 
     perror("fcntl"); 
     exit(EXIT_FAILURE); 
    } 
} 


int main(int argc, char ** argv) 
{ 
    struct termios params; 
    struct termios params_orig; 
    char buf[10]; 
    int fd = fileno(stdin); 

    if (tcgetattr(fd, &params) < 0) { 
     perror("tcgetattr"); 
     exit(EXIT_FAILURE); 
    } 
    params_orig = params; 

    cfmakeraw(&params); 

    if (tcsetattr(fd, TCSANOW, &params) < 0) { 
     perror("tcsetattr"); 
     exit(EXIT_FAILURE); 
    } 
    set_non_blocking(fd); 

    while (read(fd, buf, sizeof buf) < 0) { 
     perror("\rread"); 
     sleep(1); 
    } 

    (void) tcsetattr(fd, TCSANOW, &params_orig); 
    return 0; 
} 
+0

이것은 나에게도 효과가있는 것 같다! (엔터 키가 눌려 졌을 때만) –

+0

'select()'가 * nix에 특화되어 있지 않기 때문에 좋아한다. –

관련 문제