4

raw ターミナル モードで入力を受け取るチャット クライアントがありますが、このモードでの入力の処理についてはわかりません。私は2つのことを知る必要があります:

  • 入力を文字単位で読み取って表示するにはどうすればよいですか? 一度に 1 文字ずつ読み取り、バッファに格納する読み取りループが必要ですか?
  • サーバーに新しい行エントリの入力を処理させたい場合、バッファに入るたびに各文字をスキャンして探す必要があり\nますか?

また、フラッシュする文字単位の読み取りループの例は、\n非常に興味深いものです。ありがとう!

4

2 に答える 2

6

Windows には非常に便利な関数 kbhit() がありますが、残念ながら Linux にはありません。これには複数の方法があります。Linux 用に独自の kbhit() メソッドを作成します。kbhit() は、入力バッファーで何かが検出された場合、ゼロ以外の値を返します。それ以外の場合は、0 を返し、次に進みます。簡単に言えば、ノンブロッキングです。結果が true の場合は常に getch() メソッドを呼び出して、押されたキーをフェッチします。

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>

void changemode(int);
int  kbhit(void);
int main(void)
{
  int ch;
  changemode(1);
  while ( !kbhit() );      // Waiting for some keyboard input.

  // something has been detected. now get that.
  ch = getchar();

  printf("\nGot %c\n", ch);

  changemode(0);
  return 0;
}

void changemode(int dir)
{
  static struct termios oldt, newt;

  if ( dir == 1 )
  {
    tcgetattr( STDIN_FILENO, &oldt);
    newt = oldt;
    newt.c_lflag &= ~( ICANON | ECHO );
    tcsetattr( STDIN_FILENO, TCSANOW, &newt);
  }
  else
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt);
}

int kbhit (void) 
{
  struct timeval tv;
  fd_set rdfs;

  tv.tv_sec = 0;
  tv.tv_usec = 0;

  FD_ZERO(&rdfs);
  FD_SET (STDIN_FILENO, &rdfs);

  select(STDIN_FILENO+1, &rdfs, NULL, NULL, &tv);
  return FD_ISSET(STDIN_FILENO, &rdfs);

}
于 2012-10-29T21:07:18.777 に答える
5

これにはGNU readline ライブラリをお勧めします。入力の行を取得するという面倒な作業を処理し、ユーザーがバックスペース、左右の矢印などを使用して行を編集したり、上矢印を使用して古いコマンドを呼び出したり、^R を使用して古いコマンドを検索したりできるようにします。など。Readline は、Linux などの典型的な UNIX ライクなディストリビューションにインストールされていますが、持っていない場合は、ここで見つけることができます。

編集: これは最小限の readline の例です:

#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>

int main(int argc, char ** argv)
{
    while(1)
    {
        char * line = readline("> ");
        if(!line) break;
        if(*line) add_history(line);
        /* Do something with the line here */
    }
}

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

readline を使用できない場合は、代わりに getline を使用できます。

#include <stdio.h>
int main()
{
    char * line = NULL;
    size_t len;
    while(getline(&line, &len, stdin) >= 0)
       printf("I got: %s", line);
}

getline でさえ受け入れられない場合は、fgets を使用できます。適切なサイズのバッファーを動的に割り当てないため、長すぎる行は切り捨てられます。しかし、少なくともそれは標準の C です:

#include <stdio.h>
int main()
{
    char buf[1000];
    while(fgets(buf, sizeof(buf), stdin)
        printf("I got: %s, line);      
}
于 2012-10-29T00:05:55.247 に答える