
@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!
^COu 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::signalPrimeiramente 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 + CEspero que tenha ajudado, para mais informações acesse uma documentação sobre o std::signal.