Alternative for getch and getche on Linux
In Windows you can easily get one character from the standard input, without the user having to press the Enter key. By default this is not possible on Linux, because the terminal is buffered by default. There is however a way to make the terminal unbuffered and achieve the same functionality on Linux. Look at this code snippet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | /* getch() and getche() functionality for UNIX, based on termios (terminal handling functions) This code snippet was written by Wesley Stessens (wesley@ubuntu.com) It is released in the Public Domain. */ #include <termios.h> #include <stdio.h> static struct termios old, new; /* Initialize new terminal i/o settings */ void initTermios(int echo) { tcgetattr(0, &old); /* grab old terminal i/o settings */ new = old; /* make new settings same as old settings */ new.c_lflag &= ~ICANON; /* disable buffered i/o */ new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ } /* Restore old terminal i/o settings */ void resetTermios(void) { tcsetattr(0, TCSANOW, &old); } /* Read 1 character - echo defines echo mode */ char getch_(int echo) { char ch; initTermios(echo); ch = getchar(); resetTermios(); return ch; } /* Read 1 character without echo */ char getch(void) { return getch_(0); } /* Read 1 character with echo */ char getche(void) { return getch_(1); } /* Let's test it out */ int main(void) { char c; printf("(getche example) please type a letter: "); c = getche(); printf("\nYou typed: %c\n", c); printf("(getch example) please type a letter..."); c = getch(); printf("\nYou typed: %c\n", c); return 0; } |








A smart change would be to pass a bool to initTermios for whether or not the ECHO flag should removed, and then it will be able to define the new terminal i/o settings itself.
This way you factorize some, and it’s cleaner, it’s more KISS-like.
void initTermios(int disable_echo) {
tcgetattr(0, &old); /* grab old terminal i/o settings */
new = old; /* make new settings same as old settings */
new.c_lflag &= ~ICANON; /* disable buffered i/o */
if (disable_echo)
new.c_lflag &= ~ECHO;
tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */
}
Change other functions accordingly…
That would be a bit cleaner indeed. I’ll update the example code a bit.
Edit: code is updated. I have created a new getch_ function as well which is called by both the getch and getche function to minimize duplicated code.