Publi

Obtener UNA tecla

Hace mucho tiempo, cuando empezaba con la programación, tenía la librería conio.h de Borland (en la que aún se siguen basando en muchos sitios), que nos permitía entre otras cosas borrar la pantalla, posicionarnos dentro de la pantalla, escribir con colores, y pedir una tecla al usuario.
Bien, vayámonos al último caso, pedir una tecla al usuario, se hacía con la función getch, y con sólo pulsar la tecla, salía de la función, es decir, no hacía falta pulsar enter.
Pero cuando nos vamos a linux, nos damos cuenta de que tenemos que utilizar getchar() y esa función estará pidiendo letras del teclado hasta que pulsemos enter.

Podemos optar por varias soluciones:

  1. Utilizar ncurses (que le da mil vueltas a conio.h)
  2. Si sólo queremos algo puntual, la que os propongo a continuación

La solución la encontré hace un tiempo y la tenía por aquí archivada, y la primera publicación del código que he encontrado ha sido esta por kermi3, la función original la publicó VvV.

La solución que propongo tiene un pequeño cambio en el que podemos elegir si queremos que se muestre dicha tecla pulsada o no (echo), y está comentada:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
#include <termios.h>
#include <unistd.h>

int mygetch(int echo)
{
  struct termios oldt, newt;
  int ch;

  /* Obtenemos atributos del terminal */
  tcgetattr( STDIN_FILENO, &oldt );
  newt = oldt;
  /* Eliminamos el modo canónico: caracteres especiales */
  newt.c_lflag &= ~ICANON;
  /* Eliminamos el echo a voluntad */
    if (!echo)
      newt.c_lflag &= ~ECHO;
  /* Definimos los nuevos atributos al terminal */
  tcsetattr( STDIN_FILENO, TCSANOW, &newt );
  ch = getchar();
  /* Ponemos los atributos como estaban al principio */
  tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
  return ch;
}

int main()
{
  int tecla;
  printf("Pulsa una tecla (sin echo): ");
  tecla=mygetch(0);
  printf("\nHas pulsado la tecla %c (%c)\n", tecla, tecla);

  printf("Pulsa una tecla (con echo): ");
  tecla=mygetch(1);
  printf("\nHas pulsado la tecla %c (%c)", tecla, tecla);
}

La incluiré en la próxima revisión de strutils.

También podría interesarte...

There are 4 comments left Ir a comentario

  1. Pingback: www.programame.net /

  2. Pingback: Poesía binaria » Desea continuar? [(S)i, (N)o, (M)e lo pienso] /

  3. josephant /
    Usando Google Chrome Google Chrome 9.0.597.107 en Linux Linux

    Disculpa, soy nuevo en esto de programación, he utilizado el código que publicaste como remplazo para getch en linux y me funciona muy bien, pero me gustaría saber si podrías explicarme como funciona (el código de la función mygetch) ya que solamente lo use y no logro entenderlo.

    Gracias

  4. admin /
    Usando Mozilla Firefox Mozilla Firefox 3.6 en Linux Linux

    @josephant Perdona el retraso, te comento, lo que hacemos es:
    * primero obtener los atributos del terminal (con tcgetattr( STDIN_FILENO, &oldt )).
    * luego nos disponemos a definir atributos personalizados:
    * newt.c_lflag &= ~ICANON; (elimina el modo canónico, esto es para no tener que pulsar enter al final)
    * newt.c_lflag &= ~ECHO; (esto evita que se represente el carácter correspondiente a la tecla. Eliminamos el eco)
    * tcsetattr( STDIN_FILENO, TCSANOW, &newt ); Aplicamos los cambios, establecemos nuestros nuevos atributos de la terminal.
    * ch = getchar(); Obtenemos la tecla
    * tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); Ponemos los atributos de la terminal como estaban antes.

    Espero que te haya quedado más claro.

    Muchas gracias por comentar!

Leave a Reply