Non-blocking user input in loop without ncurses.

Source: Internet
Author: User
Tags usleep vmin

The title sounds a bit awkward, let my briefly explain what is it all about.

In my program, I want to wait for user input, but at the same time, I want my other operations keep continue processing. that I define it as non-blocking user input. I want my program to wait for user input in the loop, if necessary ES user input process it and continue wait for next user input, else continue processing other circular operations.

Usually, people will think about using ncurses library. by using ncurses, you can easily perform non-blocking user input using timeout (0) and getch (). refers to the ncurses matrix for references.

What if I don't want to uses ncurses? Its there any alternatives? Sometimes I just wanna add a function which need non-blocking in a large program, I don't want to use ncurses because it makes my print line acts differently, or some other reason.

I have figure out a way, thanks to programmers at # [email protected] It might look messy and complected, but it works the way I wanted. I uses functions of termios and select, lets look at the functions one by one.

?
0102030405060708091011 int kbhit(){    struct timeval tv;    fd_set fds;    tv.tv_sec = 0;    tv.tv_usec = 0;    FD_ZERO(&fds);    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);    return FD_ISSET(STDIN_FILENO, &fds);}

This function perform non-blocking checking on the standard input (stdin) without timeout 0, TV. TV _sec and TV. TV _usec both set to zero. select usually uses in the case where there have multiple I/O need to process, or check at the same time. but in this case, I only interested in standard input, therefore only one fd_set (stdin_fileno, & FDs) is Trigger. for select parameters details, please check out the manual. seems we are only interested in input, so we place out FD set at second parameter of select (), the 3rd is for output and 4th is for exception.

Important part, after select if user input is Trigger, fd_isset will return non zero value, else return 0. So, we now can use it like this

?
12345 while(!kbhit()){      //do certain operation..}//user hits enter.

Due to the canonical mode of your terminal, you need to hit enter to confirm your user input. canonical Mode means it always wait for enter to confirms the user input. if that is not your case, Bellow is another function to cater that.

?
0102030405060708091011121314151617181920212223 void nonblock(int state){    struct termios ttystate;     //get the terminal state    tcgetattr(STDIN_FILENO, &ttystate);     if (state==NB_ENABLE)    {        //turn off canonical mode        ttystate.c_lflag &= ~ICANON;        //minimum of number input read.        ttystate.c_cc[VMIN] = 1;    }    else if (state==NB_DISABLE)    {        //turn on canonical mode        ttystate.c_lflag |= ICANON;    }    //set the terminal attributes.    tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); }

The function name might be misleading, what the function actually does is turn off the canonical mode for stdin. first, get the states of stdin of term. next turn off the canonical by set 0 to the bits. the line of ttystate. c_cc [Vmin] is set the minimum number of user input to accept. if you set it as 2, the Select will wait until 2 character is given, then it will capture as input. at last set the term state. the function actually does allow you to turn on and off the canonical mode.

Okay, let see how it apply to work

?
0102030405060708091011121314151617181920212223242526 int main(){    char c;    int i=0;     nonblock(NB_ENABLE);    while(!i)    {        usleep(1);        i=kbhit();        if (i!=0)        {            c=fgetc(stdin);            if (c==‘q‘)                i=1;            else                i=0;        }         fprintf(stderr,"%d ",i);    }    printf("\n you hit %c. \n",c);    nonblock(NB_DISABLE);     return 0;}

Press 'q' will lead the program to quit, else you will see the print of '0' overwhelming the screen. observed that I am using usleep (1) inside the loop, without putting usleep, the programs is more responsive, but it uses high CPU resources. on the other hand, putting usleep (1) CES the CPU resources and also decreases responsiveness of the program. depend on your needs, you may choose to put it in or not.

I have make the comparison between this application and a simple ncurses program, this program seems to use lesser memory. Couldn't measure for CPU resources, as both PS and top shows 0.0%.

Curses sample shows as bellow:

?
010203040506070809101112131415161718192021222324 #include<stdio.h>#include<curses.h>#include<unistd.h> int main (){    int i=0;     initscr();     //in ncurses    timeout(0);    while(!i)    {        usleep(1);        i=getch();        printw("%d ",i);        if(i>0)            i=1;        else            i=0;    }    endwin();    printf("\nhitkb end\n");    return 0;}

Download the source code:
Non-blocking kbhit sample source code.

Non-blocking user input in loop without ncurses.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.