Search code examples
cwhile-loopuser-input

Continue iterating/repeating while loop until enter (or arbitrary key) is pressed


I'm trying to get a while loop to iterate until a key, ideally enter, is pressed.

Specifically, what I want is for a value to continually update and be visible to the user until he presses enter.

Here is the basic code I'm working with, which doesn't work as I'd like it to

while(1){       
    printf("Press Enter to Continue\n");    
    printf("Value to Update: %f\n",value_to_update); 
    usleep(10000);      
    system("clear"); 
    while(getchar() != '\n'){
        continue; 
    }       
}; 

Thanks. Happy to clarify anything I've said or answer other questions.

I'm not sure how to explain exactly what I'm looking for. I'll try two ways:

1) I want it to do what the following code does, except stop when the user presses enter:

while(1){           
    printf("Value to Update: %f\n",value_to_update); 
    usleep(10000);      
    system("clear"); 
};

2) I'll enumerate the steps

1) Print the value to update to the screen

2) Wait for N microseconds

3) Did the User Press enter?

3.False) If No: Clear the screen, Go to step 1

3.True) If Yes: Break from loop

I guess this is way way harder than I thought it would be.


Solution

  • Here is example code that works using the select call.

    It only works for newline because the kernel TTY layer will hold up until it gets a newline.

    So, for any other char (e.g. space), we'd have to issue the ioctl calls I mentioned in my top comments to put the layer into "raw" mode (vs. the default of "cooked"). If you need that, see tcgetattr and tcsetattr calls.

    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <time.h>
    #include <sys/time.h>
    #include <sys/select.h>
    
    int
    main(void)
    {
        int fd;
        char buf[10];
        int len;
        fd_set rdset;
    
        fd = 0;
    
        while (1) {
            // this is do whatever until newline is pressed ...
            printf(".");
            fflush(stdout);
    
            // set up the select mask -- the list of file descriptors we want to
            // wait on for read/input data available
            FD_ZERO(&rdset);
            FD_SET(fd,&rdset);
    
            // set timeout of 1ms
            struct timeval tv;
            tv.tv_sec = 0;
            tv.tv_usec = 1000;
    
            // wait for action on stdin [or loop if timeout]
            // the first arg must be: the highest fd number in the mask + 1
            len = select(fd + 1,&rdset,NULL,NULL,&tv);
            if (len <= 0)
                continue;
    
            // we're guaranteed at least one char of input here
            len = read(fd,buf,1);
            if (len <= 0)
                continue;
    
            // wait for newline -- stop program when we get it
            if (buf[0] == '\n')
                break;
        }
    
        printf("\n");
    
        return 0;
    }