c++ linux getch conio kbhit

c++ - Usando kbhit() y getch() en Linux



conio (4)

El cómo ncurses citado anteriormente puede ser útil. Aquí hay un ejemplo que ilustra cómo ncurses podría usarse como el ejemplo conio:

#include <ncurses.h> int main() { initscr(); cbreak(); noecho(); scrollok(stdscr, TRUE); nodelay(stdscr, TRUE); while (true) { if (getch() == ''g'') { printw("You pressed G/n"); } napms(500); printw("Running/n"); } }

Tenga en cuenta que con ncurses, el encabezado iostream no se utiliza. Esto se debe a que mezclar stdio con ncurses puede tener resultados inesperados.

ncurses, por cierto, define TRUE y FALSE . Un ncurses configurado correctamente utilizará el mismo tipo de datos para ncurses '' bool que el compilador de C ++ utilizado para configurar ncurses.

En Windows, tengo el siguiente código para buscar entradas sin interrumpir el ciclo:

#include <conio.h> #include <Windows.h> #include <iostream> int main() { while (true) { if (_kbhit()) { if (_getch() == ''g'') { std::cout << "You pressed G" << std::endl; } } Sleep(500); std::cout << "Running" << std::endl; } }

Sin embargo, al ver que no hay conio.h , ¿cuál es la forma más sencilla de lograr esto mismo en Linux?


Si bien el uso de ncurses es funcionalmente equivalente a la API Turbo C "conio.h", una solución más completa es utilizar una implementación de conio, como se puede encontrar aquí .

Lo descarga y lo usa en su programa para una implementación muy completa de la interfaz conio, en Linux. (O OSX.) Escrito por Ron Burkey.


Si su Linux no tiene conio.h que admita kbhit() , puede buscar aquí el código de Morgan Mattews para proporcionar la funcionalidad kbhit() de manera compatible con cualquier sistema compatible con POSIX.

Como el truco desactiva el almacenamiento en búfer a nivel de termios, también debería resolver el problema getchar() como se demuestra here .


Una solución compacta basada en la respuesta de Christophe es

#include <sys/ioctl.h> #include <termios.h> bool kbhit() { termios term; tcgetattr(0, &term); termios term2 = term; term2.c_lflag &= ~ICANON; tcsetattr(0, TCSANOW, &term2); int byteswaiting; ioctl(0, FIONREAD, &byteswaiting); tcsetattr(0, TCSANOW, &term); return byteswaiting > 0; }

A diferencia de esa respuesta, esto no dejará el terminal en un estado extraño después de que el programa haya salido. Sin embargo, todavía deja los caracteres sentados en el búfer de entrada, por lo que la tecla que se presionó aparecerá desagradablemente en la siguiente línea de solicitud.

Una solución diferente que soluciona este problema es

void enable_raw_mode() { termios term; tcgetattr(0, &term); term.c_lflag &= ~(ICANON | ECHO); // Disable echo as well tcsetattr(0, TCSANOW, &term); } void disable_raw_mode() { termios term; tcgetattr(0, &term); term.c_lflag |= ICANON | ECHO; tcsetattr(0, TCSANOW, &term); } bool kbhit() { int byteswaiting; ioctl(0, FIONREAD, &byteswaiting); return byteswaiting > 0; }

El uso es el siguiente

enable_raw_mode(); // ... if (kbhit()) ... // ... disable_raw_mode(); tcflush(0, TCIFLUSH); // Clear stdin to prevent characters appearing on prompt

Ahora los caracteres escritos entre la ejecución de la primera y la última línea no aparecerán en el terminal. Sin embargo, si sale con Ctrl + C, el terminal queda en un estado extraño. (Suspiro)