Como posso capturar um pressionamento de tecla imediatamente no linux?[duplicado]

StackOverflow https://stackoverflow.com//questions/12710582

  •  13-12-2019
  •  | 
  •  

Pergunta

Possíveis Duplicados:
O que é equivalente a getch() & getche() no Linux?

Eu sou um novato em linux e programação.:-)

Eu só quero saber se o meu programa (usando C idioma) pode capturar cada pressionamento de tecla imediatamente em linux e, em seguida, decidir se a eco-lo ou não e como exibi-lo, assim como o telnet.

por exemplo, se um usuário greves 'Um', eu quero que o programa para exibir 'B', se ele digita 'B', 'C' é procurado, e assim por diante.

Soa engraçado e inútil.Eu só estou curioso para saber sobre isso.

Foi útil?

Solução

Basicamente, ele depende muito de como você definir imediatamente.

Há duas tarefas aqui.A primeira é desativar a tecla eco que é incorporado na maioria dos C bibliotecas de entrada.A segunda é para imprimir o novo personagem, em vez do antigo.

Em pseudo-código.

 echo(off);
 while (capturing && charIsAvailable()) {
   c = readOneChar();
   if (c == '\n') {
     capturing = false;
   }
   printf("%c", c++);
 }
 echo(on);

Há uma série de sistemas de comunicação para capturar uma tecla.

  1. O teclado
  2. (possivelmente) um barramento USB
  3. A CPU processador de interrupção
  4. O sistema operacional
  5. O X window processo do servidor
  6. O X da janela"," que tem o foco.

O último passo é feito com um programa que é executado um loop contínuo, captura de eventos do servidor X, e processa-os.Se você queria expandir este programa de determinadas maneiras (obter o comprimento de tempo que a tecla foi pressionada) você precisa dizer a outros programas que você deseja "raw" eventos de teclado, o que significa que você realmente não vai estar recebendo totalmente "cozinhado" caracteres.Como resultado, você terá que manter o controle de quais chaves são para cima e para baixo, e por quanto tempo, e tratar de todos os ímpares meta o comportamento de uma tecla em seu programa (que não é um 'a' é 'A' porque mudança é baixo, etc).

Há também outros modos de processamento para considerar, como canônicos e não-canônicos, que irá controlar se você deseja que os eventos a serem recebidos em linha orientada a blocos (linha de eventos) ou de carácter orientado a blocos (personagem de eventos).Novamente, este é um pouco complicado pela necessidade de se fazer a montante programas cientes das exigências do cliente descendentes.

Agora que você tem uma idéia do seu ambiente, vamos rever o código necessário para suprimir a saída de caracteres.

// define a terminal configuration data structure
struct termios term;

// copy the stdin terminal configuration into term
tcgetattr( fileno(stdin), &term );

// turn off Canonical processing in term
term.c_lflag &= ~ICANON;

// turn off screen echo in term
term.c_lflag &= ~ECHO;

// set the terminal configuration for stdin according to term, now
tcsetattr( fileno(stdin), TCSANOW, &term);


(fetch characters here, use printf to show whatever you like)

// turn on Canonical processing in term
term.c_lflag |= ICANON;

// turn on screen echo in term
term.c_lflag |= ECHO;

// set the terminal configuration for stdin according to term, now
tcsetattr( fileno(stdin), TCSANOW, &term);

Mesmo que isso não é imediata.Para obter imediata, você precisa para chegar mais perto da fonte, o que, eventualmente, significa que um módulo do kernel (que ainda não é tão imediata como o teclado do micro-controlador, o que não é tão imediata como o momento em que o interruptor na verdade, fecha).Com bastante itens, entre a origem e o destino, eventualmente, torna-se possível perceber a diferença, no entanto, na prática, este código tem sido trabalhado muito por pessoas que estão buscando o melhor equilíbrio entre desempenho e flexibilidade.

Outras dicas

Edwin Buck desde uma grande resposta.Aqui é outra alternativa que utiliza ncurses o que torna as coisas um pouco mais fácil e é compatível com quase todas as distribuições de Linux e outras variantes de Unix.

#include <ncurses.h>

int main(int argc, char *argv[])
{
    int ch,c;
    initscr();
    cbreak();
    noecho();

    while( ch != 'q')
    {
        switch( c = getch() )
        {
            case 'a':
                ch = 'b';
            break;

            case 'b':
                ch = 'c';
            break;

            case 'c':
                ch = 'd';
            break;

            default:
                ch = c;                 
            break;
        }
        printw("%c",ch);
    }
    endwin();
    return(0);
}

compilar com o gcc código.c-o código -lncurses

E aqui estão alguns links de apoio:

em ncurses noecho e outros - o homem da página
em ncurses de programação COMO

Este código pode ser encontrado na internet e é por kermi3 a partir de c-conselho

#include <termios.h>
#include <unistd.h>

int mygetch(void)
{
    struct termios oldt,newt;
    int ch;
    tcgetattr( STDIN_FILENO, &oldt );
    newt = oldt;
    newt.c_lflag &= ~( ICANON | ECHO );
    tcsetattr( STDIN_FILENO, TCSANOW, &newt );
    ch = getchar();
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
    return ch;
}

EDITAR: é claro que se você deseja obter o char em si, e não o valor ascii alteração char em vez de int

Pode ser exagero, mas você pode usar bibliotecas de jogos como sdl para conseguir isso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top