Si tu Linux no tiene conio.h
que soporta kbhit()
puede buscar aquí el código de Morgan Mattews para proporcionar kbhit()
funcionalidad de manera compatible con cualquier sistema compatible con POSIX.
Como el truco para desactivar el almacenamiento en búfer a nivel de termios, también debería resolver el getchar()
problema como se demuestra aquí.
El ncurses howto citado anteriormente puede ser útil. Aquí hay un ejemplo que ilustra cómo se pueden usar ncurses como el ejemplo de 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 iostream
el encabezado 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 correctamente configurado utilizará el mismo tipo de datos para el bool
de ncurses como el compilador de C++ utilizado para configurar ncurses.
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á la terminal en un estado extraño después de que el programa haya salido. Sin embargo, aún deja los caracteres en el búfer de entrada, por lo que la tecla que se presionó aparecerá de forma no deseada en la siguiente línea de aviso.
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 cualquier carácter escrito entre la ejecución de la primera y la última línea no aparecerá en la terminal. Sin embargo, si sale con Ctrl+C, el terminal es dejado en un estado extraño. (Suspiro)