Logo ITP-NEWS
RSS | Contatti | Login|Registrati| Home
giornali
Rubriche telefoniche con liste concatenate
Di Fusco Francesco::2011-03-17
Lo scopo di questo articolo è illustrare la progettazione di un software che gestisca la rubrica telefonica di uno smartphone. Per ogni contatto memorizzato in rubrica, sono presenti: nome, cognome, numero di telefono, indirizzo pagina web personale, indirizzo email.
Le funzioni di gestione da implementare sono almeno: inserimento contatto, ricerca numero contatto, eliminazione contatto, eliminazione di tutta la rubrica, visualizzazione di tutti i contatti.
Ecco il diagramma dei moduli del nostro programma:



I blocchi di livello inferiore sono procedure richiamate dai moduli di livello superiore.

La nostra lista sarà costituita da una sequenza di nodi aventi la seguente struttura:



La parte "informativa" del nodo, ovvero la parte che contiene le informazioni relative ad una voce della rubrica (il contatto) avrà la seguente struttura:



Dichiariamo la nostra struttura nodo (composta da informazioni + campo puntatore al nodo successivo) nel seguente modo:

struct contatto
{
char nome[25];
char cognome[25];
char telefono[18];
char web[80];
char email[40];
struct contatto *next;
};


Il campo "next" contiene l'indirizzo del prossimo nodo della lista al quale è collegato:



Per semplificare la dichiarazione del tipo di dato composto contatto usiamo l'istruzione typedef

typedef struct contatto Contatto;
typedef Contatto * ContattoPTR;


in questo modo, quando avremo la necessità di dichiarare una variabile di tipo contatto o un puntatore ad una variabile di tipo contatto, scriveremo semplicemente:

Contatto Cont;
ContattoPtr ContPtr;

invece di scrivere:

struct contatto Cont;
struct contatto * ContPtr;




// RUBRICA TELEFONICA CON LISTE CONCATENATE
/*
* (C) Copyright Di Fusco Francesco 2011-
*/
// Versione 0.3
#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#define FILERUBRICA "rubrica.txt"
// Dichiarazione della struttura
typedef struct contatto Contatto;
typedef Contatto * ContattoPTR;

struct contatto
{
char nome[25];
char cognome[25];
char telefono[18];
char web[80];
char email[40];
Contatto *next;
};

// Definizione del tipo Boolean
typedef enum {false,true} boolean;

/*
* Dichiarazione dei prototipi delle funzioni
*/
void menu(Contatto *rubrica);
void stampa_contatto(Contatto p);
void stampa_rubrica(Contatto *p);
Contatto *inserisci_contatto(Contatto *testa, Contatto p);
Contatto leggi_contatto(void);
Contatto *trova_contatto(Contatto *rubrica, char *telefono);
Contatto *inserimento_ordinato(Contatto *testa, Contatto pers);
Contatto *crea_contatto(Contatto p);
Contatto *elimina_contatto(Contatto *testa, char *cognome);
Contatto *cancella_rubrica(Contatto *rubrica);
void salva_rubrica(Contatto *testa);
Contatto *carica_rubrica(char *filename);

// Programma principale
int main()
{
Contatto *rubrica=NULL;// puntatore alla testa della lista della rubrica
menu(rubrica);
return 0;
}

/*
* Legge le informazioni relative ad un contatto in agenda
*/
Contatto leggi_contatto(void)
{
Contatto p;
printf("\nCognome:");scanf("%25s",&p.cognome);
printf("\nNome:");scanf("%25s",&p.nome);
printf("\nTelefono:");scanf("%18s",&p.telefono);
printf("\nweb:");scanf("%80s",&p.web);
printf("\nemail:");scanf("%40s",&p.email);
p.next=NULL;
return p;
}

