Frage

Mögliches Duplikat:
Was entspricht getch() & getche() in Linux?

Ich bin ein Neuling in der Linux-Programmierung.:-)

Ich frage mich nur, ob mein Programm (mit C sprache) kann unter Linux jeden einzelnen Tastendruck sofort erfassen und dann entscheiden, ob er wiedergegeben werden soll oder nicht und wie er angezeigt werden soll, genau wie Telnet.

wenn ein Benutzer beispielsweise 'A' schlägt, möchte ich, dass das Programm 'B' anzeigt, wenn er 'B' eingibt, wird 'C' gewünscht und so weiter.

Es klingt lustig und nutzlos.Ich bin nur neugierig darauf.

War es hilfreich?

Lösung

Grundsätzlich hängt es stark davon ab, wie Sie sofort definieren.

Hier gibt es zwei Aufgaben.Die erste besteht darin, das reguläre Schlüsselecho zu deaktivieren, das in den meisten C-Eingabebibliotheken integriert ist.Die zweite besteht darin, das neue Zeichen anstelle des alten auszudrucken.

Im Pseudocode.

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

Es gibt eine Reihe von Systemen, die kommunizieren, um einen Tastendruck zu erfassen.

  1. Tastatur
  2. (möglicherweise) ein USB-Bus
  3. Der CPU-Interrupt-Handler
  4. Betriebssystem
  5. Der X Window Server Prozess
  6. Das X "Fenster", das den Fokus hat.

Der letzte Schritt wird mit einem Programm ausgeführt, das eine Endlosschleife ausführt, die Ereignisse vom X-Server erfasst und verarbeitet.Wenn Sie dieses Programm auf bestimmte Weise erweitern möchten (ermitteln Sie, wie lange die Taste gedrückt wurde), müssen Sie den anderen Programmen mitteilen, dass Sie "rohe" Tastaturereignisse wünschen, was bedeutet, dass Sie nicht wirklich vollständig empfangen werden "gekochte" Zeichen.Daher müssen Sie nachverfolgen, welche Tasten auf und ab sind und wie lange, und mit dem seltsamen Verhalten von Metaschlüsseln in Ihrem Programm umgehen (das ist kein 'a', sondern ein 'A', weil Shift ist unten usw.).

Es sind auch andere Verarbeitungsmodi zu berücksichtigen, z. B. kanonische und nicht kanonische, die steuern, ob die Ereignisse in zeilenorientierten Blöcken (Zeilenereignisse) oder zeichenorientierten Blöcken (Zeichenereignisse) empfangen werden sollen.Dies wird wiederum etwas kompliziert durch die Notwendigkeit, die Upstream-Programme auf die Anforderungen des Downstream-Clients aufmerksam zu machen.

Nachdem Sie nun eine Vorstellung von Ihrer Umgebung haben, sehen wir uns den eigentlichen Code an, der zum Unterdrücken der Zeichenausgabe erforderlich ist.

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

Auch das ist nicht sofort.Um sofort zu werden, müssen Sie näher an die Quelle heranrücken, was letztendlich ein Kernelmodul bedeutet (das immer noch nicht so unmittelbar ist wie der Tastatur-Mikrocontroller, der nicht so unmittelbar ist wie der Moment, in dem der Schalter tatsächlich schließt).Mit genügend Elementen zwischen der Quelle und dem Ziel wird es schließlich möglich, den Unterschied zu bemerken, aber in der Praxis wurde an diesem Code viel von Leuten gearbeitet, die den besten Kompromiss zwischen Leistung und Flexibilität suchen.

Andere Tipps

Edwin Buck lieferte eine großartige Antwort.Hier ist eine andere Alternative, die verwendet ncurses das macht solche Dinge etwas einfacher und wird von fast jeder Linux-Distribution und anderen Unix-Varianten unterstützt.

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

kompilieren Sie mit GCC-Code.c -o Code -Flüche

Und hier sind einige unterstützende Links:

ncurses noecho und andere - manpage
ncurses Programmieranleitung

Dieser Code kann im Internet gefunden werden und ist von kermi3 vom c-Brett

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

BEARBEITEN: natürlich, wenn Sie das Zeichen selbst und nicht den ASCII-Wert erhalten möchten, ändern Sie zu char statt int

es mag übertrieben sein, aber Sie können Spielbibliotheken wie verwenden sdl um das zu erreichen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top