0

有谁知道如何在没有库的情况下在 c++ 中创建事件循环?它不必是跨平台的,我在 Mac 上。基本上,我希望程序运行并且什么都不做,直到用户按下向上箭头键,然后程序将输出“你按下了”或其他东西。我能想到的只是有一个无限whilefor循环并使用 输入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() 一次读取单个字符。3) 暂时回显读取的字符(作为 int),以便您可以找到向上箭头键为您提供的内容。

至于更一般的事件循环问题,唯一的输入设备是键盘,你坐在一个循环中,每当键入一个键(在原始模式下?)你调用一个带有键入的键值的例程。如果您有更多输入设备,则需要多个线程,每个线程都可以监听不同的设备,将它们找到的内容放入队列中(使用适当的锁定)。然后,主循环将检查队列并在每次出现某些内容时适当地调用例程。

于 2012-03-29T17:36:14.173 回答
1

您可以使用ncurses并启用cbreak来获取原始输入流。

于 2012-03-29T17:39:25.177 回答
-1

I've used a while loop with signal handlers. Like this incomplete snippet.

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 shell 可以将程序放入后台也断开程序的标准输入与终端的连接,所以 AFAIK,这已成为不可能。


这不需要特定于 Mac。Mac 支持 *NIX 机制从键盘读取字符。

AFAICT 程序所做的所有事情都是在等待一个字符,所以它还不如阻塞。

通常,终端设备 tty(电传打字机!)在您的程序可以从标准输入读取它们之前解释在键盘上键入的字符。具体来说,tty 设备通常会缓冲整行文本,并截取 rubout 字符(以及一些其他字符,例如 CTRL+w)来编辑该行文本。这种对字符的预处理称为“行规”

您需要设置 tty 设备驱动程序来停止这样做!然后你可以得到用户输入的所有字符。

您可以在文件描述符上使用 ioctl 或 termios 更改设备。

搜索例如“ioctl tty line discipline raw”以了解详细信息,并查找程序示例。

您可以使用命令行程序将终端设置为“原始” stty。请阅读 stty 手册页,因为将其重新设置可能会有些棘手(注意:如果您犯了错误,杀死终端通常比尝试修复它更容易,因为您键入的任何内容都不会回显)

向上箭头可能不是单个字符,因此需要一次字节解码以避免在输入流中的错误点处阻塞,即如果某些输入序列是一个字符,而其他两个或三个字符,需要在每个字节处进行解码以确定是否有待处理的字节,或者可能发出过多的读取,这将导致程序阻塞。

于 2012-03-29T17:48:55.580 回答