Поймать Ctrl-C в C

Как поймать Ctrl + C в C?

С обработчиком сигнала.

Вот простой пример перебора bool используемого в main() :

 #include  static volatile int keepRunning = 1; void intHandler(int dummy) { keepRunning = 0; } // ... int main(void) { signal(SIGINT, intHandler); while (keepRunning) { // ... 

Редактировать в июне 2017 года : к кому это может относиться, особенно к тем, у кого ненасытное желание отредактировать этот ответ. Послушай, я написал этот ответ семь лет назад. Да, языковые стандарты меняются. Если вы действительно должны улучшить мир, добавьте свой новый ответ, но оставите мое, как есть. Поскольку ответ имеет мое имя на нем, я бы предпочел, чтобы он тоже содержал мои слова. Спасибо.

Проверить здесь:

Примечание. Очевидно, что это простой пример, объясняющий, как настроить обработчик Ctrl C , но, как всегда, существуют правила, которые необходимо соблюдать, чтобы не сломать что-то еще. Пожалуйста, прочитайте комментарии ниже.

Пример кода сверху:

 #include  #include  #include  void INThandler(int); int main(void) { signal(SIGINT, INThandler); while (1) pause(); return 0; } void INThandler(int sig) { char c; signal(sig, SIG_IGN); printf("OUCH, did you hit Ctrl-C?\n" "Do you really want to quit? [y/n] "); c = getchar(); if (c == 'y' || c == 'Y') exit(0); else signal(SIGINT, INThandler); getchar(); // Get new line character } 

Добавление к платформам UN * X.

Согласно signal(2) странице man в GNU / Linux, поведение signal не так переносимо, как поведение sigaction :

Поведение сигнала () варьируется в разных версиях UNIX и также исторически варьировалось в разных версиях Linux. Избегайте его использования: вместо этого используйте sigaction (2).

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

Следующий вариант предыдущего ответа Дирка Эддельбуэттеля использует sigaction вместо signal :

 #include  #include  static bool keepRunning = true; void intHandler(int) { keepRunning = false; } int main(int argc, char *argv[]) { struct sigaction act; act.sa_handler = intHandler; sigaction(SIGINT, &act, NULL); while (keepRunning) { // main loop } } 

Настройте ловушку (вы можете захватить несколько сигналов одним обработчиком):

 сигнал (SIGQUIT, my_handler);
 сигнал (SIGINT, my_handler);

Обращайтесь с сигналом, как хотите, но будьте осторожны с ограничениями и gotchas:

 void my_handler (int sig)
 {
   / * Ваш код здесь.  * /
 }

Или вы можете поместить терминал в необработанный режим, например:

 struct termios term; term.c_iflag |= IGNBRK; term.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF); term.c_lflag &= ~(ICANON | ECHO | ECHOK | ECHOE | ECHONL | ISIG | IEXTEN); term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; tcsetattr(fileno(stdin), TCSANOW, &term); 

Теперь нужно иметь возможность читать клавиши Ctrl + C с помощью fgetc(stdin) . Остерегайтесь использовать это, потому что вы не можете Ctrl + Z , Ctrl + Q , Ctrl + S и т. Д., Как обычно.

Что касается существующих ответов, обратите внимание, что обработка сигналов зависит от платформы. Win32, например, обрабатывает гораздо меньше сигналов, чем операционные системы POSIX; см. здесь . Хотя SIGINT объявлен в signal.h на Win32, см. Примечание в документации, в котором объясняется, что он не будет делать то, что вы ожидаете.

Это просто печать перед выходом.

 #include  #include  #include  void sigint_handler(int); int main(void) { signal(SIGINT, sigint_handler); while (1){ pause(); } return 0; } void sigint_handler(int sig) { /*do something*/ printf("killing process %d\n",getpid()); exit(0); } 
 #include #include #include void sig_handler(int signo) { if (signo == SIGINT) printf("received SIGINT\n"); } int main(void) { if (signal(SIGINT, sig_handler) == SIG_ERR) printf("\ncan't catch SIGINT\n"); // A long long wait so that we can easily issue a signal to this process while(1) sleep(1); return 0; } в #include #include #include void sig_handler(int signo) { if (signo == SIGINT) printf("received SIGINT\n"); } int main(void) { if (signal(SIGINT, sig_handler) == SIG_ERR) printf("\ncan't catch SIGINT\n"); // A long long wait so that we can easily issue a signal to this process while(1) sleep(1); return 0; } 

Функция sig_handler проверяет, соответствует ли значение переданного аргумента SIGINT, затем выполняется printf.

  • Отключение политики одного и того же происхождения в Safari
  • Как представить номер FLOAT в памяти на C
  • C - передача массива 2d в качестве аргумента функции?
  • Почему мы не можем использовать двойной указатель для представления двухмерных массивов?
  • Как я могу написать общий class контейнера, который реализует данный интерфейс в C #?
  • Где найти реализации функций stdio.h?
  • Программа для конверсии Фаренгейта в цель
  • Может ли sizeof (int) когда-либо быть 1 в размещенной реализации?
  • Является ли fmod () точным, когда y является целым числом?
  • Странное предупреждение компилятора C: предупреждение: «struct» объявлен в списке параметров
  • Почему strcmp () возвращает 0, когда его входы равны?
  • Давайте будем гением компьютера.