Hola a todos, ya tengo una solucion para la lectura del teclado de forma no bloqueante es una mezcla de cambiar algunos aspectos de la configuracion de la terminal (de lo ke no tengo ni idea ya ke parte del codigo es sacado de ejemplos que encontre que no funcionaban del todo bien) y un poco de codigo igual que el que tuve que usar al programar SNL para los grupos de conexiones de sockets. Segun estuve leyendo de donde obtuve el codigo de los ejemplos el cambio en la configuracion de la terminal es por que la terminal en GNU/Linux por defecto trabaja de forma bloqueante, trabaja normal y cuando necesita algo se para para que el usuario escriba o pulse alguna tecla, por lo que hace es obtener la configuracion de la terminal, cambiar las opciones de la terminal para que trabaje de forma no bloqueante, con grupos de sockets y la funcion select se comprueba si la entrada estandar tiene algun caracter pendiente o a sucedido algo, obtiene el caracter de la tecla pulsada, comprueba que se obtuvo el caracter de forma correcta y restaura la terminal a su configuracion anterior. El codigo que encontre fallaba en que despues del select no comprobaba que fuese la entrada estandar la que verdaderamente tuviese algun caracter pendiente o algun suceso despues del select y en que no comprobaba que la funcion select no devolviese -1 y que read devolviese 1. Os dejo la funcion que he escrito finalmente con la que leer una tecla de forma no bloqueante:
- Código: Seleccionar todo
char tecla_pulsada(void){
char t='\0';
static struct termios oldconsola,consola;
fd_set rfd;
struct timeval timeout;
/* Leer los parametros asociados a la consola */
if (tcgetattr(STDIN_FILENO,&consola)==-1) {
t= '\0';
}else{
/* Almacenar parametros para su posterior recuperacion*/
oldconsola = consola;
/* Cambiar parametros */
consola.c_cc[VMIN]=1;
consola.c_lflag&=~(ECHO|ICANON);
if(tcsetattr(STDIN_FILENO,TCSANOW,&consola)==-1){
t= '\0';
}else{
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
FD_ZERO(&rfd);
FD_SET(STDIN_FILENO,&rfd);
if(select(STDIN_FILENO+1,&rfd,NULL,NULL,&timeout) != -1){
if(FD_ISSET(STDIN_FILENO, &rfd)){
read(STDIN_FILENO,&t,1);
}
}else{
t= '\0';
}
/*recuperando la terminal anterior*/
tcsetattr(STDIN_FILENO,TCSANOW,&oldconsola);
}
}
return t;
}
Aprovecho tambien para dejaros un poco de codigo con el que se puede mostrar una barra "/" girando mientras el programa espera o hace cualquier cosa esperando a que el usuario pulse alguna tecla. El codigo que se pone donde se quiera escribir la barra girando es:
- Código: Seleccionar todo
printf("%c", barra_girando());
printf("%c[1D", 27);
Y el codigo de la funcion barra_girando(), que es la funcion que devuelve el caracter apropiado para hacer la animacion de la barra girando:
- Código: Seleccionar todo
char barra_girando(void){
static unsigned int f=0;
char s=' ';
if(f == 0){
s= '\\';
}else if(f == 1){
s= '|';
}else if(f == 2){
s= '/';
}else if(f == 3){
s= '-';
}
f++;
f= f%4;
return s;
}
Se que esto no tiene valor cuando se programa usando bibliotecas graficas como SDL, pero se puede usar por ejemplo para juegos en modo texto, para programar un servidor para un juego y cualquier otra cosa que se os ocurra.