C ++ - Создание цикла событий - PullRequest
0 голосов
/ 29 марта 2012

Кто-нибудь знает, как сделать цикл обработки событий в 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 ]

1 голос
/ 29 марта 2012

Вы можете использовать ncurses и включить cbreak для получения необработанного входного потока.

1 голос
/ 29 марта 2012

Поскольку вы говорите о вводе с клавиатуры, а не ищете внешний вид Mac, вам нужен UNIX-способ. И это,

1) установить терминал в режиме raw или cbrk (я забыл, какой). 2) теперь используйте read () для чтения отдельных символов за раз. 3) временно отобразить прочитанный символ (как целое число), чтобы вы могли найти, что дает вам стрелка вверх.

Что касается более общего вопроса о цикле событий, когда единственным устройством ввода является клавиатура, вы сидите в цикле, и всякий раз, когда клавиша набирается (в необработанном режиме?), Вы вызываете подпрограмму со значением набранной клавиши. , Если бы у вас было больше устройств ввода, вам понадобилось бы несколько потоков, каждый из которых мог бы прослушивать разные устройства, помещая то, что они находят, в очереди (с соответствующей блокировкой). Затем основной цикл проверяет очередь и соответствующим образом вызывает процедуру каждый раз, когда в ней что-то появляется.

0 голосов
/ 29 марта 2012

Вопрос был обновлен: «Программа должна работать в фоновом режиме ... но командная строка не GUI».

Все традиционное; * Оболочки NIX, которые могут перевести программу в фоновый режим, также отключают стандартный ввод программы от терминала, так что, AFAIK, это стало невозможным.


Это не обязательно для Mac. Mac поддерживает * NIX механизмы для чтения символов с клавиатуры.

AFAICT все, что делает программа, ждет символа, так что она может также блокироваться.

Обычно терминальное устройство tty (телетайп!) Интерпретирует символы, набранные на клавиатуре, прежде чем ваша программа сможет прочитать их со стандартного ввода. В частности, устройство tty обычно буферизует всю строку текста и перехватывает символ удаления (и некоторые другие, такие как CTRL + w), чтобы редактировать строку текста. Эта предварительная обработка символов называется «дисциплиной линии»

Вам нужно установить драйвер устройства tty, чтобы прекратить это делать! Затем вы можете получить все символы, которые вводит пользователь.

Вы меняете устройство, используя ioctl или termios в файловом дескрипторе.

Поиск, например, "ioctl tty line дисциплина raw", чтобы понять детали и найти примеры программ.

Вы можете установить терминал в «raw», используя программу командной строки stty. Пожалуйста, прочитайте man-страницу stty, потому что ее установка может быть немного хитрой (NB: если вы допустили ошибку, часто проще убить терминал, чем пытаться исправить это, потому что нет ничего, что вы вводите)

Возможно, что стрелка вверх не является одиночным символом, поэтому потребуется некоторое побайтное декодирование, чтобы избежать блокировки в неправильной точке входного потока, т.е. если некоторые входные последовательности представляют собой один символ и другие два или три символа, декодирование должно происходить в каждом байте, чтобы решить, есть ли ожидающий байт, или может быть выдано слишком много чтения, что приведет к блокировке программы.

0 голосов
/ 29 марта 2012

Я использовал цикл 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);
}
...