Domanda

Possibile duplicazione:
Che cosa è equivalente a getch () & getche () in Linux?

Sono un principiante nella programmazione linux.:-)

Mi chiedo solo se il mio programma (usando C lingua) in grado di catturare ogni singolo tratto di chiave immediatamente in linux, e quindi decidere se eco o no e come visualizzarlo, proprio come telnet.

ad esempio, se un utente colpisce 'A', voglio che il programma visualizzi 'B', se digita 'B', 'C' è voluto e così via.

Sembra divertente e inutile.Sono solo curioso.

È stato utile?

Soluzione

Fondamentalmente, dipende molto da come si definisce immediatamente.

Ci sono due compiti qui.Il primo è disabilitare il normale eco dei tasti che è integrato nella maggior parte delle librerie di input C.Il secondo è quello di stampare il nuovo personaggio invece di quello vecchio.

In pseudo codice.

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

Ci sono un certo numero di sistemi che comunicano per catturare una pressione di un tasto.

  1. Tastiera
  2. (possibilmente) un bus USB
  3. Il gestore interrupt CPU
  4. Il sistema operativo
  5. Il processo X window server
  6. La "finestra" X che ha il focus.

L'ultimo passaggio viene eseguito con un programma che esegue un ciclo continuo che cattura gli eventi dal server X e li elabora.Se si desidera espandere questo programma in determinati modi (ottenere il periodo di tempo in cui è stato premuto il tasto) è necessario dire agli altri programmi che si desidera che gli eventi della tastiera "raw", il che significa che non si riceveranno realmente caratteri completamente "cotti".Di conseguenza, dovrai tenere traccia di quali chiavi sono su e giù, e per quanto tempo, e gestire tutto lo strano comportamento della chiave meta nel tuo programma (non è una 'a' è una 'A' perché Shift è giù, ecc).

Ci sono anche altre modalità di elaborazione da considerare, come canoniche e non canoniche, che controlleranno se si desidera che gli eventi vengano ricevuti in blocchi orientati alla linea (eventi di linea) o blocchi orientati ai caratteri (eventi di carattere).Ancora una volta questo è un po ' complicato dalla necessità di rendere i programmi upstream consapevoli dei requisiti del client downstream.

Ora che hai un'idea del tuo ambiente, rivisitiamo il codice effettivo necessario per sopprimere l'output dei caratteri.

// 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);

Anche questo non è immediato.Per ottenere immediato, è necessario avvicinarsi alla fonte, che alla fine significa un modulo del kernel (che non è ancora immediato come il microcontrollore della tastiera, che non è immediato come il momento in cui l'interruttore si chiude effettivamente).Con abbastanza elementi tra l'origine e la destinazione, alla fine diventa possibile notare la differenza, tuttavia, in pratica questo codice è stato lavorato molto da persone che cercano il miglior compromesso tra prestazioni e flessibilità.

Altri suggerimenti

Edwin Buck ha fornito una grande risposta.Ecco un'altra alternativa che utilizza ncurses il che rende queste cose un po ' più facili ed è supportato su quasi tutte le distribuzioni Linux e altre varianti 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);
}

compilare con codice gcc.codice c-o-lncurses

E qui ci sono alcuni link di supporto:

ncurses noecho e altri-pagina man
ncurses programmazione HOWTO

Questo codice può essere trovato in Internet ed è di kermi3 di c-board

#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;
}

MODIFICARE: naturalmente che se si desidera ottenere il carattere stesso e non il valore ascii cambiare in char anziché int

potrebbe essere eccessivo ma puoi usare librerie di giochi come sdl per raggiungere questo obiettivo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top