Bagaimana saya bisa menangkap acara ctrl-c?

133

Bagaimana cara menangkap peristiwa Ctrl+ Cdi C ++?

Scott
sumber
Aplikasi konsol, aplikasi windows, atau apa?
GManNickG
7
Yang OS Windows, Linux, dll.
shf301
1
Ya, ini adalah aplikasi Qt, tapi saya menjalankannya dari konsol selama pengembangan. (Ini Linux)
Scott

Jawaban:

172

signalbukan cara yang paling dapat diandalkan karena berbeda dalam implementasi. Saya akan merekomendasikan menggunakan sigaction. Kode Tom sekarang akan terlihat seperti ini:

#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
sumber
1
Saya pikir my_handler harus mengambil int sargumen. sig_titu sendiri merupakan tipe pointer fungsi.
Matius Marshall
38
<stdlib.h>, dll - ini C, bukan C ++. Dalam C ++ Anda harus menggunakan <cstdlib>
Abyx
8
printf()tidak async-signal-safe, jadi tidak dapat digunakan di dalam handler sinyal.
PP
7
Fungsi-fungsi ini tidak tersedia di Windows.
Timmmm
2
akan menyenangkan untuk memiliki beberapa penjelasan tentang sa_maskdan sa_flags.
qed
52

Untuk aplikasi konsol Windows, Anda ingin menggunakan SetConsoleCtrlHandler untuk menangani CTRL+ Cdan CTRL+BREAK .

Lihat di sini untuk contoh.

Chris Smith
sumber
40

Anda harus menangkap sinyal SIGINT (kita berbicara POSIX kan?)

Lihat jawaban @Gab Royer untuk sigaction.

Contoh:

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

}
Tom
sumber
Ya, itu POSIX. Saya lupa menambahkan Linux ke pertanyaan.
Scott
2
signal () berperilaku berbeda, tergantung apakah itu mengikuti gaya BSD atau SysV. sigaction () lebih disukai.
asveikau
2
Saya tahu ini sudah tua, tetapi ini tidak dapat dikompilasi di g ++ (Ubuntu 7.4.0-1ubuntu1 ~ 18.04.1) 7.4.0. Saya harus pindah void my_handler(sig_t s)ke void my_handler(sig_atomic_t s).
jcmonteiro
1

Ya, ini adalah pertanyaan yang bergantung pada platform.

Jika Anda menulis program konsol pada POSIX, gunakan API sinyal ( #include <signal.h>).

Dalam aplikasi GUI WIN32 Anda harus menangani WM_KEYDOWNpesan.

Joyer
sumber