Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to break a while loop in C on linux by taking any value from keyboard?

The program I am building runs in an infinite while loop with a switch case in it. I want to insert a while loop under each case and perform few operations in the loop, but the loop should exit as soon as a keyboard input is given. So that after taking the input from keyboard another case is run with the nested while loop in it, and the process continues.

The structure is:

while()//infinite loop
    {
    ...............      //operations
    ...............      //operations
    switch()
        {
        case 1:
        ...............    //operations
        ...............    //operations
        while()//infinite loop
             {
             ..............
             ..............
             exit if there is any input from keyboard
             }
        break;

        case 2:
        ...............    //operations
        ...............    //operations
        while()//infinite loop
             {
             ..............
             ..............
             exit if there is any input from keyboard
             }
        break;


        case n:
        ...............    //operations
        ...............    //operations
        while()//infinite loop
             {
             ..............
             ..............
             exit if there is any input from keyboard
             }
        break;
        }
  }

Is there any way to do it???

like image 610
Nitish Sahay Avatar asked Jun 05 '13 10:06

Nitish Sahay


1 Answers

Linux keyboard input is buffered, in order to catch a key that was hit on the fly you have to configure TERM IO.

Near the top of main() add a call to (see code below)

term_nonblocking();

to read a key that was pressed on the fly, without waiting for a carriage return (CR).

Code:

struct termios stdin_orig;  // Structure to save parameters

void term_reset() {
        tcsetattr(STDIN_FILENO,TCSANOW,&stdin_orig);
        tcsetattr(STDIN_FILENO,TCSAFLUSH,&stdin_orig);
}

void term_nonblocking() {
        struct termios newt;
        tcgetattr(STDIN_FILENO, &stdin_orig);
        fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // non-blocking
        newt = stdin_orig;
        newt.c_lflag &= ~(ICANON | ECHO);
        tcsetattr(STDIN_FILENO, TCSANOW, &newt);

        atexit(term_reset);
}

Note: term_reset() will be called automatically when your program exits, (to reset the terminal parameters).

You can call the now non-blocking getchar() anywhere in your program to detect a key press

int i = getchar();

and check if a key was pressed:

if (i > 0) {
    // key was pressed, code in `i`
}

In your program for instance:

int key = 0;

while (... && key <= 0) {
   // ... 
   key = getchar();
}

Note: if you want the output to be unbuffered, call setbuf(stdout, NULL);

(comment from @stacey : getchar() may return 0 or -1 when no key is available)

like image 107
Déjà vu Avatar answered Sep 18 '22 18:09

Déjà vu