La tua attività richiede un ciclo di eventi basato su select
o epoll
. Un evento che aspetterebbe è l'input dell'utente - quando STDIN_FILENO
diventa pronto per la lettura. Un altro è il timer periodico di 1 secondo quando è necessario interrogare il controller.
Esistono alcune librerie che implementano un ciclo di eventi per te in modo che tu possa concentrarti su quali eventi devi gestire e come. libevent
è uno dei più vecchi, ricco di funzionalità e popolare.
Credo che il modo "Unix" non sarebbe quello di chiedere l'input dell'utente, ma di reagire a un segnale dell'utente. Ad esempio, quando l'utente preme Ctrl-C, il processo attualmente in esecuzione riceve SIGINT.
Un esempio di come utilizzare correttamente SIGINT per interrompere un loop può essere trovato qui. Copiandolo nella risposta nel caso in cui il collegamento diventi obsoleto:
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static volatile sig_atomic_t got_signal = 0;
static void my_sig_handler(int signo)
{
got_signal = 1;
}
int main()
{
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = &my_sig_handler;
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction");
return EXIT_FAILURE;
}
for (;;) {
if (got_signal) {
got_signal = 0;
printf("Received interrupt signal!\n");
}
printf("Doing useful stuff...\n");
sleep(1); /* Sleep is not only useful, it is essential! */
}
return EXIT_SUCCESS;
}
(nel tuo caso sarebbe una buona idea mettere break;
nel if
bloccare o usare while(!got_signal)
)
La risposta semplice è il multi-threading, in cui è stato distribuito il thread per attendere l'input dell'utente, mentre il ciclo continua. Quindi prendi questo:
char flag = 1;
while (flag) {
// run the loop
// if thing happens deploy the thread which will ask user for input
}
Non ho fatto threading per un po', penso che questa pagina sarebbe meglio di me che te lo spiego:https://randu.org/tutorials/threads/