/*
* Inserimento di un nodo in testa alla lista concatenata
*/
Contatto *inserisci_contatto(Contatto *testa, Contatto p)
{
Contatto *x=NULL;
x=(Contatto *) malloc(sizeof(struct contatto));
if(x!=NULL)
{
strcpy(x-> nome,p.nome);
strcpy(x->cognome,p.cognome);
strcpy(x->telefono,p.telefono);
strcpy(x->web,p.web);
strcpy(x->email,p.email);
x->next=testa;
}
return x; // x sarà il puntatore alla nuova testa della lista
}
/*
*Crea un nuovo nodo nella lista concatenata e lo inserisce in testa
*/
Contatto *crea_contatto(Contatto p)
{
Contatto *x=NULL;
x=(Contatto *) malloc(sizeof(struct contatto));
if(x!=NULL)
{
strcpy(x->nome,p.nome);
strcpy(x->cognome,p.cognome);
strcpy(x->telefono,p.telefono);
strcpy(x->web,p.web);
strcpy(x->email,p.email);
x->next=NULL;
}
return x; // x sarà il puntatore al nodo appena creato
}
// Stampa un contatto della rubrica
void stampa_contatto(Contatto p)
{
printf("Cognome:\t %s Nome:\t %s Telefono:\t %s web:\t %s email:\t %s\n",p.cognome,p.nome,p.telefono,p.web,p.email);
}
// Stampa tutti i contatti della rubrica
void stampa_rubrica(Contatto *testa)
{
Contatto *q=testa;
while(q!=NULL)
{
stampa_contatto(*q);
q=q->next;
}
}
// Funzione per la ricerca di un contatto tramite il numero telefonico
Contatto *trova_contatto(Contatto *rubrica, char *telefono)
{
Contatto *p=NULL;
boolean trovato=false;
p=rubrica;
while(p!=NULL && trovato==false)
{
if(strcmp(p->telefono,telefono)==0) trovato=true;
else
p=p->next;
}
return p;
}
// Inserimento in una lista ordinata
Contatto *inserimento_ordinato(Contatto *testa, Contatto pers)
{
Contatto *p=NULL, *precPtr=NULL, *corrente=NULL;
precPtr=testa;
corrente=testa;
if(corrente==NULL || strcmp(corrente->cognome,pers.cognome)>=0)
{
testa=inserisci_contatto(testa,pers);// Inserisce il nuovo contatto in testa alla lista
}
else {
while(corrente!=NULL && strcmp(corrente->cognome,pers.cognome)<0)
{
precPtr=corrente;
corrente=corrente->next;
}
p=crea_contatto(pers);// Crea un nuovo nodo da aggiungere alla lista, nel posto opportuno, per mantenere l'ordinamento
p->next=corrente;
precPtr->next=p;
}
return testa;
}
// Elimina un contatto dato un cognome
Contatto *elimina_contatto(Contatto *testa, char *cognome)
{
Contatto *precPtr=NULL,*currPtr=testa, *tmp=NULL;
while(currPtr!=NULL && strcmp(currPtr->cognome,cognome)!=0)
{
precPtr=currPtr;
currPtr=currPtr->next;
}
if (currPtr!=NULL) // L'elemento è stato trovato nella rubrica
{
tmp=currPtr;
// il record da eliminare è il primo della lista
if(currPtr==testa)
{
testa=currPtr->next;
}
// Il record da eliminare si trova tra due record
else
precPtr->next=currPtr->next;
}
return (testa);
}
// Elimina tutti i dati della rubrica e restituisce il puntatore NULL
Contatto *cancella_rubrica(Contatto *rubrica)
{
Contatto *currPtr=rubrica,*tmp=NULL;
while(currPtr!=NULL)
{
tmp=currPtr;
currPtr=currPtr->next;
free(tmp);
}
return NULL;
}
void salva_rubrica(Contatto *testa)
{
printf("Sto salvando la rubrica ...\n");
Contatto *ptrRubrica=testa;
FILE *filerubrica=fopen(FILERUBRICA,"w+");
if(filerubrica!=NULL)
{
printf("Il file è stato correttamente aperto\n");
while(ptrRubrica!=NULL)
{printf("%s %s %s %s %s\n",ptrRubrica->cognome,ptrRubrica->nome,ptrRubrica->telefono,ptrRubrica->web,ptrRubrica->email);
fprintf(filerubrica,"%s %s %s %s %s\n",ptrRubrica->cognome,ptrRubrica->nome,ptrRubrica->telefono,ptrRubrica->web,ptrRubrica->email);
ptrRubrica=ptrRubrica->next;

}
}
else
printf("Errore di apertura del file\n");
fclose(filerubrica);
}
Contatto *carica_rubrica(char *filename)
{
Contatto *ptrRubrica=NULL;
Contatto utente;
FILE *filerubrica=fopen(FILERUBRICA,"r");
if(filerubrica!=NULL)
{
printf("Il file è stato correttamente aperto\n");
while(!feof(filerubrica))
{
fscanf(filerubrica,"%s %s %s %s %s\n",&utente.cognome,&utente.nome,&utente.telefono,&utente.web,&utente.email);
ptrRubrica=inserimento_ordinato(ptrRubrica,utente);
}
}
else
printf("Errore di apertura del file\n");
fclose(filerubrica);
return ptrRubrica;
}
// Listdelete.c
//FUNZIONE MENU: GESTISCE L'ATTIVAZIONE DELLE VARIE FUNZIONI ATTRAVERSO UN MENU' INTERATTIVO
void menu(Contatto *rubrica)
{
int opz=0;
Contatto p;
Contatto *pers=NULL;
char telefono[18];
char cognome[25];
printf ("*RUBRICA TELEFONICA CON LISTE CONCATENATE*\n");
do{
printf ("\nScegli una delle seguenti opzioni\n");
printf ("1)Inserisci nuovo contatto ........\n");
printf ("2)Cerca un contatto:...............\n");
printf ("3)Elimina un contatto..............\n");
printf ("4)Visualizza rubrica...............\n");
printf ("5)Elimina rubrica..................\n");
printf ("6)Salva rubrica....................\n");
printf ("7)Carica rubrica...................\n");
printf ("8)Esci.............................\n");
printf ("Scelta:............................");
scanf ("%d", &opz);
switch(opz)
{
case 1:
printf("Inserisci contatto\n");
p=leggi_contatto();
rubrica=inserimento_ordinato(rubrica,p);
break;
case 2:
printf ("\nRICERCA CONTATTO\n");
printf("Telefono:"); scanf("%s",&telefono);
pers=trova_contatto(rubrica,telefono);
if(pers!=NULL) stampa_contatto(*pers);
else
printf("Numero inesistente\n");
break;
case 3:
printf ("\nELIMINAZIONE CONTATTO\n");
printf("Cognome:"); scanf("%s",cognome);
rubrica=elimina_contatto(rubrica,cognome);
break;
case 4:
stampa_rubrica(rubrica);
break;
case 5:
// Elimina tutti i nodi della lista (la rubrica) e restituisce il puntatore NULL
rubrica=cancella_rubrica(rubrica);
case 6:
// Salva la rubrica su un file di testo
if(rubrica!=NULL)
salva_rubrica(rubrica);
else
printf("Errore: la lista è vuota\n");
break;
case 7:
// Carica la rubrica du un file di testo
rubrica=carica_rubrica(FILERUBRICA);
break;
case 8:
printf ("\nUSCITA DAL PROGRAMMA\n");
break;
system ("PAUSE");
default: //stampa a video un messaggio di avviso nel caso in cui si scelga un opzione a cui non corrisponde una funzione
printf ("\nL'OPZIONE NON E' SUPPORTATA.\n");
}
}while (opz!=8);
}