2012-11-17 46 views
4

我想編寫一個運行無限循環的小C程序,直到用戶按下鍵盤上的某個鍵(即:stdin緩衝區中有一個字符)。我遇到了打破用戶輸入循環的麻煩。我嘗試過使用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:我在平臺的情況下寫這對於Unix主機的具體解決方案

注2:不建議Ctrl + C/X/Z作爲用戶干預的觸發

+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,輸入密鑰的用戶不會向程序提供任何輸入。在用戶點擊「輸入」或通過^ C或^]或^ Z發送信號之前,tty不會向您的程序發送任何內容。澄清你的問題。你想回應輸入,還是想回應鍵盤事件?兩者不同。 –

回答

4

這似乎爲工作我:

#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; 
} 

最後一個方法是設置在「原始」模式的終端。請注意,這會擾亂輸出到終端(至少在我的OS-X上),因爲\ r在\ n之後變得必要。還要注意,它最後需要撤消(終止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特定的 –