Jak mogę złapać zdarzenie ctrl-c?

134

Jak złapać zdarzenie Ctrl+ Cw C ++?

Scott
źródło
Aplikacja konsolowa, aplikacja windowsowa czy co?
GManNickG
7
Który system operacyjny Windows, Linux itp.
shf301
1
Cóż, to aplikacja Qt, ale uruchamiam ją z konsoli podczas programowania. (To jest Linux)
Scott,

Odpowiedzi:

175

signalnie jest najbardziej niezawodnym sposobem, ponieważ różni się implementacjami. Polecam używanie sigaction. Kod Toma wyglądałby teraz następująco:

#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;    
}
Gab Royer
źródło
1
Myślę, że my_handler powinien przyjąć int sargument. sig_tjest sam w sobie typem wskaźnika funkcji.
Matthew Marshall,
38
<stdlib.h> itd. - to jest C, a nie C ++. W C ++ powinieneś użyć <cstdlib>
Abyx,
8
printf()nie jest bezpieczny dla sygnału asynchronicznego, więc nie może być używany wewnątrz modułu obsługi sygnału.
PP
8
Te funkcje nie są dostępne w systemie Windows.
Timmmm
2
byłoby miło mieć jakieś wyjaśnienie dotyczące sa_maski sa_flags.
napisano
54

W przypadku aplikacji konsoli systemu Windows chcesz użyć SetConsoleCtrlHandler do obsługi CTRL+ Ci CTRL+ BREAK.

Zobacz tutaj przykład.

Chris Smith
źródło
40

Musisz złapać sygnał SIGINT (mówimy o POSIX, prawda?)

Zobacz odpowiedź @Gab Royer na sigaction.

Przykład:

#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;

}
Tomek
źródło
Tak, to POSIX. Zapomniałem dodać Linuksa do pytania.
Scott
3
signal () zachowuje się inaczej, w zależności od tego, czy jest zgodny ze stylem BSD czy SysV. sigaction () jest preferowana.
asveikau
3
Wiem, że jest stary, ale to nie kompiluje się w g ++ (Ubuntu 7.4.0-1ubuntu1 ~ 18.04.1) 7.4.0. Musiałem zmienić void my_handler(sig_t s)się void my_handler(sig_atomic_t s).
jcmonteiro
1

Tak, to jest pytanie zależne od platformy.

Jeśli piszesz program konsoli w systemie POSIX, użyj funkcji signal API ( #include <signal.h>).

W aplikacji WIN32 GUI powinieneś obsłużyć WM_KEYDOWNwiadomość.

Joyer
źródło