Search code examples
c++cgetchar

C++ getchar() is there data still waiting to be read


I am implementing a key reader program in c/c++. I am using linux. I know that the unbuffered getchar function will return little data values of keys. For all ASCII keys (a-z, A-Z, 1-9, punctuation, enter, tab, and ESC) there will be a single value returned from getchar(). For other keys, such as the arrow keys, there will be the ESC key read, but then when getchar() is called again, it will get another value (A, B, C,or D).

A = 65

B = 66

UP arrow = 27 91 65

F5 = 27 91 49 53 126

ESC = 27

full table here

Is there any way to check if there are more characters to be read or if there is just a single character? When a key is read and it's first value is ESC I do not know if it is a function key that starts with ESC or if it is just the ESC key.

#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <iostream>
#include <string>
#include <termios.h>
#include <unistd.h>

using namespace std;

int main(int argc, char *argv[]) {

    int ch[5];
    int i;
    struct termios term;

    tcgetattr( STDIN_FILENO, &term );
    term.c_lflag &= ~( ICANON | ECHO );
    tcsetattr( STDIN_FILENO, TCSANOW, &term );

    ch[0] = getchar();

    // If ch[0] = 27 and there is more data in the buffer
    // printf("You pressed a function key");
    // Else
    // printf("You pressed ESC");

    return 0;   

}

Solution

  • You can mark stdio nonblocking when you get escape and then read as much as possible. You need to include <fcntl.h>

    if (ch[0] == 27) {
        int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
        fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
        for (;;) {
            int c = getchar();
            if (c == EOF)
                break;
            printf("%u ", c);
        }
        fcntl(STDIN_FILENO, F_SETFL, flags);
        puts("\n");
    }
    

    There is still a problem with two keys after each other as the loop will read until there is no more data available.