Come si cattura Ctrl + C in C?Catch Ctrl-C in C
risposta
Con un gestore di segnale.
Ecco un semplice esempio lanciando una bool
utilizzato in main()
:
#include <signal.h>
static volatile int keepRunning = 1;
void intHandler(int dummy) {
keepRunning = 0;
}
// ...
int main(void) {
signal(SIGINT, intHandler);
while (keepRunning) {
// ...
Modifica nel giugno 2017: Per GSA può interessare, in particolare quelli con una voglia insaziabile di modificare questa risposta. Guarda, ho scritto questa risposta sette anni anni fa. Sì, cambiano gli standard linguistici. Se davvero devi migliorare il mondo, per favore aggiungi la tua nuova risposta ma lascia il mio così com'è. Poiché la risposta ha il mio nome, preferirei che contenga anche le mie parole. Grazie.
http://www.google.com/#q=c+signal+handler – sbi
Abbastanza corretto ma la domanda era su Ctrl-C e risponde a questo - quindi non c'è bisogno di downvotare. –
Ok, abbastanza giusto. –
Controllare qui:
Nota: Ovviamente, questo è un semplice esempio che spiega solo come impostare un CtrlC gestore, ma come sempre ci sono regole che devono essere rispettate per non rompere qualcos'altro. Si prega di leggere i commenti qui sotto.
Il codice di esempio dall'alto:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
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
}
Non esiste una cosa come 'void main' ... –
@Derrick Agree,' int main' è una cosa appropriata, ma 'gcc' e altri compilatori lo compilano con un programma in esecuzione corretto sin dagli anni '90. Spiegato abbastanza bene qui: http://www.eskimo.com/~scs/readings/voidmain.960823.html - è fondamentalmente una "caratteristica", lo prendo così. –
@ icyrock.com: Tutto molto vero (per quanto riguarda void main() in C), ma quando pubblichi pubblicamente è probabilmente meglio evitare del tutto il dibattito usando int main() per non distrarlo dal punto principale. – Clifford
Impostare una trappola (si può intrappolare diversi segnali con un gestore):
signal (SIGQUIT, my_handler); signal (SIGINT, my_handler);
gestire il segnale come vuoi, ma essere consapevoli di limitazioni e trucchi:
void my_handler (int sig) { /* Your code here. */ }
Oppure si può mettere il terminale in modalità raw, come questo:
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);
Ora dovrebbe essere possibile leggere Ctrl +C sequenze di tasti utilizzando fgetc(stdin)
. Attenzione, però, perché con questo non si può Ctrl +Z, Ctrl +Q, Ctrl +S, ecc come normalmente più neanche.
Per quanto riguarda le risposte esistenti, tenere presente che la gestione del segnale dipende dalla piattaforma. Ad esempio, Win32 gestisce molti meno segnali rispetto ai sistemi operativi POSIX; see here. Mentre SIGINT è dichiarato in signals.h su Win32, consultare la nota nella documentazione che spiega che non farà ciò che ci si potrebbe aspettare.
Questo stampa appena prima di uscire.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
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);
}
Addendum relativo alle piattaforme UN * X.
Secondo la pagina signal(2)
uomo su GNU/Linux, il comportamento di signal
non è portatile come il comportamento di sigaction
:
Il comportamento del segnale() varia tra le versioni di UNIX, e ha anche varia storicamente attraverso diverse versioni di Linux. Evita l'uso di : usa invece sigaction (2).
Su Sistema V, il sistema non ha bloccato la consegna di ulteriori istanze del segnale e l'invio di un segnale reimposta il gestore su quello predefinito. In BSD la semantica è cambiata.
la seguente variazione della risposta precedente Dirk Eddelbuettel usa sigaction
anziché signal
:
#include <signal.h>
#include <stdlib.h>
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
}
}
Cound si prega di inviare un codice praticabile? –
[Dev'essere 'volatile sig_atomic_t' per essere ben definito] (https://stackoverflow.com/questions/37631153/how-to-clean-up-local-data-in-sigint-handler#comment62744362_37631288) – Eric
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
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;
}
I controlli funzione sig_handler se il valore dell'argomento passato è uguale al SIGINT, quindi printf è eseguito.
- 1. C# try-catch-else
- 2. @try - blocco catch in Objective-c
- 3. Utilizzo dei blocchi try/catch in C++
- 4. Catch Nan e Inf in Windows C++
- 5. try {} catch (...) {} in callback C - cattiva idea?
- 6. Assert in Try..Catch catch viene rilevato
- 7. aspettano in blocco catch
- 8. try/catch block in Arduino
- 9. Impossibile intercettare l'eccezione C++ utilizzando il catch (...)
- 10. C# catch (DataException) - nessuna variabile definita
- 11. Percorso catch catch di AngularJS?
- 12. C# - try/catch con l'espressione del predicato
- 13. Attributo C# per circondare con try - catch
- 14. Posso avere blocchi di try-catch nidificati in C++?
- 15. Catch stderr e stdout dal programma esterno in C++
- 16. C++ ottiene la descrizione di un'eccezione catturati in catch (...) bloccare
- 17. Quante volte dovrei usare try e catch in C#?
- 18. C#/Java "Try/Finally/Catch" costrutto equivalente in Delphi
- 19. Perché "try catch" in Objective-C causa perdite di memoria?
- 20. Gestione delle eccezioni try catch catch inside
- 21. Differenza tra catch (Exception) e Catch (eccezione ex)
- 22. Eccezione catch in unit test
- 23. try catch in finally section
- 24. Errore Catch 404 in MVC
- 25. on rejected catch in Promise
- 26. Prova catch token imprevisto
- 27. Gestione delle eccezioni C#, quale clausola catch da usare?
- 28. C#: Equivalente del try pitone/catch/altro blocco
- 29. Catch SIGINT in bash, handle AND ignora
- 30. C# Nested Prova le istruzioni oi metodi Catch?
Non c'è niente come segnali in C .... o almeno così ho pensato fino a quando ho letto lo standard C99. Si scopre che esiste una gestione del segnale definita in C, ma Ctrl-C non è obbligato a produrre alcun segnale specifico o alcun segnale. A seconda della piattaforma, questo potrebbe essere impossibile. – JeremyP
La gestione del segnale dipende principalmente dall'implementazione. Su piattaforme * nix, utilizza e, se sei su OSX, puoi sfruttare GCD per rendere le cose ancora più facili ~. –