/*
* ask_yn - Wait for a user to press Y or N.
*
* By default, standard input in C++ (and most terminals) is line-buffered:
* the terminal waits until you press Enter before sending the input to your
* program.
*
* Getting a character immediately is not part of standard C++; it requires
* platform-specific APIs. On Windows, you can use _getch() from <conio.h>.
* It reads a character immediately without waiting for Enter.
* On Linux, you need termios to switch the terminal to raw mode (disable
* canonical input buffering) and read a single character immediately.
* Note that anything send to stdout while in raw mode is buffered and
* printed after leaving raw mode.
*
* If any type of portability is needed, use ncurses. It is a programming
* library for creating textual user interfaces (TUIs) that work across a
* wide variety of terminals.
*
* g++ -std=c++17 -Wpedantic -Wall -Wextra ask_yn.cpp -o ask_yn
*/
#include <iostream>
#if defined(_WIN32) || defined(_WIN64)
// -------------------- WINDOWS VERSION --------------------
#include <conio.h>
#else
// -------------------- LINUX / POSIX VERSION --------------------
#include <unistd.h>
#include <termios.h>
class BlockingRawModeScope {
public:
BlockingRawModeScope() {
tcgetattr(STDIN_FILENO, &orig_termios);
termios raw = orig_termios;
raw.c_lflag &= ~(ICANON | ECHO); // disable canonical mode and echo
tcsetattr(STDIN_FILENO, TCSANOW, &raw);
}
~BlockingRawModeScope() {
tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
}
private:
termios orig_termios;
};
#endif
bool get_yn()
{
#if defined(_WIN32) || defined(_WIN64)
// -------------------- WINDOWS VERSION --------------------
for(;;) {
char c = _getch();
if (c == 'Y' || c == 'y') {
return true;
}
if (c == 'N' || c == 'n') {
return false;
}
}
#else
// -------------------- LINUX / POSIX VERSION --------------------
BlockingRawModeScope rawMode;
for(;;) {
char c;
if (read(STDIN_FILENO, &c, 1) > 0) {
if (c == 'Y' || c == 'y') {
return true;
}
if (c == 'N' || c == 'n') {
return false;
}
}
}
#endif
}
int main() {
std::cout << "Press Y or N: " << std::flush;
if (get_yn())
std::cout << "\nYou pressed Y\n";
else
std::cout << "\nYou pressed N\n";
return 0;
}