#include #include #include /* ANSI C vuole che tutte le struct abbiano nome */ typedef struct { char nome[31]; char cognome[31]; int g; int m; int a; int hasEmail; /* se TRUE allora c'e' l'email */ union { struct { char uname[51]; char domain[51]; } email; /* email */ struct { int pref_int; char prefisso[6]; double numero; } tel; /* telefono */ } et; /* email o telefono */ } Voce; /* prototipi delle funzioni */ int fine( char riga[]); int add( char riga[], Voce agenda[], int * quanti); int del( char riga[], Voce agenda[], int * quanti); int print( char riga[], Voce agenda[], int quanti); int prox( char riga[], Voce agenda[], int quanti); int sort_nome( char riga[], Voce agenda[], int quanti); int sort_cognome(char riga[], Voce agenda[], int quanti); int sort_compl( char riga[], Voce agenda[], int quanti); void print_voce(Voce * voce); #define NUMVOCI 20 #define MAXLINE 201 #define FALSE 0 #define TRUE 1 /* Programma principale */ int main(int argc, char* argv[]) { char riga[MAXLINE] = { 0 }; /* buffer per l'ultima riga letta */ Voce agenda[NUMVOCI] = { 0 }; /* vettore di NVOCI (20) voci */ int quanti = 0; /* numero di voci inserite */ int found = FALSE; /* leggo tutta una riga (al max MAXLINE caratteri) */ scanf("%200[^\n]",riga); /* continuo finche' non arriva il comando 'fine' */ while (!fine(riga)) { found = FALSE; found |= add(riga,agenda,&quanti); found |= del(riga,agenda,&quanti); found |= prox(riga,agenda,quanti); found |= print(riga,agenda,quanti); found |= sort_nome(riga,agenda,quanti); found |= sort_cognome(riga,agenda,quanti); found |= sort_compl(riga,agenda,quanti); /* if (!found) printf("comando non riconosciuto\n"); */ scanf("\n%200[^\n]",riga); } return FALSE; } /* Riconosco il comando 'fine' torno TRUE se l'ho riconosciuto */ int fine(char riga[]) { return (0==strcmp(riga,"fine")); } /* Riconosco ed eseguo i comandi 'add tel ' 'add email ' torno TRUE se l'ho riconosciuto */ int add(char riga[], Voce agenda[], int *quanti) { Voce nuova = { 0 }; /* nuova voce (variabile locale) */ char * dot = NULL; /* indice dell'ultimo carattere '.' nell'email */ /* uso due buffer di appoggio per contenere (a turno) la parte della linea non ancora esaminata */ char resto[MAXLINE] = { 0 }; /* resto della linea ancora non esaminata */ char resto1[MAXLINE] = { 0 }; /* resto della linea ancora non esaminata */ /* riconosciamo il comando (seguito da almeno uno spazio) */ if (1 != sscanf(riga,"add%*[ ]%[^\n]", resto)) return FALSE; /* riconosciamo il nome (seguito da almeno uno spazio) */ if (2 != sscanf(resto,"\"%30[^\"]\"%*[ ]%[^\n]", nuova.nome, resto1) && 2 != sscanf(resto,"%30[^ ]%*[ ]%[^\n]", nuova.nome, resto1)) { printf("nome errato\n"); return FALSE; } /* riconosciamo il cognome (seguito da almeno uno spazio) */ if (2 != sscanf(resto1,"\"%30[^\"]\"%*[ ]%[^\n]", nuova.cognome, resto) && 2 != sscanf(resto1,"%30[^ ]%*[ ]%[^\n]", nuova.cognome, resto)) { printf("cognome errato\n"); return FALSE; } /* riconosciamo la data (seguita da almeno uno spazio) */ if (4 != sscanf(resto,"%d-%d-%d%*[ ]%[^\n]", &nuova.g, &nuova.m, &nuova.a, resto1)) { printf("data errata\n"); return FALSE; } /* controlliamo il valore dei campi della data (tutti mesi da 31 giorni) */ if (nuova.g < 1 || nuova.g > 31 || nuova.m < 1 || nuova.m > 12 || nuova.a < 0 || nuova.a > 9999) { printf("data errata\n"); return FALSE; } /* poi vediamo se seguira' l'email o il telefono */ if (1 == sscanf(resto1,"email%*[ ]%[^\n]",resto)) { nuova.hasEmail = TRUE; /* leggiamo l'email (e non ci aspettiamo altri caratteri dopo) */ if (2 != sscanf(resto,"%46[^@ ]@%48[^@ ]%[^\n]", nuova.et.email.uname, nuova.et.email.domain, resto1)) { printf("email errata\n"); return FALSE; } /* controllo che non sia troppo lunga */ if (strlen(nuova.et.email.uname)+strlen(nuova.et.email.domain)+1>50) { printf("email errata\n"); return FALSE; } /* controllo che il 'domain' contenga almeno un punto preceduto e seguito da qualcosa */ dot = rindex(nuova.et.email.domain,'.'); /* puntatore all'ultimo '.' */ if (dot == NULL || /* se non lo trovo */ dot == nuova.et.email.domain || /* o e' all'inizio */ 1 == strlen(dot)) { /* o e' alla fine */ printf("email errata\n"); return FALSE; } } else { if (1 == sscanf(resto1,"tel%*[ ]%[^\n]",resto)) { nuova.hasEmail = FALSE; /* leggiamo il telefono (e non ci aspettiamo altri caratteri dopo) */ if (3 != sscanf(resto,"+%d-%5[0-9]-%d%[^\n]", &nuova.et.tel.pref_int, nuova.et.tel.prefisso, &nuova.et.tel.numero, resto1) || nuova.et.tel.pref_int>999 || nuova.et.tel.pref_int<=0 || nuova.et.tel.numero>9999999999.0 || nuova.et.tel.numero<=0) { printf("telefono errato\n"); return FALSE; } } else { printf("comando errato\n"); return FALSE; } } if (*quanti == NUMVOCI) printf("piena\n"); else agenda[(*quanti)++] = nuova; /* trovato */ return TRUE; } /* Riconosco ed eseguo il comando 'del ' torno il numero di elementi cancellati */ int del(char riga[], Voce agenda[], int *quanti) { char nome[31] = { 0 }; char cognome[31] = { 0 }; int cancellati = 0, i, j; /* uso due buffer di appoggio per contenere (a turno) la parte della linea non ancora esaminata */ char resto[MAXLINE] = { 0 }; /* resto della linea ancora non esaminata */ char resto1[MAXLINE] = { 0 }; /* resto della linea ancora non esaminata */ /* riconosciamo il comando (seguito da almeno uno spazio) */ if (1 != sscanf(riga,"del%*[ ]%[^\n]", resto)) return FALSE; /* riconosciamo il nome (seguito da almeno uno spazio) */ if (2 != sscanf(resto,"\"%30[^\"]\"%*[ ]%[^\n]", nome, resto1) && 2 != sscanf(resto,"%30[^ ]%*[ ]%[^\n]", nome, resto1)) { printf("nome errato\n"); return FALSE; } /* riconosciamo il cognome (non seguito da altri caratteri) */ if (1 != sscanf(resto1,"\"%30[^\"]\"%[^\n]", cognome, resto) && 1 != sscanf(resto1,"%30[^ ]%[^\n]", cognome, resto)) { printf("cognome errato\n"); return FALSE; } /* cerco tutte le voci che corrispondono */ for (i=0; i<(*quanti)-cancellati; i++) if (0==strcmp(agenda[i].nome, nome) && 0==strcmp(agenda[i].cognome,cognome)) { /* ogni voce trovata viene stampata */ /* print_voce(&agenda[i]); */ /* e le successive vengono spostate indietro di un posto */ for (j=i+1; j<(*quanti); j++) agenda[j-1]=agenda[j]; cancellati++; } if (0==cancellati) printf("nessuna\n"); (*quanti) -= cancellati; return TRUE; } /* Riconosco ed eseguo la stampa di tutta la tabella (o di 'nessuna') torno TRUE se l'ho riconosciuto */ int print(char riga[], Voce agenda[], int quanti) { int i; if (0!=strcmp(riga,"print")) return FALSE; for (i=0; ihasEmail) sprintf(lastcolumn, "%s@%s", v->et.email.uname, v->et.email.domain ); else sprintf(lastcolumn, "+%d-%0.5s-%d", v->et.tel.pref_int, v->et.tel.prefisso, v->et.tel.numero ); /* stampo la riga della tabella */ printf("|%30.30s|%30.30s|%02d-%02d-%04d|%-50.50s|\n", v->nome, v->cognome, v->g, v->m, v->a, lastcolumn); } /* Riconosco ed eseguo il comando 'prox ' */ int prox( char riga[], Voce agenda[], int quanti) { int g = 0; int m = 0; int i, j, trovato=0; /* uso due buffer di appoggio per contenere (a turno) la parte della linea non ancora esaminata */ char resto[MAXLINE] = { 0 }; /* resto della linea ancora non esaminata */ char resto1[MAXLINE] = { 0 }; /* resto della linea ancora non esaminata */ /* riconosciamo il comando */ if (1 != sscanf(riga,"prox%*[ ]%[^\n]", resto)) return FALSE; /* riconosciamo la data di nascita */ if (2 != sscanf(resto,"%2d-%2d%[^\n]", &g, &m, resto1)) { printf("data errata\n"); return FALSE; } /* controlliamo i due valori (tutti mesi da 31 giorni) */ if (g < 1 || g > 31 || m < 1 || m > 12 ) { printf("data errata\n"); return FALSE; } /* per fare i conti faccio partire il numero del giorno e del mese da 0 */ g--; m--; /* considero i mesi tutti lunghi 31 giorni */ for (i=0;i<12*31 && trovato==0;i++) for (j=0; jnome, y->nome); } /* confronto tra due voci per determinare quale cognome viene prima */ int surname_compare(const void * xx, const void * yy) { Voce * x = (Voce *) xx; Voce * y = (Voce *) yy; return strcmp(x->cognome, y->cognome); } /* confronto tra due voci per determinare quale compleanno viene prima */ int birthday_compare(const void * xx, const void * yy) { Voce * x = (Voce *) xx; Voce * y = (Voce *) yy; if (x->m < y->m) return -1; if (x->m > y->m) return +1; if (x->g < y->g) return -1; if (x->g > y->g) return +1; return 0; } /* Riconosco ed eseguo il comando 'sort nome' */ int sort_nome( char riga[], Voce agenda[], int quanti) { if (0!=strcmp(riga,"sort nome")) return FALSE; qsort(agenda, quanti, sizeof(Voce), name_compare); return TRUE; } /* Riconosco ed eseguo il comando 'sort cognome' */ int sort_cognome(char riga[], Voce agenda[], int quanti) { if (0!=strcmp(riga,"sort cognome")) return FALSE; qsort(agenda, quanti, sizeof(Voce), surname_compare); return TRUE; } /* Riconosco ed eseguo il comando 'sort compleanno' */ int sort_compl( char riga[], Voce agenda[], int quanti) { if (0!=strcmp(riga,"sort compleanno")) return FALSE; qsort(agenda, quanti, sizeof(Voce), birthday_compare); return TRUE; } /******************************* fine *********************************/