Allora, per capire questo codice commentato bisogna che tu sappia la differenza tra dichiarazione e definizione, conosca i puntatori a funzione, sappia cosa sia una struct, sappia cosa sia un array, sappia cosa sia una variabile globale, sappia cosa sia l'inizializzazione statica.
Se non conosci qualcuna di queste definizioni chiedi, è molto utile conoscerle, soprattutto parlando tra programmatori (d'altronde quando esci con gli amici o con la ragazza avrai poche occasioni di parlare di puntatori o di strutture
)
codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
QUA SOTTO [B]DICHIARO[B] LE FUZIONI CHE RISPONDONO
ALL'EVENTO RICHIAMATO DALL'UTENTE
se ad esempio l'utente scrive "aiuto" viene richiamata
la funzione help.
*/
int fai_questo(void * args);
int fai_quello(void * args);
int esci(void * args);
int help(void*args);
/*
Siccome in C non esistono nella libreria array associativi,
mi creo una struttura in cui memorizzare la corrispondenza
tra il comando dell'utente e la funzione da fare partire
in risposta al comando
ad esempio
MAP.key <- "aiuto"
MAP.trigger <- help()
Se l'utente digita "aiuto" il programma saprà
di dovere fare partire la funzione help
*/
typedef struct _MAP
{
/*parola chiave del menu*/
char * key;
/*puntatore alla funzione da lanciare*/
int (* trigger )(void*args);
} MAP;
/*
Dichiaro una variabile globale di tipo array di MAP
e la inizializzo staticamente mappando i nomi dei comandi
con le funzioni da lanciare in risposta ai comandi
e la chiamo Menu
*/
MAP Menu[] = {
{"opzione1", fai_questo},
{"opzione2", fai_quello},
{"aiuto", help},
{"esci", esci}
};
/* +++++++++++++++++++++++++++++++++
DEFINIZIONE HANDLER DI EVENTO
QUA SOTTO [B]DEFINISCO[B] LE FUZIONI CHE RISPONDONO
ALL'EVENTO RICHIAMATO DALL'UTENTE
se ad esempio l'utente scrive "aiuto" viene richiamata
la funzione help.
*/
int fai_questo(void * args)
{
printf("ho fatto questo\n");
return 0;
}
int fai_quello(void * args)
{
printf("ho fatto quello\n");
return 0;
}
int esci(void * args)
{
exit(0);
}
int help(void*args)
{
unsigned i, nelem = sizeof(Menu) / sizeof(MAP);
printf ("==================\n"
"Elenco dei comandi\n"
"==================\n");
for(i=0; i<nelem; ++i)
{
printf("%s\n", Menu[i].key);
}
printf ("\n");
return 0;
}
/* +++++++++++++++++++++++++++
FINE DEFINIZIONE HANDLER DI EVENTO
*/
int main()
{
/*dichiaro uno spazio in memoria dove contenere
max 1024 caratteri digitati alla tastiera*/
char buffer[1024];
/*
nelem:= numero di elementi nell'array Menu
i:= contatore nel ciclo for
*/
unsigned nelem, i;
/*
calcolo quanti elementi ci sono in Menu
siccome sizeof restituisce la dimensione in byte, per sapere
quanti elementi ci sono in Menu devo dividere la sua dimensione
in byte per la dimensione in byte di un singolo elemento, cioè
la dimensione in byte di MAP
*/
nelem = sizeof(Menu) / sizeof(MAP);
/*
stampa lo schermo di help
*/
help(NULL);
/*
ciclo infinito
*/
while(1)
{
/*leggi max 1023 caratteri da input (per evitare stack overflow)
e inseriscili nella variabile buffer.
*/
scanf("%1023s", buffer);
/*
per ogni elemento del MENU
*/
for(i=0; i<nelem; ++i)
{
/*
strcmp(stringa1, stringa2) restituisce 0 se due
stringhe sono uguali.
per cui !strcmp(stringa1, stringa2) restituisce non zero
se due stringhe sono uguali, per cui, siccome l'if viene
eseguito quando l'espressione tra parentesi è non zero,
significa che il corpo dell'if viene eseguito solo se
le due stringhe sono uguali.
Nella fattispecie confronto l'i-esima parola chiave del
menu, con la stringa letta da tastiera
*/
if(!strcmp(buffer, Menu[i].key))
{
/*
avendo trovato una parola chiave, lancio il comando
corrispondente (che è il comando i-esimo.
*/
Menu[i].trigger(NULL);
/*esce dal ciclo for, dal momento che ha gia trovato
il risultato.
*/
break;
}
}
}
}