My app first takes some input, then it 'thinks' showing a progress bar, then throws an exit code and waits with getchar()
for ENTER to be clicked before exiting.
The problem is that if I click ENTER during the 'thinking' process, it will affect the getchar()
, causing it to exit immediately after throwing the exit code, without waiting for a new ENTER. I only found methods of clearing the cin
buffer until \n
what doesn't work in my case - I need to somehow clear the whole buffer just before calling getchar()
- I think.
My app is meant for both Windows and MacOS, but in different #ifdef
s, so both cases need solving.
The code is similar to this:
int main()
{
string name;
getline(cin, name);
//Think and show progres bar
cout << "Ended with exit code 1";
getchar();
return 1;
}
Here you go.
On Windows, you can use _kbhit
/_getch
from conio.h
.
On POSIX-compliant systems, such as MacOS, you can use termios.h
to reproduce those functions.
// You didn't include those three lines in your sample code, but they're implied, so here they are.
#include <iostream>
#include <string>
use namespace std;
// kbhit/getch compatibility
#if defined(_WIN32) || defined(WIN32)
#include <conio.h>
#define kbhit _kbhit
#define getch _getch
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__)) // Should work for any POSIX-compliant system, including MacOS
#include <sys/ioctl.h>
#include <sys/select.h>
#include <termios.h>
#include <stdarg.h>
#include <unistd.h>
static int peek = -1;
inline int kbhit() {
// Initial variables
char ch;
int nread;
struct termios origTerm, newTerm;
// Check if a character hasn't been buffered yet
if (peek != -1)
return 1;
// Preparing the terminal
tcgetattr(0, &origTerm);
newTerm = origTerm;
newTerm.c_lflag &= ~ICANON;
newTerm.c_lflag &= ~ECHO;
newTerm.c_lflag &= ~ISIG;
newTerm.c_cc[VMIN] = 1;
newTerm.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &newTerm);
// Read potential keyboard input
newTerm.c_cc[VMIN] = 0;
tcsetattr(0, TCSANOW, &newTerm);
nread = read(0, &ch, 1);
newTerm.c_cc[VMIN] = 1;
tcsetattr(0, TCSANOW, &newTerm);
// Restore the terminal
tcsetattr(0, TCSANOW, &origTerm);
// Check if something was read
if (nread == 1) {
peek = ch;
return 1;
}
return 0;
}
inline char getch() {
char ch = peek;
peek = -1;
return ch;
}
#else
#error kbhit and getch are not supported.
#endif
// Your code, with a new line to clear the keyboard buffer
int main()
{
string name;
getline(cin, name);
//Think and show progress bar
while (kbhit()) getch(); // Clear keyboard buffer
cout << "Ended with exit code 1";
getchar();
return 1;
}
References: