Как я могу поймать событие ctrl-c?

133

Как мне поймать событие Ctrl+ Cв C ++?

Скотт
источник
Консольное приложение, приложение Windows или что?
GManNickG
7
Какие ОС Windows, Linux и т. Д.
shf301,
1
Ну, это приложение Qt, но я запускаю его с консоли во время разработки. (Это Linux)
Скотт

Ответы:

172

signalне самый надежный способ, так как он отличается реализациями. Я бы порекомендовал использовать sigaction. Теперь код Тома будет выглядеть так:

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

void my_handler(int s){
           printf("Caught signal %d\n",s);
           exit(1); 

}

int main(int argc,char** argv)
{

   struct sigaction sigIntHandler;

   sigIntHandler.sa_handler = my_handler;
   sigemptyset(&sigIntHandler.sa_mask);
   sigIntHandler.sa_flags = 0;

   sigaction(SIGINT, &sigIntHandler, NULL);

   pause();

   return 0;    
}
Габ Ройер
источник
1
Я думаю, что my_handler следует рассматривать int sкак аргумент. sig_tсам по себе является типом указателя функции.
Мэтью Маршалл,
38
<stdlib.h> и т. д. - это C, а не C ++. В C ++ вы должны использовать <cstdlib>
Abyx
8
printf()не является безопасным для асинхронных сигналов, поэтому не может использоваться внутри обработчика сигналов.
PP
7
Эти функции недоступны в Windows.
Timmmm
2
было бы неплохо получить пояснения по поводу sa_maskи sa_flags.
Qed
53

Для консольного приложения Windows вы хотите использовать SetConsoleCtrlHandler для обработки CTRL+ Cи CTRL+ BREAK.

Смотрите здесь для примера.

Крис Смит
источник
40

Вы должны поймать сигнал SIGINT (мы ведь говорим о POSIX?)

См. Ответ @Gab Royer для подтверждения.

Пример:

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

void my_handler(sig_t s){
           printf("Caught signal %d\n",s);
           exit(1); 

}

int main(int argc,char** argv)
{
   signal (SIGINT,my_handler);

   while(1);
   return 0;

}
Том
источник
Да, это POSIX. Забыл добавить к вопросу Linux.
Скотт
2
signal () ведет себя по-разному, в зависимости от того, соответствует ли он стилю BSD или SysV. sigaction () предпочтительнее.
asveikau
2
Я знаю, что он старый, но он не компилируется в g ++ (Ubuntu 7.4.0-1ubuntu1 ~ 18.04.1) 7.4.0. Пришлось сменить void my_handler(sig_t s)на void my_handler(sig_atomic_t s).
jcmonteiro
1

Да, это вопрос, зависящий от платформы.

Если вы пишете консольную программу на POSIX, используйте signal API ( #include <signal.h>).

В приложении WIN32 GUI вы должны обработать WM_KEYDOWNсообщение.

Joyer
источник