0

ライブラリなしでC ++でイベントループを作成する方法を知っている人はいますか? クロスプラットフォームである必要はありません。私は Mac を使用しています。基本的に、ユーザーが上矢印キーを押すまでプログラムを実行して何もしないようにしたいのですが、プログラムは「あなたが押した」などを出力します。私が考えることができるのは、無限whileまたはforループを使用して入力を取得するcinことだけですが、矢印キーを検出できるとは思わずcin、「\ n」に達するまでプログラムを一時停止すると思います。

私はそれを次のようにしたいと思います:

void RUN()
{
   while(true)
   {
      // poll events and do something if needed
   }
}

int main()
{
   RUN();
}

スレッドがなくても可能だと確信しています。これは何かで達成できると聞いたことがありますが、どうすればよいfd_setかわかりません。

どんな助けでも本当に感謝しています。

編集:

イベントがない場合、プログラムはバックグラウンドで実行する必要があります。たとえば、Microsoft Word はユーザーがボタンを押すまで停止せず、実行を続けます。そのようなものが欲しいのですが、GUIではなくコマンドラインです。

4

4 に答える 4

1

あなたが話しているのはキーボード入力であり、Mac のルック アンド フィールを探しているわけではないので、必要なのは UNIX の方法です。つまり、

1)端末をrawモードまたはcbrkモードに設定します(どちらか忘れました)。2) read() を使用して、一度に 1 文字ずつ読み取るようになりました。3) 読み取った文字を (int として) 一時的にエコーし、上矢印キーで何が得られるかを確認します。

より一般的なイベント ループの質問については、唯一の入力デバイスがキーボードである場合、ループに座って、キーが入力されるたびに (raw モードで?)、入力されたキーの値でルーチンを呼び出します。より多くの入力デバイスがある場合は、それぞれが異なるデバイスをリッスンし、見つけたものを (適切なロックを使用して) キューに入れることができる複数のスレッドが必要になります。次に、メイン ループはキューをチェックし、キューに何かが現れるたびにルーチンを適切に呼び出します。

于 2012-03-29T17:36:14.173 に答える
1

ncursesを使用し、 cbreakを有効にして生の入力ストリームを取得できます。

于 2012-03-29T17:39:25.177 に答える
-1

シグナル ハンドラで while ループを使用しました。この不完全なスニペットのように。

void getSomething()
{
  std::cout << "Enter new step size: "; std::cout.flush();
  std::cin >> globalVariable;
  std::getchar();  // consume enter key.
}

void printCommands()
{
  std::cout << "1: do something\n"
        << "q: quit\n"
    << "h: help\n"
    << std::endl;
}

void getCommand()
{
  // Output prompt 
  std::cout << "Enter command ('h' for help): "; std::cout.flush();

  // Set terminal to raw mode 
  int ret = system("stty raw"); 

  // Wait for single character 
  char input = std::getchar(); 

  // Reset terminal to normal "cooked" mode 
  ret = system("stty cooked"); 

  std::cout << std::endl;

  if (input == 'h') printCommands();
  else if (input == '1') getSomething();
  else if (input == 'q') {
    g_next = true;
    g_quit = true;
  } 
}

void 
signalHandler(int signo)
{
  if (signo == SIGINT) {
    g_next = true;
  } else if (signo == SIGQUIT) {
    getCommand();
  }
}

int main(int argc, char* argv[])
{
  signal(SIGINT, signalHandler);
  signal(SIGUSR1, signalHandler);
  signal(SIGQUIT, signalHandler);

  do {
    // Stuff
  } while (!g_quit);

  exit(0);
}
于 2012-03-29T17:46:06.237 に答える
-1

質問が更新され、「プログラムはバックグラウンドで実行する必要がありますが、GUI ではなくコマンドラインで実行する必要があります。」

すべて伝統的です。*プログラムをバックグラウンドに置くことができるNIXシェルも、プログラムの標準入力を端末から切断するため、知る限り、これは不可能になりました。


これは Mac 固有である必要はありません。Mac は、キーボードから文字を読み取るための *NIX メカニズムをサポートしています。

AFAICTプログラムが行っていることはすべて文字を待っているため、ブロックすることもできます。

通常、端末デバイス tty (テレタイプ!) は、プログラムが標準入力から文字を読み取る前に、キーボードで入力された文字を解釈します。具体的には、tty デバイスは通常、テキスト行全体をバッファリングし、テキスト行を編集するために rubout 文字 (および CTRL+w などの他のいくつかの文字) をインターセプトします。この文字の前処理は「ラインディシプリン」と呼ばれます

それをやめるには、tty デバイスドライバーを設定する必要があります! 次に、ユーザーが入力したすべての文字を取得できます。

ファイル記述子で ioctl または termios を使用してデバイスを変更します。

詳細を理解し、プログラムの例を見つけるために、たとえば「ioctl tty 行規律 raw」を検索してください。

コマンド ライン プログラムを使用して、ターミナルを「raw」に設定できますstty。設定を元に戻すのは少し難しいので、stty の man ページを読んでください。

上向き矢印が単一の文字ではない可能性があるため、入力ストリームの間違ったポイントでのブロックを回避するために、一度にバイト単位でデコードする必要があります。 2 つまたは 3 つの文字の場合、保留中のバイトがあるかどうかを判断するために各バイトでデコードを行う必要があります。

于 2012-03-29T17:48:55.580 に答える