How to make C program stop the loop from any user input?

I would like to write a small C program that starts an infinite loop until the user presses a key on the keyboard (i.e. there is a char in the stdin buffer). I ran into a loop breaking problem on user input. I tried using fgetc , but this does not behave as expected. The code below is waiting for user input, and does not work until user input.

C code example:

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

How to write a loop that runs before user intervention? Pressing any key or a specific key can be an intervention trigger.

Note 1: I am writing this for the Unix console in the case of platform-specific solutions

Note 2: Do not offer Ctrl + C/X/Z as a trigger for user intervention

+4
source share
1 answer

This seems to work for me:

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

or you can use 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; } 

The survey also works :-)

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

The last way is to install the terminal in raw mode. Note that this upsets the output to the terminal (at least on my OS-X) in that \ r becomes necessary after \ n. Also note that it must be undone at the end (the final call to tcsetattr ). This is the only one that does not need \ n (i.e. any keystroke)

 #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; } 
+4
source

Source: https://habr.com/ru/post/1446580/


All Articles