Получить прерывание клавиатуры в C

Программа:

#include<stdio.h>
void main()
{
    int time=1800;
    while(1){
        system("clear");
        time-=1;
        printf("%d\n",time);
        sleep(1);
    if(time==0)
        pause();
    }
}

Вышеупомянутая программа останавливается, когда время достигает 0. Мое требование - во время выполнения программы. Если я нажму любую клавишу, например пробел или любую другую клавишу, программа будет приостановлена, и еще раз я нажму клавишу, программа возобновится. Поэтому для этого перед выполнением условия while мы отправляем обработчик сигнала прерывания клавиатуры. В C как это сделать.

Какая функция используется для получения прерывания клавиатуры. Я не хочу получать ввод от пользователя, я хочу обрабатывать прерывание, сгенерированное пользователем через клавиатуру.

Заранее спасибо..,


person mohangraj    schedule 04.09.2015    source источник
comment
Какая операционная система?   -  person kaylum    schedule 04.09.2015
comment
использовать сигнал sighandler_t (int signum, обработчик sighandler_t);   -  person venki    schedule 04.09.2015
comment
Существует библиотека signal.h для использования сигналов и их обработки. Используйте это и ^ это.   -  person vish4071    schedule 04.09.2015
comment
@venki и vish4071 Пожалуйста, расскажите, как можно использовать сигналы для нажатия клавиш. Я не знаю способа. Сигналы можно использовать для перехвата определенных комбинаций клавиш, таких как ctrl-c. Но вопрос, похоже, заключается в получении произвольных нажатий клавиш.   -  person kaylum    schedule 04.09.2015
comment
В Linux вы можете получать нажатия клавиш через подсистему ввода. Прочитайте об этом здесь. В основном открывается устройство ввода, такое как /dev/input/event0, которое соответствует клавиатуре. Затем события могут быть прочитаны с этого устройства. Каждое нажатие и отпускание клавиши будет генерировать событие.   -  person kaylum    schedule 04.09.2015
comment
ctrl и c не клавиши клавиатуры?   -  person venki    schedule 04.09.2015
comment
Я хочу обработать прерывание, сгенерированное пользователем через клавиатуру, что означает эта строка   -  person venki    schedule 04.09.2015
comment
@venki Это клавиши клавиатуры. Но это не единственные клавиши клавиатуры. Простой пример, как получить сигнал, когда пользователь нажимает пробел?   -  person kaylum    schedule 04.09.2015
comment
пробел больше не будет генерировать контрольный вопрос о прерывании   -  person venki    schedule 04.09.2015
comment
Давайте продолжим это обсуждение в чате.   -  person venki    schedule 04.09.2015
comment
mohan + @alanau: makelinux.net/ldd3/chp-6-sect-4   -  person rici    schedule 04.09.2015


Ответы (3)


Вам нужен conio.h для вашего требования. Он определяет kbhit() и getch(), которые ждут ввода с клавиатуры.

Всякий раз, когда вызывается kbhit(), он проверяет буфер клавиатуры и возвращает ненулевое значение, если в буфере есть какое-либо нажатие клавиши, в противном случае возвращается 0.

Conio.h используется компиляторами MSDOS и не является частью стандартных библиотек C (ISO). Он также не определен в POSIX.

#include<stdio.h>
#include<conio.h>

int main()
{
   while(1)
   {
       while(!kbhit())
       {
          //works continuously until interrupted by keyboard input.
          printf("M Tired. Break Me\n");
       }
       getch();
   }
   return 0;
}

Для Linux вы можете использовать следующий фрагмент для реализации kbhit(), используя fnctl() из fnctl.h для обработки сигналов:

  #include <termios.h>
    #include <unistd.h>
    #include <fcntl.h>


        int kbhit(void)
        {
          struct termios oldt, newt;
          int ch;
          int oldf;

          tcgetattr(STDIN_FILENO, &oldt);
          newt = oldt;
          newt.c_lflag &= ~(ICANON | ECHO);
          tcsetattr(STDIN_FILENO, TCSANOW, &newt);
          oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
          fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

          ch = getchar();

          tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
          fcntl(STDIN_FILENO, F_SETFL, oldf);

          if(ch != EOF)
          {
            ungetc(ch, stdin);
            return 1;
          }

          return 0;
        }
person Community    schedule 04.09.2015

Клавиатура не существует в чисто стандартных C99 или C11 (stdin не является клавиатурой и может быть pipe(7), так что это не всегда tty(4); вы можете прочитать из /dev/tty ...).

Так что это гораздо менее просто, чем вы хотите, и это зависит от операционной системы. Я ориентируюсь на линукс.

Узнайте больше о tty, в частности прочитайте разоблачение tty. Обратите внимание, что tty обычно находится в подготовленном режиме, когда ядро буферизует строки (в дополнение к буферизации строк stdin).

Разумным способом является использование терминальной библиотеки, такой как ncurses или readline. Эти библиотеки устанавливают tty в необработанном режиме (что вы можете сделать самостоятельно, см. это и termios(3); возможно, вам потребуется также poll(2)). Перед выходом обязательно правильно выйдите и сбросьте tty в режим приготовления.

Но ваша жизнь, вероятно, слишком коротка, чтобы погрузиться в termios(3) и tty_ioctl(4), поэтому просто используйте ncurses или readline

Вы также можете рассмотреть приложение с графическим интерфейсом (например, выше X11 или Wayland). Затем используйте набор инструментов (GTK, Qt, ...).

person Basile Starynkevitch    schedule 04.09.2015

Мое требование — во время выполнения программы. Если я нажму любую клавишу, например пробел или любую другую, программа будет приостановлена, и еще раз, когда я нажму клавишу, программа возобновится.

Вы можете добиться этого с помощью этого типа кода

#include <stdio.h>
int main()
{
  char i;int y=0;
  while(1)
  {
     if(!(_kbhit()))
     {
       y=0;
       printf("//key is not pressed");
       //do what you want
     }
     else
     {
       printf("key pressed (execution pause) , press again to resume");
       i=_getch();
       y=1;
     }
     if(y==1)
     {
       getch();
     }
  }
  return 0;
}
person udit043    schedule 04.09.2015
comment
_kbhit(), _getch(), где это объявлено, что означает, в каких заголовочных файлах они объявлены - person mohangraj; 04.09.2015
comment
Заголовок @mohan conio.h - person ameyCU; 04.09.2015
comment
@ameyCU conio.h доступен только в Windows. Я использую Ubuntu 12.04 - person mohangraj; 04.09.2015
comment
Вы можете отправить его в функцию, которая снова реализует ту же обработку прерывания, вместо getch(). - person vish4071; 04.09.2015
comment
@mohan Используйте curses, затем . См. этот вопрос. Будет полезно в этом случае - stackoverflow.com/questions/3276546/ - person ameyCU; 04.09.2015
comment
На виндовс 10 работает, спасибо! - person Christianidis Vasileios; 11.06.2021
comment
@ChristianidisVasileios хорошо :) - person udit043; 11.06.2021