@terminalroot Como Mapear o 'Ctrl + c' com C++ #cpp #cplusplus #programacao #programming #code ♬ original sound - terminalroot
Ás vezes precisamos devolver algo ao sistema quando finalizamos um programa, mas pode ser que o usuário matou o processo antes do fim do mesmo sem ser de uma maneira esperada.
Acontece muito em programas que possuem um loop while
com tarefas a serem executadas para o final esperado!
Suponhamos que vc possua esse código que emite um aviso no início do programa e após 5 segundos o programa termina e emite outro aviso:
#include <iostream>
#include <memory>
#include <chrono>
#include <thread>
void msgOut(){
std::cout << "Terminou a contagem dos 5 segundos." << '\n';
}
class CountTime {
void m_start_count(){
std::this_thread::sleep_for(std::chrono::seconds(5));
}
public:
CountTime(){
std::cout << "Começou a contagem dos 5 segundos!" << '\n';
this->m_start_count();
}
~CountTime(){
msgOut();
}
};
int main(){
auto ct = std::make_unique<CountTime>();
return 0;
}
Após você compilar e rodar, após 5 segundos apareceram essas duas mensagens na saída:
Começou a contagem dos 5 segundos!
Terminou a contagem dos 5 segundos.
Agora suponhamos que antes do fim dos 5 segundos, você pressione Ctrl + c
, a segunda mensagem não aparecerá e a saída ficará assim:
Começou a contagem dos 5 segundos!
^C
Ou seja, se seu programa tem uma função para ser executada sempre que o programa terminar, logo, ele gerará um bug silencioso.
Para resolver isso, podemos mapear o sinal enviado e executar determinada tarefa mesmo que o programa seja interrompido antes do seu fim esperado de forma comum.
std::signal
Primeiramente vamos incluir o cabeçalho:
#include <csignal>
Criar uma função de callback que tratará o signal, fora da execução da nossa classe:
void signal_handler(int signal) {
if (signal == SIGINT) {
msgOut();
std::exit(EXIT_SUCCESS);
}
}
E startar ele no construtor, ou antes do início de um suposto loop
que executaremos!
std::signal(SIGINT, signal_handler);
O código final será:
#include <iostream>
#include <memory>
#include <chrono>
#include <thread>
#include <csignal> // incluir
void msgOut(){
std::cout << "Terminou a contagem dos 5 segundos." << '\n';
}
// Nossa função para tratamento do signal
void signal_handler(int signal) {
if (signal == SIGINT) {
msgOut();
std::exit(EXIT_SUCCESS);
}
}
class CountTime {
void m_start_count(){
std::this_thread::sleep_for(std::chrono::seconds(5));
}
public:
CountTime(){
std::signal(SIGINT, signal_handler); // Configurando o tratamento do signal
std::cout << "Começou a contagem dos 5 segundos!" << '\n';
this->m_start_count();
}
~CountTime(){
msgOut();
}
};
int main(){
auto ct = std::make_unique<CountTime>();
return 0;
}
Após compilar e rodar, após teclar Ctrl + c
, agora a saída será:
Começou a contagem dos 5 segundos!
^CTerminou a contagem dos 5 segundos.
Note que após o Ctrl + c
(^C
) a mensagem apareceu normalmente!
while
#include <iostream>
#include <csignal>
void signal_handler(int signal) {
if (signal == SIGINT) {
std::cout << "Você pressinou: Ctrl + C\n";
std::exit(EXIT_SUCCESS);
}
}
auto main() -> int {
std::signal(SIGINT, signal_handler);
while (true){}
}
Saída após
Ctrl + c
:
^CVocê pressinou: Ctrl + C
Espero que tenha ajudado, para mais informações acesse uma documentação sobre o std::signal
.