8

重複の可能性:
Linuxのgetch()およびgetche()と同等のものは何ですか?

私はLinuxプログラミングの初心者です。:-)

私のプログラム(C言語を使用)がLinuxですべてのキーストロークをすぐにキャプチャし、それをエコーするかどうか、およびtelnetのように表示する方法を決定できるかどうか疑問に思います。

たとえば、ユーザーが「A」を押すと、プログラムに「B」が表示され、「B」と入力すると、「C」が必要になります。

それは面白くて役に立たないように聞こえます。気になるところです。

4

4 に答える 4

13

基本的に、すぐに定義する方法に大きく依存します。

ここには 2 つのタスクがあります。1 つ目は、ほとんどの C 入力ライブラリに組み込まれている通常のキー エコーを無効にすることです。2 つ目は、古い文字の代わりに新しい文字を出力することです。

擬似コードで。

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

キーの押下をキャプチャするために通信するシステムは多数あります。

  1. キーボード
  2. (おそらく) USB バス
  3. CPU 割り込みハンドラ
  4. オペレーティング システム
  5. X ウィンドウ サーバー プロセス
  6. フォーカスがある X の「ウィンドウ」。

最後のステップは、X サーバーからイベントを取得して処理する連続ループを実行するプログラムで行われます。このプログラムを特定の方法で拡張したい (キーが押された時間の長さを取得する) 場合は、「生の」キーボード イベントが必要であることを他のプログラムに伝える必要があります。 」の文字。その結果、上下にあるキーとその長さを追跡し、プログラム内のすべての奇妙なメタ キーの動作を処理する必要があります (これは 'a' ではなく、シフトが下にあるため 'A' です。等)。

イベントを行指向のチャンク (行イベント) で受信するか、文字指向のチャンク (文字イベント) で受信するかを制御する、正規および非正規など、考慮すべき他の処理モードもあります。これもまた、上流のプログラムに下流のクライアントの要件を認識させる必要があるため、多少複雑になります。

環境についてある程度理解できたので、文字出力を抑制するために必要な実際のコードをもう一度見てみましょう。

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

これでもすぐにはできません。すぐに取得するには、ソースに近づく必要があります。これは、最終的にはカーネル モジュールを意味します (それでも、スイッチが実際に閉じた瞬間ほどすぐではないキーボード マイクロコントローラーほどすぐではありません)。ソースと宛先の間に十分な項目があると、最終的に違いに気付くことができるようになりますが、実際には、このコードは、パフォーマンスと柔軟性の間の最適なトレードオフを求める人々によって多くの作業が行われています。

于 2012-10-03T14:51:25.487 に答える
6

Edwin Buckは素晴らしい回答を提供してくれました。ncursesこれは、そのようなことをもう少し簡単にし、ほぼすべての Linux ディストリビューションと他の 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);
}

gcc code.c -o code -lncurses でコンパイルします。

そして、ここにいくつかのサポートリンクがあります:

ncurses noecho およびその他 - man ページ
ncurses プログラミング HOWTO

于 2012-10-03T16:46:08.717 に答える
4

このコードはインターネットで見つけることができkermi3、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;
}

編集:もちろん、ASCII値ではなくchar自体を取得したい場合は、char代わりにに変更してくださいint

于 2012-10-03T14:34:41.873 に答える
0

やり過ぎかもしれませんが、sdlなどのゲームライブラリを使用してそれを実現できます。

于 2012-10-03T14:29:23.467 に答える