LINUX.ORG.RU

Работа с клавиатурой на Си

 ,


0

3

Всем привет! Имеем программу на си (без окна). В ней есть цикл. Мне нужно сделать работу с клавиатурой. Одна из задач это прерывание цикла и тем самым выход их программы. К примеру подойдет: функция отслеживающая нажатие клавиши и записывающая это действие в переменную. Наш цикл выполняется и дойдя до конца итерации проверяет значение переменной. На сайте искал, в гугле тоже, англоязычные ресурсы не предлагать. Интим тоже.


Разные варианты. Если вам нужно просто корректно прерывать программу, (только после цикла), то лучше сделать обработку сигналов (SIGTERM, SIGINT) и прерывать по Ctrl-C. Чтобы программу можно было корректно останавливать не только с терминала, но и через kill.

А если именно ловить нажатие клавиш (но оставаясь в рамках терминала), то getchar(), но у терминала нужно убирать канонический режим. Гуглите примеры с tcsetattr()/tcgetattr() с флагом ICANON.

mky ★★★★★
()

На сайте искал, в гугле тоже, англоязычные ресурсы не предлагать. Интим тоже.

Найми репетитором Павла [@LZai] Вениаминовича.

anonymous
()

читать с устройства ввода, что-то там в /dev/input*

Harald ★★★★★
()
Ответ на: удаленный комментарий

можно через select()

Harald ★★★★★
()

Сделай через дырявые иксы

И root-доступ не нужен!

$ cat x11shit.c
// x11shit.c -- Die X.Org shit!

#include <X11/XKBlib.h>
#include <X11/extensions/XInput2.h>

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void main(void) {
  Display *disp = XOpenDisplay(":0");
  int xiOpcode, queryEvent, queryError, major = 2, minor = 0;
  XQueryExtension(disp, "XInputExtension", &xiOpcode, &queryEvent, &queryError);
  XIQueryVersion(disp, &major, &minor);

  Window root = DefaultRootWindow(disp);
  XIEventMask m;
  m.deviceid = XIAllMasterDevices;
  m.mask_len = XIMaskLen(XI_LASTEVENT);
  m.mask = calloc(m.mask_len, sizeof(char));
  XISetMask(m.mask, XI_RawKeyPress);
  XISelectEvents(disp, root, &m, 1);
  XSync(disp, 0);
  free(m.mask);

  while ("X.Org is shit") {
    XEvent event;
    XGenericEventCookie *cookie = (XGenericEventCookie*)&event.xcookie;
    XNextEvent(disp, &event);
    if (XGetEventData(disp, cookie) && cookie->type == GenericEvent && cookie->extension == xiOpcode) {
      switch (cookie->evtype) {
        case XI_RawKeyPress: {
          XIRawEvent *ev = cookie->data;
          KeySym s = XkbKeycodeToKeysym(disp, ev->detail, 0, 0);
          if (s == NoSymbol) continue;
          char *str = XKeysymToString(s);
          if (str == NULL) continue;
          if (strncmp(str, "Escape", 6) == 0) {
            fprintf(stderr, "Esc получен. Выход из программы.\n", str);
            exit(0);
          } else
            fprintf(stderr, "В дырявые иксы утёк keyEvent: \'%s\'. Нажми \'Esc\' для выхода.\n", str);
        }
      }
    }
  }
}


$ gcc x11shit.c -lX11 -lXi
$ ./a.out 
В дырявые иксы утёк keyEvent: 'f'. Нажми 'Esc' для выхода.
В дырявые иксы утёк keyEvent: 'u'. Нажми 'Esc' для выхода.
В дырявые иксы утёк keyEvent: 'c'. Нажми 'Esc' для выхода.
В дырявые иксы утёк keyEvent: 'k'. Нажми 'Esc' для выхода.
Esc получен. Выход из программы.
EXL ★★★★★
()
Последнее исправление: EXL (всего исправлений: 3)
Ответ на: комментарий от anonymous

Его зовут Михаил Павлович Терентьев.

anonymous
()

функция отслеживающая нажатие клавиши

Посмотри как bind в bash устроен.

anonymous
()
31 октября 2021 г.

Тебе неблокирующий getch нужен что ли? Ну, дык это легко велосипедится.

Или можно ncurses для этого использовать (функция getkey()).

anonymous
()
Ответ на: комментарий от EXL

Пиздец решето. Но кстати в винде точно так же можно.

anonymous
()
Ответ на: Сделай через дырявые иксы от EXL

И, между прочим, это — не баг, а фича! Мне вот очень даже нравится, что в иксах именно так ввод работает.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.