/***************************************
  PROGRAMMA "GESTIONE CONTRAVVENZIONI"
  PROGETTO C++ - DICEMBRE 2008
  by DAMIANO MILANI - damianomilani.com        
****************************************/


/**********
 LIBRERIE
**********/

#include <iostream.h>   
#include <stdlib.h>  
#include <fstream.h>    //per gestione file
#include <string.h>     //funzioni stringhe
#include <iomanip.h>    //contiene manipolatori setprecision e setw
#include <math.h>       //contiene funzioni matematiche



/**************************
  DEFINIZIONE TIPI UTENTE
**************************/

struct DATA {                            //per utilizzare DATA come tipo di dato astratto
       short int giorno;
       short int mese;
       short int anno;
};

struct DATI_ANAGRAFICI {
       unsigned long int cod_anagraf;    //identificatore univoco
       char cognome[32];
       char nome[32];
       DATA data_di_nascita;
       char indirizzo[32];
       char citta[32];
       char provincia[3];
       char cap[6];
       char codice_fiscale[18];
       char num_patente[11];      
};

struct NODO_ANAGRAF {                    //unità elementare della lista dati anagrafici
       DATI_ANAGRAFICI dati_anagraf;
       NODO_ANAGRAF *next_anagraf;       //puntatore a nodo successivo della lista
};

struct CONTRAVVENZIONE {
       unsigned long int num_contravv;   //da incrementare in auto, identificatore UNIVOCO!
       DATA data_contravv; 
       char luogo[64];
       char targa[8]; 
       char tipo[128];
       double importo;
       bool flag_anagraf_ins; 
       NODO_ANAGRAF *proprietario;          //collegamento tra le liste
       bool flag_pagam_eff;   
       DATA data_pagam;
};

struct NODO_CONTRAVV {                     //nodo della lista di contravvenzioni
       CONTRAVVENZIONE dati_contravv;
       NODO_CONTRAVV *next_contravv;       //puntatore per nodo successivo della lista  
};




/********************
 PROTOTIPI FUNZIONI
********************/

//Funzioni per gestione dei dati in input/output
int maiusc(char *par);                    //trasforma i caratteri alfabetici minuscoli nei corrispondenti maiuscoli
int ins_str(char *str, int n_car);        //chiede una stringa e il num caratteri che si vogliono memorizzare chiudendo con /0
int ins_txt(char *txt,int num_car);       //chiede una stringa e controlla che sia composta da soli caratteri alfabetici
int ins_num(char *num,int num_car);       //chiede una stringa e controlla che sia composta da soli caratteri numerici
int ins_int(int *intero);                 //legge una stringa e la trasforma in intero
int ins_double(double *decimale);         //legge una stringa e restituisce un double (usare printf("%4.2f\n",decim); per gli importi)
int ins_data(DATA *data);                 //chiede una data e ne controlla la validità
void vis_data(DATA data);                 //scrive una data
int ordine_data(DATA data1, DATA data2);  //passate due date determina quella che è venuta prima
int ins_cf(char *cf);                     //chiede un codice fiscale e ne controlla il formato
int ins_pat(char *pat);                   //chiede una stringa e controlla la conformità alla sintassi di un numero di patente
int trnk_str(char *str, int n_car);       //chiude una stringa quando incotra due spazi consecutivi



//Funzioni per gestire le due liste dinamiche
NODO_ANAGRAF *ins_anagraf(NODO_ANAGRAF *lista_a);              //inserisce un nodo di dati anagrafici in fondo alla lista e lo collega alla contravvenzione corrispondente
                                                                          //restituisce 0 se va a buon fine, -1 se la memoria è esaurita
int vis_anagraf(NODO_ANAGRAF *lista_a, NODO_ANAGRAF *cursore);            //visualizza i dati anagrafici collegati a una contravvenzione
                                                                          //estituisce 0 se va a buon fine, 1 se non li trova, -1 se lista vuota
int ins_contravv(NODO_CONTRAVV *lista_contravv);                          //inserisce una contravvenzione in fondo alla lista delle contravvenzioni
                                                                          //restituisce -1 se memoria esaurita, 0 se va a buon fine
int vis_contravv(NODO_CONTRAVV *lista_contravv, unsigned long int index); //visualizza la contravvenzione numero index
                                                                          //restituisce 0 se trovata, 1 se non è stata trovata, -1 in caso di lista vuota         
int vis_pagam(NODO_CONTRAVV *lista_c, unsigned long int indice);          //visualizza le contravvenzioni senza pagamento
                                                                          //ritorna 0 se è stata trovata la contravvenzione, 1 contravv inesistente, -1 lista vuota
int ins_pagam(unsigned long int indice);                                  //inserisce la data di un pagamento
                                                                          //ritorna 0 se ok, 1 se già registrato o se mancano dati anagrafici, -1 lista vuota o elemento inesistente


                                   
//Funzioni di modifica/cancella per le liste
int mod_pagam(NODO_CONTRAVV *lista_c, unsigned long int indice);  //restituisce 1 se non modificato, -1 se non viene trovata la contravvenzione, 0 se modificato
int canc_pagam(NODO_CONTRAVV *punt, unsigned long int index);     //cancella la data di un pagamento e cambia valore alla flag; ridà 0 se data eliminata, 1 se interrotto da utente, -1 se errore
int mod_anagraf(NODO_ANAGRAF *lista_a, unsigned long int codice); //modifica dati anagrafici corrispondenti a un codice: ritorna 0 se nodo modificato
int canc_anagraf(unsigned long int index);                        //cancella i dati anagrafici di codice index, eliminando tutti i riferimenti ad essi dalla lista di contravvenzioni
int mod_contravv(NODO_CONTRAVV *lista_c);                         //modifica i dati di una contravvenzione sovrascrivendoli
                                                                  //ritorna 0 se nodo modificato, 1 nodo non modificato, -1 contravvenzione non trovata
int canc_contravv();                                              //elimina la contravvenzione e risistema la lista
                                                                  //non vengono passate variabili, è necessario utilizzare la variabile globale per eventuali modifiche alla testa della lista
NODO_ANAGRAF* anagraf_doppia(NODO_ANAGRAF *punt);                 //controlla che non siano già presenti i dati punt nella lista di dati anagrafici: restituisce l'indirizzo di questi se presenti, altrimenti indirizzo dei dati in esame



//Funzioni di ricerca e statistica
int bilancio(NODO_CONTRAVV *lista); //calcola i totali degli importi delle multe restituisce 1 se non esistono contravvenzioni

int cerca_no_anagraf(NODO_CONTRAVV *listaC);  //cerca le contravvenzioni a cui non sono ancora stati associati dati anagrafici; ritorna 1 se si raggiunge la fine della lista  

int cerca_no_pagam(NODO_CONTRAVV *listaC);    //cerca le multe non pagate; ritorna 1 se si raggiunge la fine della lista



//Funzioni per gestire i file
int carica(); //caricamento dei dati (da due file a relative liste dinamiche)
              //ritorna 0 se caricamento a buon fine, 1 se caricam fallito, -1 memoria esaurita
int salva();  //salvataggio dei dati (scaricamento delle due liste su file)
              //ritorna 0 se salvataggio a buon fine, 1 fallito, -1 interrotto da utente



//Funzioni per l'interfaccia a menu
void menu_principale(); //scelta delle operazioni (chiede il caricamento dei dati nel caso l'utente non lo faccia da solo)
void menu_contravv();   //scelta operazioni da fare su contravvenzioni
void menu_anagraf();    //operazioni da compiere sui dati anagrafici
void menu_pagam();      //scelta operazioni relative ai pagamenti
void menu_cerca();      //scelta di funzioni per statistica e ricerca
void esci();            //permette di uscire dal programma e chiede se deve salvare



/*********************************
 DICHIARAZIONE VARIABILI GLOBALI
*********************************/

NODO_ANAGRAF *lista_anagraf;      //testa della lista delle contravvenzioni
NODO_CONTRAVV *lista_contravv;    //testa lista dei dati anagrafici
char nome_file_c[128], nome_file_a[128]; //nomi file contenenti rispettivamente dati contravvenzioni e dati anagrafici



/**********
 COSTANTI
**********/

#define pathfile_c "dati/contravvenzioni.txt"   //file di default per dati delle contravvenzioni
#define pathfile_a "dati/anagrafica.txt"        //file di default per dati anagrafici





/*******
  MAIN 
*******/

int main()
{
 system("CLS");
 system("COLOR 9E");   //colori del carattere e dello sfondo del terminale
 cout<< "                  ----------------------------------------\n"
        "                   PROGETTO IN C++ - by DAMIANO MILANI \n"
        "                  ----------------------------------------\n";
 cout<<"  ___________________________________________________________________________\n";
 cout<<"\n                   === Gestione Contravvenzioni v1.0 ===\n\n";
 menu_principale();
 cout<<"\nGrazie per aver utilizzato Gestione Contravvenzioni\n\n\t\t\t\tDamiano Milani\n\n\n";
 system("PAUSE");
 return 0;   
}



/**********************
 DEFINIZIONI FUNZIONI
**********************/

//Funzione maiusc: trasforma i caratteri alfabetici minuscoli nei corrispondenti maiuscoli (di modo da standardizzare l'input)
int maiusc(char *par)
{
    int i,k=strlen(par);
    for(i=0;i<k;i++) 
    if (par[i]>='a'&&par[i]<='z')        //il carattere viene visto anche come numero (secondo il codice ASCII)
       par[i]+='A'-'a'; //'A'-'a'=-32
    return 0; //restituisce 0 se va a buon fine
}


//Funzione ins_str: funzione di ingresso stringa per evitare problemi che possono insorgere con la funzione standard cin.getline()
int ins_str(char* str,int n_car)      //n_car è un carattere in meno della dimensione della stringa
{
    char str_lunga[512];
    cin.getline(str_lunga,511);
    strncpy(str,str_lunga,n_car);
    str[n_car]='\0';             //carattere di fine stringa
    return 0;                    //restituisce 0 se va a buon fine
}


//Funzione ins_txt: chiede una stringa e controlla che sia composta da soli caratteri alfabetici o spazi
int ins_txt(char* txt,int num_car)
{
      int i,k;
      bool flag=false;
      do {
         if (flag)
            cout<<"Il testo inserito contiene caratteri non validi, prego riprovare"<<endl;         
         ins_str(txt,num_car);
         k=strlen(txt);
         flag=false;
         for (i=0;i<k;i++)
             if ((txt[i]<'A'||txt[i]>'Z'&&txt[i]<'a'||txt[i]>'z')   //lettere min/maiusc
                   && !(txt[i]>=-126&&txt[i]<=-105)                //vocali accentate (à=-123 è=-118 ì=-115 ò=-107 ù=-105 é=-126) 
                   && (txt[i]!=' '))
                flag=true;                    //flag diventa true quando il testo non è esatto
         }while(flag);
      return 0;                               //restituisce 0 se va a buon fine
}


//Funzione ins_num: chiede una stringa e controlla che sia composta da soli caratteri numerici
int ins_num(char* num, int num_car)
{
      int i,k;
      bool flag=false;
      do {
         if (flag)
            cout<<"Il valore numerico inserito contiene caratteri non validi, prego riprovare"<<endl;
         ins_str(num,num_car);
         k=strlen(num);
         flag=false;
         for (i=0;i<k;i++)
             if (num[i]<'0'||num[i]>'9') 
                flag=true; //flag diventa true quando il testo nn è esatto
         }while(flag);
      return 0;            //restituisce 0 se va a buon fine
}


//Funzione ins_int: chiede e controlla una stringa e la trasforma in un numero intero
int ins_int(int *intero)
{
      int i,k;
      bool flag=false;
      char str_int[64];
      do {
         if (flag)
            cout<<"Il valore numerico inserito contiene caratteri non validi, prego riprovare"<<endl;
         ins_str(str_int,64);
         k=strlen(str_int);
         flag=false;
         for (i=0;i<k;i++)
             if (str_int[i]<'0'||str_int[i]>'9')
                flag=true;
         }while(flag);
      *intero=atol(str_int);
      return 0; //restituisce 0 se va a buon fine
}


//Funzione ins_double: chiede e controlla una stringa e la trasforma in un numero in virgola mobile
int ins_double(double *decimale)
{
      int i,k;
      bool flag=false;
      char str_decim[65];
      do {
         if (flag)
            cout<<"Il valore numerico inserito contiene caratteri non validi, prego riprovare"<<endl;
         ins_str(str_decim,64);
         k=strlen(str_decim);
         flag=false;
         for (i=0;i<k;i++)
             if ((str_decim[i]<'0'||str_decim[i]>'9')&&str_decim[i]!='.')
                flag=true;
         }while(flag);
      *decimale=atof(str_decim);
      return 0; //restituisce 0 se va a buon fine
}



//Funzioni di gestione per il formato DATA
//Funzione ins_data: chiede una data e ne controlla la validità
int ins_data(DATA *data)
{
      char str[64],buffer[5];
      int i,k,g,m,a;
      bool flag=false;
      do {                                //il ciclo si ripete finchè la data non è corretta
         if (flag)
            cout<<"La data  inserita non e' corretta, prego riprovare (formato gg/mm/aaaa)"<<endl;
         flag=false;
         ins_str(str,63);
         k=strlen(str);
         if (k!=10) {                                 //controllo del formato
                    flag=true; 
                    continue;
         }
         for (i=0;i<k;i++)
             if (i==2||i==5) {
                if (str[i]!='/') {
                   flag=true; 
                   continue;
                   }
             }
             else if (str[i]<'0'||str[i]>'9') {
                  flag=true; 
                  continue;
             }
         for (i=0;i<6;i++)                             //inizializzazione variabile buffer
             buffer[i]=0;
         for (i=0;i<2;i++)                             //estrazione dalla variabile stringa dei dati
             buffer[i]=str[i];
         g=atoi(buffer);
         for (i=3;i<5;i++)
             buffer[i-3]=str[i];
         m=atoi(buffer);
         for (i=6;i<10;i++)
             buffer[i-6]=str[i];
         a=atoi(buffer);
         if (!(m>0 && m<=12)) {
                   flag=true; 
                   continue;
         }
         if (m==2) {                                  //controllo febbraio (eventualmente bisestile)
            if ((a%4==0 && a%100!=0) || a%400==0) {
              if (!(g>0 && g<=29)) {
                 flag=true; 
                 continue;
              }
            }
            else if (!(g>0 && g<=28)) {
                 flag=true; 
                 continue;
            }     
         }
         else if (m==4||m==6||m==9||m==11) {          //controllo dei mesi con 30gg
                 if (!(g>0 && g<=30)) {
                    flag=true; 
                    continue;
                 }
         }
         else if (!(g>0 && g<=31)) {                  //controllo mesi con 31gg
              flag=true; 
              continue;
         }         
      }while(flag);
      data->giorno=g;                                 //salvataggio dei valori
      data->mese=m;
      data->anno=a;
      return 0; //restituisce 0 se va a buon fine
}


//Funzione vis_data: visualizza una data trattandola come dato astratto
void vis_data(DATA data) {
     cout<<data.giorno<<"/"<<data.mese<<"/"<<data.anno<<endl;          
}


//Funzione ordine_data: determina quale delle due date passate viene prima (ritorna 0 se la prima, 1 la seconda, -1 sono uguali)
int ordine_data(DATA data1, DATA data2)
{
 if (data1.anno<data2.anno)
    return 0; //data1 è più vecchia
 if (data1.anno==data2.anno) {
    if (data1.mese<data2.mese)
       return 0; //data 1 è più vecchia
    if (data1.mese==data2.mese) {
       if (data1.giorno<data2.giorno)
          return 0;
       if (data1.giorno==data2.giorno)
          return -1; //le due date sono uguali
    }
 }
 return 1; //data2 è più vecchia (non sono neccessari if perchè questa strada è seguita solo se vengono scarate le altre condizioni)
}



//Funzione ins_cf: chiede una stringa e controlla che sia corretta la sintassi da codice fiscale
int ins_cf(char* cf)
{
      int i,k;
      bool flag=false;
      do {
         if (flag)
            cout<<"Il formato del codice fiscale non e' valido, prego riprovare"<<endl;
         ins_str(cf,16);
         flag=false;
         for (i=0;i<16;i++)
             if (i<6||i==8||i==11||i==15) {
                if (cf[i]<'A'||cf[i]>'Z'&&cf[i]<'a'||cf[i]>'z')
                   flag=true;//controllo lettere
                }  
             else if (cf[i]<'0'||cf[i]>'9') 
                  flag=true; //controllo numeri
         }while(flag);
      return 0; //restituisce 0 se va a buon fine
}


//Funzione ins_pat: chiede e controlla il numero patente
int ins_pat(char *pat)
{
      int i,k;
      bool flag=false;
      do {
         if (flag)
            cout<<"Il formato del numero della patente non e' valido, prego riprovare"<<endl;
         ins_str(pat,10);
         flag=false;
         for (i=0;i<10;i++)
             if (i<2||i==9) {
                if (pat[i]<'A'||pat[i]>'Z'&&pat[i]<'a'||pat[i]>'z')
                   flag=true;//controllo lettere
                }  
             else if (pat[i]<'0'||pat[i]>'9') 
                  flag=true; //controllo numeri
         }while(flag);
      return 0;
}


//Funzione trnk_str: tronca una stringa se incontra due spazi consecutivi; utilizzata per la formattazione delle variabili lette nel caricamento
int trnk_str(char* str,int n_car)//n_car è un carattere in meno della dim della stringa
{
    int i;
    for(i=0;i<n_car;i++)
    if (str[i]==' ')
       if (str[i+1]==' ') {
           str[i]='\0';    
           return 0;
       }
    str[n_car]='\0';
    return 1;
}




//Funzioni per la gestione delle liste

//Funzione ins_anagraf: inserimento da tastiera dei dati anagrafici che vengono messi in fondo alla lista_a, e collegati tramite il puntatore punta alla corrispondente contravvenzione
NODO_ANAGRAF *ins_anagraf(NODO_ANAGRAF *lista_a)
{
 NODO_ANAGRAF *cursore,*punta,*punta_finale;
 int indice;
 punta=new NODO_ANAGRAF;
 if (punta==NULL) {
          cout<<"\n\n ! ATTENZIONE: Memoria esaurita.\n\nImpossibile allocare ulteriore memoria\n\n";
          system("PAUSE");
          return NULL; //errore nell'allocazione di nuova memoria
          }
 if (lista_a==NULL) {//controlla se la lista è vuota 
    lista_a=punta;
    indice=0;
 }
 else {
  cursore=lista_a;
  while (cursore->next_anagraf!=NULL) { //cursore scorre la lista fino all'ultimo nodo
        cursore=cursore->next_anagraf;     
        }
  cursore->next_anagraf=punta;
  indice=cursore->dati_anagraf.cod_anagraf;
 }
 //assegnamento
 punta->dati_anagraf.cod_anagraf=++indice;
 cout<<"\n\nInserire i dati anagrafici del proprietario del veicolo";
 cout<<"\nCognome: ";
 ins_txt(punta->dati_anagraf.cognome,31);
 maiusc(punta->dati_anagraf.cognome);
 cout<<"Nome   : ";
 ins_txt(punta->dati_anagraf.nome,31);
 maiusc(punta->dati_anagraf.nome);
 cout<<"Data di nascita: ";
 ins_data(&punta->dati_anagraf.data_di_nascita);
 cout<<"\nInserire i dati relativi alla residenza del proprietario del veicolo\n";
 cout<<"Indirizzo:  ";
 ins_str(punta->dati_anagraf.indirizzo,31);
 cout<<"Citta'   :  ";
 ins_txt(punta->dati_anagraf.citta,31);
 cout<<"CAP      :  ";
 ins_num(punta->dati_anagraf.cap,5);
 cout<<"Provincia:  ";
 ins_txt(punta->dati_anagraf.provincia,2);
 maiusc(punta->dati_anagraf.provincia);
 cout<<"\nInserire il codice fiscale del proprietario:\n> ";
 ins_cf(punta->dati_anagraf.codice_fiscale);
 maiusc(punta->dati_anagraf.codice_fiscale);
 cout<<"\nInserire il numero della patente del guidatore:\n> ";
 ins_pat(punta->dati_anagraf.num_patente);
 maiusc(punta->dati_anagraf.num_patente);

 punta->next_anagraf=NULL;   //coda della lista
 
 //controllo nel caso ci siano dati identici già inseriti nella lista
 punta_finale=anagraf_doppia(punta);
 if (punta_finale!=punta)
    canc_anagraf(punta->dati_anagraf.cod_anagraf);                //elimina i dati appena inseriti, dato che sono già presenti in lista
 return punta_finale; //se andato a buon fine ritorna il valore del puntatore (se i dati non sono doppi punta_finale==punta, altrimenti punta_finale si riferisce a dati già esistenti)
}


//Funzione vis_anagraf: visualizza il nodo della lista_a puntato dalla variabile cursore
int vis_anagraf(NODO_ANAGRAF *lista_a, NODO_ANAGRAF *cursore)
{
 if (lista_a!=NULL) {
    if (cursore!=NULL) { 
           cout<<"-----------------------------------------------\n";
           cout<<"\n DATI ANAGRAFICI COD."<<cursore->dati_anagraf.cod_anagraf<<endl;
           cout<<"\nProprietario:             "<<cursore->dati_anagraf.cognome<<" "<<cursore->dati_anagraf.nome<<endl;
           cout<<"Data di nascita:          "; vis_data(cursore->dati_anagraf.data_di_nascita);
           cout<<"Indirizzo:                "<<cursore->dati_anagraf.indirizzo<<endl;
           cout<<"Citta', CAP e provincia:  "<<cursore->dati_anagraf.citta<<" "<<cursore->dati_anagraf.cap<<" "<<cursore->dati_anagraf.provincia<<endl; 
           cout<<"Codice fiscale:           "<<cursore->dati_anagraf.codice_fiscale<<endl;
           cout<<"Numero patente guidatore: "<<cursore->dati_anagraf.num_patente;
           cout<<"\n-----------------------------------------------\n";               
          return 0;   //nodo trovato
          }
    cout<<"Dati anagrafici inesistenti./n"; //non è necessario else perchè nell'if è presente l'istruzione return
    system("PAUSE"); 
    return 1; //caso di nodo inesistente
 }
 else cout<<"Non sono presenti dati anagrafici./n";
 system("PAUSE");
 return -1;//caso di lista vuota     
}



//Funzione ins_contravv: funzione inserimento da tastiera dati contravvenzione (inserisce nodo in fondo alla lista); restituisce -1 se memoria esaurita
int ins_contravv(NODO_CONTRAVV *lista_c)
{
 NODO_CONTRAVV *puntc,*cursore;
 NODO_ANAGRAF *lnk;

 puntc=new NODO_CONTRAVV;
 if (puntc==NULL) {
          cout<<"\n\nATTENZIONE: Memoria esaurita.\n\nImpossibile allocare nuova memoria\n\n";
          system("PAUSE");
          return -1;
          }
 int indice;
 char choose;
 
 if (lista_c==NULL) //controlla se la lista è vuota
 { 
    lista_c=puntc;
    indice=0;
 }
 else 
 {
      cursore=lista_c;
      while (cursore->next_contravv!=NULL) { //cursore scorre la lista fino all'ultimo nodo
       cursore=cursore->next_contravv;     
      }
      cursore->next_contravv=puntc;
      indice=cursore->dati_contravv.num_contravv;
 }      
 //assegnamento
 puntc->dati_contravv.num_contravv=++indice;
 cout<<"\n\nInserire la data del verbale della contravvenzione (gg/mm/aaaa):\n> ";
 ins_data(&puntc->dati_contravv.data_contravv); 
 cout<<"\nInserire il luogo in cui e' stata commessa l'infrazione (citta', via):\n> ";
 ins_str(puntc->dati_contravv.luogo,63);
 cout<<"\nInserire la targa del veicolo multato:\n> ";
 ins_str(puntc->dati_contravv.targa,7);
 maiusc(puntc->dati_contravv.targa);
 cout<<"\nInserire il tipo di infrazione:\n> ";
 ins_str(puntc->dati_contravv.tipo,127);
 cout<<"\nInserire l'importo della multa in euro:\n> ";
 ins_double(&puntc->dati_contravv.importo);
 do {
    cout<<"\n\nInserire subito i dati del proprietario? (s/n) ";
    cin>>choose; 
    cin.ignore();
    if (choose=='s' || choose=='S') {
       cout<<"\n\n----------------------------------------------------------";
      if ((puntc->dati_contravv.proprietario=ins_anagraf(lista_anagraf))!=NULL)         
         puntc->dati_contravv.flag_anagraf_ins=true;         
    }
 } while (choose!='n' && choose!='N' && choose!='s' && choose!='S');
 if ((choose=='n' || choose=='N'))
 puntc->dati_contravv.flag_anagraf_ins=false;
 if (choose=='s' || choose=='S') {                  //è chiesto l'inserimento del pagamento solo se sono stati appena inseriti i dati anagrafici
    do {
       cout<<"\nInserire subito i dati dell'avvenuto pagamento? (s/n) ";
       cin>>choose;
       cin.ignore();
       if (choose=='s' || choose=='S') {
          cout<<"\nInserire la data del pagamento:  ";
          while ((ins_data(&puntc->dati_contravv.data_pagam)!=0) || ordine_data(puntc->dati_contravv.data_contravv,puntc->dati_contravv.data_pagam)==1) {  
                                                                         //nota: importante l'ordine della proposizione (se l'inserimento è avvenuto correttamente 
                                                                         //E se la data di pagamento segue quella della contravvenzione
                 cout<<"\nData non valida \nLa data di pagamento deve essere successiva a quella della contravvenzione.\nPrego reinserire la data del pagamento: ";                       
          }
          puntc->dati_contravv.flag_pagam_eff=true;
       }
    } while (choose!='n' && choose!='N' && choose!='s' && choose!='S');
 }
 if ((choose=='n' || choose=='N'))
 puntc->dati_contravv.flag_pagam_eff=false;
 puntc->next_contravv=NULL; 
 cout<<"\nContravvenzione n."<< puntc->dati_contravv.num_contravv<<" inserita correttamente. \n";
 return 0; //restituisce 0 se va a buon fine  
}


//Funzione vis_contravv: visualizza contravv dopo ricerca in base al numero contravv (restituisce 0 se trovata, 1 se non è stata trovata, -1 in caso di lista vuota)
int vis_contravv(NODO_CONTRAVV *lista_c, unsigned long int index)
{
 NODO_CONTRAVV *cursore;
 
 if (lista_c!=NULL) {
    cursore=lista_c;
    while (cursore!=NULL) {
          if (cursore->dati_contravv.num_contravv==index) { 
           cout<<"\n\n==============================================\n";
           cout<<" CONTRAVVENZIONE N."<<index<<endl<<endl;
           cout<<"Data del verbale     : "; vis_data(cursore->dati_contravv.data_contravv);  
           cout<<"Luogo dell'infrazione: "<<cursore->dati_contravv.luogo<<endl;  
           cout<<"Targa del veicolo    : "<<cursore->dati_contravv.targa<<endl;  
           cout<<"Tipo di infrazione   : "<<cursore->dati_contravv.tipo<<endl;  
           cout<<"Importo della multa  : "<<setprecision(2)<<fixed<<cursore->dati_contravv.importo<<" euro"<<endl;
           if (cursore->dati_contravv.flag_anagraf_ins)
              vis_anagraf(lista_anagraf,cursore->dati_contravv.proprietario);
           else cout<<"\nDati anagrafici non ancora inseriti\n";
           if (cursore->dati_contravv.flag_pagam_eff) {
              cout<<"\nLa contravvenzione e' stata pagata in data ";
              vis_data(cursore->dati_contravv.data_pagam);
           }
           else cout<<"\nMulta non ancora pagata";
           cout<<"\n==============================================\n\n";               
          return 0;   //nodo trovato
          }
          cursore=cursore->next_contravv;
    }
    cout<<"\nLa contravvenzione cercata non e' stata trovata.\n"; 
    return 1; //caso di nodo inesistente
 }
 else cout<<"\nNon e' presente alcuna contravvenzione./n";
 return -1;//caso di lista vuota     
}



//Funzione ins_pagam: ritorna 0 se ok, 1 se già registrato o se mancano dati anagrafici, -1 lista vuota o elemento inesistente
int ins_pagam(unsigned long int indice)
{                 
 if (lista_contravv!=NULL) {
    NODO_CONTRAVV *cursore=lista_contravv;
    while (cursore!=NULL) {
          if (cursore->dati_contravv.num_contravv==indice) { 
             if (cursore->dati_contravv.flag_pagam_eff) {  
                cout<<"\nLa contravvenzione e' gia' stata pagata dal Sig./dalla Sig.ra.\n";
                vis_anagraf(lista_anagraf,cursore->dati_contravv.proprietario);
                return 1; //caso di contravv già pagata (nota: non è necessario l'else)
             }
             if (cursore->dati_contravv.flag_anagraf_ins)  {  //se esiste un proprietario
                cout<<"\nLa contravvenzione deve essere pagata da \n";
                vis_anagraf(lista_anagraf,cursore->dati_contravv.proprietario);                                          
                cout<<"\nInserire la data del pagamento:  ";
                while ((ins_data(&cursore->dati_contravv.data_pagam)!=0) || ordine_data(cursore->dati_contravv.data_contravv,cursore->dati_contravv.data_pagam)==1) {  
                                                                         //nota: importante l'ordine della proposizione (se l'inserimento è avvenuto correttamente 
                                                                         //E se la data di pagamento segue quella della contravvenzione
                 cout<<"\nData non valida: \nLa data di pagamento deve essere successiva a quella della contravvenzione.\nPrego reinserire la data del pagamento: ";                       
                }
                cursore->dati_contravv.flag_pagam_eff=true;
                cout<<"\n\nPagamento aggiunto.\n";
                system("PAUSE");
                return 0; //dati aggiunti
             }
             else
                 cout<<"\nNon e' possibile registrare il pagamento in quanto non e' stato ancora inserito un proprietario\n";
             system("PAUSE");
             return 1 ;   //dati aggiunti                                 
             }
          cursore=cursore->next_contravv;
    }
    cout<<"\nLa contravvenzione cercata non esiste.\n"; //sarà necessariamente cursore==NULL
    system("PAUSE"); 
    return -1; 
 }
 else
     cout<<"\nErrore: non e' presente alcuna contravvenzione.\n";
 system("PAUSE");
 return -1;//caso di lista vuota
}


//Funzione vis_pagam: visualizza le contravvenzioni senza pagamento: ritorna 0 se è stata trovata la contravvenzione, 1 se non è stata pagata, -1 non presente
int vis_pagam(NODO_CONTRAVV *lista_c, unsigned long int indice)
{
 NODO_CONTRAVV *cursore; 
 if (lista_c!=NULL) {
    cursore=lista_c;
    while (cursore!=NULL) {
          if (cursore->dati_contravv.num_contravv==indice) { 
            if (cursore->dati_contravv.flag_pagam_eff) {
              cout<<"\nLa contravvenzione e' stata pagata in data ";
              vis_data(cursore->dati_contravv.data_pagam);                                           
              cout<<"dal Sig./dalla Sig.ra\n";
              vis_anagraf(lista_anagraf,cursore->dati_contravv.proprietario);   //si intende che la multa sia sata pagata conoscendo i dati anagrafici
              return 0;
            }
            else {
                cout<<"\nMulta non ancora pagata";
                if (cursore->dati_contravv.flag_anagraf_ins) 
                   cout<<", ma sono gia' stati inseriti i dati anagrafici.";
                cout<<endl;
                return 1;    
            }
          }
          cursore=cursore->next_contravv;
    }
    cout<<"\nLa contravvenzione cercata non esiste.\n"; 
    return -1; //caso di nodo inesistente
 }
 else cout<<"\nNon e' presente alcuna contravvenzione./n";
 return -1;//caso di lista vuota  
}




//Funzioni di modifica/cancellazione delle liste
//Funzione mod_pagamento: restituisce 1 se non modificato, -1 se non viene trovata la contravvenzione, 0 se modificato
int mod_pagam(NODO_CONTRAVV *lista_c, unsigned long int indice)
{
 NODO_CONTRAVV *cursore;
 char mdf[3]; 
 if (lista_c!=NULL) {
    cursore=lista_c;
    while (cursore!=NULL) {
          if (cursore->dati_contravv.num_contravv==indice) { 
            if (cursore->dati_contravv.flag_pagam_eff) {
              cout<<"\nLa contravvenzione e' stata pagata in data ";
              vis_data(cursore->dati_contravv.data_pagam);                                           
              cout<<"dal Sig./dalla Sig.ra\n";
              vis_anagraf(lista_anagraf,cursore->dati_contravv.proprietario); //si intende che una multa sia sata pagata solo dopo aver inserito i dati anagrafici
              cout<<"\nPremere INVIO per modificare la data di pagamento, X per uscire... ";
              ins_str(mdf,2);
              if (strcmp(mdf,"X") && strcmp(mdf,"x")) { 
                 cout<<"\nInserire la nuova data di pagamento:  ";
                 while ((ins_data(&cursore->dati_contravv.data_pagam)!=0) || ordine_data(cursore->dati_contravv.data_contravv,cursore->dati_contravv.data_pagam)==1) {  
                                                                         //nota: importante l'ordine della proposizione (se l'inserimento è avvenuto correttamente 
                                                                         //E se la data di pagamento segue quella della contravvenzione
                 cout<<"\nData non valida: \nLa data di pagamento deve essere successiva a quella della contravvenzione.\nPrego reinserire la data del pagamento: ";                       
                 }
                 cursore->dati_contravv.flag_pagam_eff=true;
                 cout<<"\n --- Data del pagamento modificata ---\n\n";
                 system("PAUSE");
                 return 0;  
              }    
            }
            else {
                cout<<"\nImpossibile modificare: multa non ancora pagata\n";
                cout<<endl;
                system("PAUSE");
            }
            return 1;
          }
          cursore=cursore->next_contravv;
    }
    cout<<"\nLa contravvenzione cercata non esiste.\n"; 
    system("PAUSE");
    return -1; //caso di nodo inesistente
 }
 else cout<<"\nNon e' presente alcuna contravvenzione./n";
 system("PAUSE");
 return -1;//caso di lista vuota  
}


//Funzione mod_anagraf modifica dati anagrafici: ritorna 0 se nodo modificato
int mod_anagraf(NODO_ANAGRAF *lista_a, unsigned long int codice)
{
 char cha;
 NODO_ANAGRAF *cursore=lista_a; //lista_a non può essere NULL 
                                //e deve necessariamente contenere il nodo cercato perchè è già stata controllata da vis_contravv nella funzione chiamante
       while (cursore!=NULL) {
             if (cursore->dati_anagraf.cod_anagraf==codice) {            
                do{
                   //visualizzazione dei campi con numero di modifica
                   system("CLS");
                   cout<<"\n DATI ANAGRAFICI COD."<<cursore->dati_anagraf.cod_anagraf<<endl;
                   cout<<"\n[1] Proprietario:             "<<cursore->dati_anagraf.cognome<<" "<<cursore->dati_anagraf.nome<<endl;
                   cout<<"[2] Data di nascita:          "; vis_data(cursore->dati_anagraf.data_di_nascita);
                   cout<<"[3] Indirizzo:                "<<cursore->dati_anagraf.indirizzo<<endl;
                   cout<<"[4] Citta', CAP e provincia:  "<<cursore->dati_anagraf.citta<<" "<<cursore->dati_anagraf.cap<<" "<<cursore->dati_anagraf.provincia<<endl; 
                   cout<<"[5] Codice fiscale:           "<<cursore->dati_anagraf.codice_fiscale<<endl;
                   cout<<"[6] Numero patente guidatore: "<<cursore->dati_anagraf.num_patente;    
                   cout<<"\n\n[7] Fine modifiche\n";  
                   //riassegnamento dei campi  //NOTA: SEBBENE I CAMPI VENGANO SOVRASCRITTI LE VARIABILI (SPECIALMENTE QUELLE DI TIPO STRINGA) 
                                               //VENGONO "PULITE" NELL'ATTO DELL'INSERIMENTO (vd funzioni di inserimento dati)
                   cout<<"\n\nSeleziona il campo da modificare [1-6, 7 fine]\n";
                   do {
                      cout<<">"; cin>>cha;
                      cin.ignore();
                   } while(cha<'1'||cha>'8');
                   cout<<endl<<endl;
                   switch (cha) {   
                          case '1': cout<<"\nCognome: ";
                                    ins_txt(cursore->dati_anagraf.cognome,31);
                                    maiusc(cursore->dati_anagraf.cognome);
                                    cout<<"Nome   : ";
                                    ins_txt(cursore->dati_anagraf.nome,31);
                                    maiusc(cursore->dati_anagraf.nome); 
                                    break;
                          case '2': cout<<"Data di nascita: ";
                                    ins_data(&cursore->dati_anagraf.data_di_nascita);
                                    break;
                          case '3': cout<<"Indirizzo:  ";
                                    ins_str(cursore->dati_anagraf.indirizzo,31);
                                    break;
                          case '4': cout<<"Citta'   :  ";
                                    ins_txt(cursore->dati_anagraf.citta,31);
                                    cout<<"CAP      :  ";
                                    ins_num(cursore->dati_anagraf.cap,5);
                                    cout<<"Provincia:  ";
                                    ins_txt(cursore->dati_anagraf.provincia,2);
                                    maiusc(cursore->dati_anagraf.provincia);
                                    break;
                          case '5': cout<<"\nInserire il codice fiscale del proprietario:\n> ";
                                    ins_cf(cursore->dati_anagraf.codice_fiscale);
                                    maiusc(cursore->dati_anagraf.codice_fiscale);
                                    break;
                          case '6': cout<<"\nInserire il numero della patente del guidatore:\n> ";
                                    ins_pat(cursore->dati_anagraf.num_patente);
                                    maiusc(cursore->dati_anagraf.num_patente);
                                    break;          
                   } 
                                 
                } while(cha!='7');  //ripete fino a fine modifiche
                
                //controllo nel caso di modifica verso dati gia' esistenti
                NODO_ANAGRAF *punt_finale=anagraf_doppia(cursore);
                if (punt_finale!=cursore) {
                   NODO_CONTRAVV *contravv=lista_contravv;
                   while (contravv!=NULL) { //aggiorna tutte le contravvenzioni che si riferiscono ai dati doppi
                         if (contravv->dati_contravv.proprietario==cursore)
                            contravv->dati_contravv.proprietario=punt_finale; 
                         contravv=contravv->next_contravv;
                   }
                   canc_anagraf(codice);    //elimina i dati appena modificati, dato che sono già presenti in lista
                }           
                cout<<"\n\n ---- Dati aggiornati. ----\n\n";                
                system("PAUSE");
                return 0;   //dati modificati                                 
             }
       cursore=cursore->next_anagraf;
       }
}


//Funzioni mod_contravv che modifica dati di una contravvenzione: ritorna 0 se nodo modificato, 1 nodo non modificato, -1 contravvenzione non trovata
int mod_contravv(NODO_CONTRAVV *lista_c)
{
 int index;
 char mdf[3];
 char cha;
 cout<<"\nInserire il numero della contravvenzione per visualizzarla ed\neventualmente modificarla\n>";
 ins_int(&index);   
 if (vis_contravv(lista_c,index)==0)  {        //è un caso che si chiamino come le variabili formali
    cout<<"\nPremere INVIO per modificare i dati della contravvenzione, X per uscire... ";
    ins_str(mdf,2);
    if (strcmp(mdf,"X") && strcmp(mdf,"x")) {
       NODO_CONTRAVV *cursore=lista_c; //lista_c non può essere NULL 
                                       //e deve necessariamente contenere il nodo cercato perchè è già stata controllata da vis_contravv
       while (cursore!=NULL) {
             if (cursore->dati_contravv.num_contravv==index) {            
 
                do{
                   //visualizzazione dei campi
                   system("CLS");
                   cout<<"\n CONTRAVVENZIONE N."<<index<<endl<<endl;
                   cout<<"[1] Data del verbale     : "; vis_data(cursore->dati_contravv.data_contravv);  
                   cout<<"[2] Luogo dell'infrazione: "<<cursore->dati_contravv.luogo<<endl;  
                   cout<<"[3] Targa del veicolo    : "<<cursore->dati_contravv.targa<<endl;  
                   cout<<"[4] Tipo di infrazione   : "<<cursore->dati_contravv.tipo<<endl;  
                   cout<<"[5] Importo della multa  : "<<setprecision(2)<<fixed<<cursore->dati_contravv.importo<<" euro"<<endl;         
                   if (cursore->dati_contravv.flag_anagraf_ins)
                      cout<<"\n[6] Modifica Dati anagrafici\n";
                   if (cursore->dati_contravv.flag_pagam_eff)
                      cout<<"\n[7] Modifica la data di pagamento\n";
                    cout<<"\n\n[8] Fine modifiche\n";  
                   //riassegnamento dei campi  //NOTA: SEBBENE I CAMPI VENGANO SOVRASCRITTI LE VARIABILI (SPECIALMENTE QUELLE DI TIPO STRINGA) 
                                               //VENGONO "PULITE" NELL'ATTO DELL'INSERIMENTO (vd funzioni di inserimento dati)
                   cout<<"\n\nSeleziona il campo da modificare [1-7, 8 fine]\n";
                   do {
                      cout<<">"; cin>>cha;
                      cin.ignore();
                   } while(cha<'1'||cha>'8');
                   cout<<endl<<endl;
                   switch (cha) {   
                          case '1': cout<<"\nInserire la data del verbale della contravvenzione (gg/mm/aaaa):\n> ";
                                    if (cursore->dati_contravv.flag_pagam_eff)
                                       while ((ins_data(&cursore->dati_contravv.data_contravv)!=0) || ordine_data(cursore->dati_contravv.data_contravv,cursore->dati_contravv.data_pagam)==1) {  
                                          cout<<"\nImpossibile modificare: data non valida\nLa data di contravvenzione deve essere precedente a quella del pagamento.\nPrego reinserire la data della contravvenzione: ";                       
                                       }
                                    else
                                        ins_data(&cursore->dati_contravv.data_contravv); 
                                    break;
                          case '2': cout<<"\nInserire il luogo in cui e' stata commessa l'infrazione (citta', via):\n> ";
                                    ins_str(cursore->dati_contravv.luogo,63);
                                    break;
                          case '3': cout<<"\nInserire la targa del veicolo multato:\n> ";
                                    ins_str(cursore->dati_contravv.targa,7);
                                    maiusc(cursore->dati_contravv.targa);
                                    break;
                          case '4': cout<<"\nInserire il tipo di infrazione:\n> ";
                                    ins_str(cursore->dati_contravv.tipo,127);
                                    break;
                          case '5': cout<<"\nInserire l'importo della multa in euro:\n> ";
                                    ins_double(&cursore->dati_contravv.importo);
                                    break;
                          case '6': if (cursore->dati_contravv.flag_anagraf_ins)
                                       mod_anagraf(lista_anagraf,cursore->dati_contravv.proprietario->dati_anagraf.cod_anagraf);
                                    break;
                          case '7': system("CLS");
                                    if (cursore->dati_contravv.flag_pagam_eff)
                                       mod_pagam(lista_contravv,cursore->dati_contravv.num_contravv);
                                    break;            
                   } 
                                 
                } while(cha!='8');  //ripete fino a fine moodifiche
                cout<<"\n\n ---- Dati aggiornati. ----\n\n";                
                system("PAUSE");
                return 0;   //dati modificati                                 
             }
             cursore=cursore->next_contravv;
       }    
    }
    return 1; //caso in cui venga digitato X e quindi dati non modificati
 }
 system("PAUSE");   
 return -1;   //nel caso si siano riscontrati errori nella individuazione(visualizzazione) del nodo (vd condizione dell'if)
}



//Funzione canc_pagam: cancella la data di un pagamento e cambia valore al flag; restituisce 0 se data eliminata, 1 se interrotto da utente, -1 se errore
int canc_pagam(NODO_CONTRAVV *listaC, unsigned long int index) 
{
  char del[3];  
  if (vis_pagam(listaC,index)==0) {   //punt viene modificato e alla fine punta all'elemento di posto index, quello ricercato
     cout<<"\nPremere INVIO per eliminare la data del pagamento, X per uscire... ";     
     ins_str(del,2);
     if (strcmp(del,"X") && strcmp(del,"x")) {
        NODO_CONTRAVV *punt=listaC;       
        while (punt!=NULL) {
              if (punt->dati_contravv.num_contravv==index) { //la contravvenzione esiste perchè l'ha già controllata vis_pagam
                 punt->dati_contravv.flag_pagam_eff=false; 
                 punt->dati_contravv.data_pagam.giorno=0;
                 punt->dati_contravv.data_pagam.mese=0;
                 punt->dati_contravv.data_pagam.anno=0;          //inizializzazione a valore nullo (il valore è comunque inaccessibile finchè flag_pagam_eff rimane false)
                 cout<<"\n --- Pagamento eliminato ---\n";
                 system("PAUSE");
                 return 0;
              } 
              punt=punt->next_contravv;
        }
     }
     return 1; //interruzione da parte dell'utente che digita X  
  }
  system("PAUSE");
  return -1; //nel caso in cui durante vis_pagam non venga trovata la contravvenzione o non esista il pagamento
}


//Funzione canc_anagraf: elimina i dati anagrafici controllando le contravvenzioni collegate
int canc_anagraf(unsigned long int index) //modificate direttamente le variabili globali
{
 NODO_ANAGRAF *prev_ana=NULL;
 NODO_ANAGRAF *cursore=lista_anagraf;
 while (cursore!=NULL) {
       if (cursore->dati_anagraf.cod_anagraf==index) {    
          
          //controllo se esistono delle contravvenzioni che fanno riferimento a questi dati
          NODO_CONTRAVV *cur2=lista_contravv;
          while (cur2!=NULL) { //se la lista_contravv è vuota o si è giunti alla fine esce dal ciclo
                if (cur2->dati_contravv.proprietario==cursore) { //scorre TUTTA la lista di contravvenzioni per cercare nodi collegati e resettare i puntatori
                   cur2->dati_contravv.flag_anagraf_ins=false;
                   cur2->dati_contravv.proprietario=NULL;
                   cur2->dati_contravv.flag_pagam_eff=false;
                   cur2->dati_contravv.data_pagam.giorno=0;
                   cur2->dati_contravv.data_pagam.mese=0;
                   cur2->dati_contravv.data_pagam.anno=0;
                }
                cur2=cur2->next_contravv;
          }                                        
            
          //cancellazione elemento            
          if (prev_ana==NULL)                           //se l'elemento cercato è il primo della lista
             lista_anagraf=lista_anagraf->next_anagraf; //modifica diretta della var globale 
          else
              prev_ana->next_anagraf=cursore->next_anagraf;  
          delete(cursore);     //DEALLOCAZIONE DELLA MEMORIA
          return 0; //dati cancellati
       }
       if (prev_ana==NULL)
          prev_ana=lista_anagraf;
       else
           prev_ana=prev_ana->next_anagraf;
       cursore=cursore->next_anagraf;  //cursore è sempre un elemento più avanti di prev_ana
       }
 }


//Funzione canc_contravv: elimina la contravvenzione e risistema la lista
int canc_contravv()  //non vengono passate variabili, è necessario utilizzare la variabile globale per eventuali modifiche alla testa della lista
{
 int index;
 char del[3];
 char chs;
 cout<<"\nInserire il numero della contravvenzione per visualizzarla ed\neventualmente eliminarla\n>";
 ins_int(&index);   
 if (vis_contravv(lista_contravv,index)==0)  {        
    cout<<"\nPremere INVIO per eliminare i dati della contravvenzione, X per uscire... ";
    ins_str(del,2);
    if (strcmp(del,"X") && strcmp(del,"x")) {
       NODO_CONTRAVV *prev_contravv=NULL;
       NODO_CONTRAVV *cursore=lista_contravv; //lista_c non può essere NULL 
                                       //e deve necessariamente contenere il nodo cercato perchè è già stata controllata da vis_contravv
       while (cursore!=NULL) {
             if (cursore->dati_contravv.num_contravv==index) {    
                if (prev_contravv==NULL)    //se l'elemento cercato è il primo della lista
                   lista_contravv=lista_contravv->next_contravv; //modifica diretta della var globale 
                else
                    prev_contravv->next_contravv=cursore->next_contravv;  

             do {
                cout<<"\nEliminare anche i dati anagrafici connessi a questa contravvenzione? (s/n)\n";
                cin>>chs; 
                cin.ignore();
                if (chs=='s' || chs=='S') 
                   canc_anagraf(cursore->dati_contravv.proprietario->dati_anagraf.cod_anagraf); 
             } while (chs!='n' && chs!='N' && chs!='s' && chs!='S');
             delete(cursore);     //RILASCIO DINAMICO DELLA MEMORIA per evitare garbage nell'heap
             cout<<"\n --- Contravvenzione eliminata ---\n";
             system("PAUSE");
             return 0; //contravvenzione cancellata
             }
             if (prev_contravv==NULL)
                prev_contravv=lista_contravv;
             else
                 prev_contravv=prev_contravv->next_contravv;
             cursore=cursore->next_contravv;  //cursore è 1sempre un elemento più avanti di prev_contravv
       }
    }
    return 1; //caso in cui venga digitato X e quindi dati non eliminati
    }
 system("PAUSE");  
 return -1;   //nel caso si siano riscontrati errori nella individuazione(visualizzazione) del nodo
}



//Funzione anagraf_doppia che controlla che non ci sia un doppione nella lista anagrafica e passa l'indirizzo di quei dati, altrimenti ritorna l'indirizzo dei dati in esame
NODO_ANAGRAF *anagraf_doppia(NODO_ANAGRAF *punt)
{
 NODO_ANAGRAF *cursore=lista_anagraf;
 while (cursore!=NULL) {
      if (cursore!=punt) 
       if (
          strcmp(cursore->dati_anagraf.cognome,punt->dati_anagraf.cognome) == 0 &&
          strcmp(cursore->dati_anagraf.nome,punt->dati_anagraf.nome) == 0 &&
          ordine_data(cursore->dati_anagraf.data_di_nascita,punt->dati_anagraf.data_di_nascita) == -1 &&
          strcmp(cursore->dati_anagraf.indirizzo,punt->dati_anagraf.indirizzo) == 0 &&
          strcmp(cursore->dati_anagraf.citta,punt->dati_anagraf.citta) == 0 &&
          strcmp(cursore->dati_anagraf.cap,punt->dati_anagraf.cap) == 0 &&
          strcmp(cursore->dati_anagraf.provincia,punt->dati_anagraf.provincia) == 0 &&
          strcmp(cursore->dati_anagraf.codice_fiscale,punt->dati_anagraf.codice_fiscale) == 0 &&
          strcmp(cursore->dati_anagraf.num_patente,punt->dati_anagraf.num_patente) == 0
          )
        return cursore;
      cursore=cursore->next_anagraf;
 }
 return punt; //tutta la lista è stata percorsa senza successo e viene restituito l'indirizzo dell'elemento sotto esame            
}






//Funzioni di ricerca e statistica

//Funzione bilancio: calcola l'importo totale delle multe pagate e delle multe ancora da pagare; dà una rappresentazione statistica di questi dati; restituisce 0 se il calcolo avviene
int bilancio(NODO_CONTRAVV *lista)
{
 int p=0,np=0;                         //numero multe pagate e non pagate
 double ip=0.00,inp=0.00;              //importo totale delle multe pagate e non pagate
 double percp, percnp;                 //percentuale delle multe pagate e non pagate sulle multe totali
 int percp_scalata, percnp_scalata;    //le due percentuali scalate e approssimate a intero necessarie per la rappresentazione
 const double scala=0.6;               //fattore scala della percentuale per la rappresentazione
 char barra=219;                       //carattere per disegnare la barra (ASCII 219)
 int k;       //contatore
 if (lista!=NULL) {
    while (lista!=NULL) {             //tutta la lista di contravvenzioni viene esaminata
          if (lista->dati_contravv.flag_pagam_eff) { //se viene trovata una contravvenzione pagata
             p++;
             ip+=lista->dati_contravv.importo;   //equivale a ip=ip+lista->dati_contravv.importo
             }
          else { //multa non pagata
             np++;
             inp+=lista->dati_contravv.importo;
             }        
          lista=lista->next_contravv;
    }
    //rappresentazione statistica delle multe pagate tramite un grafico a barre
    cout<<"\n\t\t\t\tTotale multe: "<<p+np;
    cout<<"\n\nMulte pagate:     "<<p<<endl;
    percp=(double)p/(p+np)*100;  //uso il costrutto cast per ottenere la percentuale come double dalla divisione di due interi
    percnp=100-percp;            //la parte complementare corrisponderà alle multe non pagate
    percp_scalata=(int)round(percp*scala);    //uso l'operatore cast per forzare round a restituire un intero
    percnp_scalata=(int)round(percnp*scala);  //round è una funzione contenuta nella libreria math.h: approssima un decimale all'intero
    for (k=0;k<percp_scalata;k++) 
        cout<<barra;
    cout<<" "<<setprecision(2)<<fixed<<percp<<"%\n\n";
    for (k=0;k<percnp_scalata;k++) 
        cout<<barra;
    cout<<" "<<setprecision(2)<<fixed<<percnp<<"%\n";
    cout<<"Multe non pagate: "<<np<<endl;
    //grafico a barre per importi
    cout<<"______________________________________________________________________________";
    cout<<"\n\n\t\t\tImporto totale multe: "<<setprecision(2)<<fixed<<ip+inp<<" euro";
    cout<<"\n\nTotale pagato:    "<<setprecision(2)<<fixed<<ip<<" euro"<<endl;
    percp=(double)ip/(ip+inp)*100;  //uso le stesse variabili di prima per fare il secondo grafico, dato che ormai non sono più necessarie
    percnp=100-percp;            
    percp_scalata=(int)round(percp*scala);    
    percnp_scalata=(int)round(percnp*scala);
    for (k=0;k<percp_scalata;k++) 
        cout<<barra;
    cout<<" "<<setprecision(2)<<fixed<<percp<<"%\n\n";
    for (k=0;k<percnp_scalata;k++) 
        cout<<barra;
    cout<<" "<<setprecision(2)<<fixed<<percnp<<"%\n";
    cout<<"Totale da pagare: "<<setprecision(2)<<fixed<<inp<<" euro\n"<<endl<<endl;
    return 0;
 }
 else 
      cout<<"\nNon e' presente alcuna contravvenzione.\n";
 return 1;//caso di lista vuota  
}



//Funzione cerca_no_anagraf: cerca le contravvenzioni a cui non sono ancora stati associati dati anagrafici; ritorna 1 se si raggiunge la fine della lista
int cerca_no_anagraf(NODO_CONTRAVV *listaC)
{
 char scelta[3];
 NODO_CONTRAVV *cursore=listaC;
 do {
    if (!cursore->dati_contravv.flag_anagraf_ins) {
       vis_contravv(listaC,cursore->dati_contravv.num_contravv);
       cout<<"\nPremere INVIO per visualizzare la contravvenzione successiva,\ndigitare M per inserire i dati anagrafici, X per uscire... ";
       ins_str(scelta,2);
       if (strcmp(scelta,"m")==0 || strcmp(scelta,"M")==0) {
         cursore->dati_contravv.proprietario=ins_anagraf(lista_anagraf); 
         cursore->dati_contravv.flag_anagraf_ins=true;
         system("CLS");        
         }
       }
    cursore=cursore->next_contravv;
    } while (strcmp(scelta,"X") && strcmp(scelta,"x") && cursore!=NULL);
    if (strcmp(scelta,"X") && strcmp(scelta,"x")) //nota: comportamento di strcmp; si sono fatte scorrere tutte le contravvenzioni senza interrompere
       {
        cout<<"\nNon esistono ulteriori contravvenzioni senza dati anagrafici.\n";
        system("PAUSE");
        return 1;
       }
 return 0;
}


//Funzione cerca_no_pagam: cerca le multe non pagate; ritorna 1 se si raggiunge la fine della lista
int cerca_no_pagam(NODO_CONTRAVV *listaC)
{
 char scelta[3];
 NODO_CONTRAVV *cursore=listaC;
 do {
    if (!cursore->dati_contravv.flag_pagam_eff) {
       vis_contravv(listaC,cursore->dati_contravv.num_contravv);
       cout<<"Premere INVIO per visualizzare la contravvenzione non pagata successiva,\ndigitare M per inserire la data del pagamento, X per uscire... ";
       ins_str(scelta,2);
       if (strcmp(scelta,"m")==0 || strcmp(scelta,"M")==0) {
          system("CLS");
          ins_pagam(cursore->dati_contravv.num_contravv);
          system("CLS");
          }      
       }
    cursore=cursore->next_contravv;
    } while (strcmp(scelta,"X") && strcmp(scelta,"x") && cursore!=NULL);
    if (strcmp(scelta,"X") && strcmp(scelta,"x")) //nota: comportamento di strcmp; si sono fatte scorrere tutte le contravvenzioni senza interrompere
       {
        cout<<"\n\n\n -- Non esistono ulteriori contravvenzioni non pagate --\n";
        system("PAUSE");
        return 1;
       }
 return 0;
}





//Funzione per la gestione dei file

//Funzione carica: carica i dati (da due file a relative liste dinamiche); ritorna 0 se caricamento a buon fine, 1 se caricam fallito, -1 overflow memoria
int carica()
{
 ifstream fin_c;       //per il file contravvenzioni
 ifstream fin_a;       //per il file anagrafica  
 char buffer[128];     //variabili di appoggio
 char data_buffer[10];
 char flag_buffer[5];
 char imp_buffer[16];
 unsigned long int cod; 
 
 cout<<"\n CARICA DA FILE\n_________________\n\n"; 
 cout<<"Inserire il nome del file contenente i dati delle contravvenzioni:\n(premere INVIO per caricare il file di default)\n";
 cout<<">";
 ins_str(nome_file_c,127);
 if (strlen(nome_file_c)==0)
    strcpy(nome_file_c,pathfile_c);
 cout<<"\n\nInserisci il nome del file contenente i dati anagrafici:\n(premere INVIO per caricare il file di default)\n";
 cout<<">";
 ins_str(nome_file_a,127);
 if (strlen(nome_file_a)==0)
    strcpy(nome_file_a,pathfile_a);
 
 fin_c.open(nome_file_c);                    //apertura dei file
 fin_a.open(nome_file_a);
 if (fin_c.fail() || fin_a.fail()) {         //se l'apertura dei file fallisce (ad es file inesistente)
    cout<<"\n\n\n ! ATTENZIONE\n\nErrore nell'apertura dei file\nVerificare il percorso o il nome dei file e assicurarsi di avere i permessi per accedere ad essi\n\n";
    system("PAUSE");
    return 1;
 } 
 
 //estrazione dati
 //creazione lista anagrafica
 NODO_ANAGRAF *cur_prev=NULL;
 while (fin_a.getline(buffer,10)) {                           //la prima riga è vuota
       NODO_ANAGRAF *cur= new NODO_ANAGRAF;
       if (cur==NULL) {
          cout<<"\n\nATTENZIONE: Memoria disponibile insufficiente.\n\nI dati non sono stati caricati correttamente\n\n";
          system("PAUSE");
          return -1; //caso di memoria esaurita durante l'allocazione
          }       
       fin_a.getline(buffer,10);                              //seconda riga: COD_ANAGRAF
       cur->dati_anagraf.cod_anagraf=atol(buffer);
       fin_a.getline(buffer,70);                              //terza riga: COGNOME e NOME
       strncpy(cur->dati_anagraf.cognome,buffer,31);
       trnk_str(cur->dati_anagraf.cognome,31);                      
       strncpy(cur->dati_anagraf.nome,buffer+32,31);
       trnk_str(cur->dati_anagraf.nome,31);
       fin_a.getline(buffer,20);                              //quarta riga: DATA_DI_NASCITA                      
       strncpy(data_buffer,buffer,2);
       data_buffer[2]='\0';
       cur->dati_anagraf.data_di_nascita.giorno=atoi(data_buffer);
       strncpy(data_buffer,buffer+3,2);
       data_buffer[2]='\0';
       cur->dati_anagraf.data_di_nascita.mese=atoi(data_buffer);
       strncpy(data_buffer,buffer+6,4);
       data_buffer[4]='\0';
       cur->dati_anagraf.data_di_nascita.anno=atoi(data_buffer);
       fin_a.getline(buffer,80);                              //quinta riga: INDIRIZZO, CITTA', CAP, PROVINCIA
       strncpy(cur->dati_anagraf.indirizzo,buffer,31);
       trnk_str(cur->dati_anagraf.indirizzo,31);                       
       strncpy(cur->dati_anagraf.citta,buffer+32,31);
       trnk_str(cur->dati_anagraf.citta,31);
       strncpy(cur->dati_anagraf.cap,buffer+64,5);
       cur->dati_anagraf.cap[5]='\0';
       strncpy(cur->dati_anagraf.provincia,buffer+70,2);
       cur->dati_anagraf.provincia[2]='\0';
       fin_a.getline(buffer,20);                              //sesta riga: CODICE_FISCALE
       strncpy(cur->dati_anagraf.codice_fiscale,buffer,17);
       cur->dati_anagraf.codice_fiscale[17]='\0';
       fin_a.getline(buffer,15);                              //settima riga: NUM_PATENTE
       strncpy(cur->dati_anagraf.num_patente,buffer,10);
       cur->dati_anagraf.num_patente[10]='\0';
       fin_a.getline(buffer,90);                              //ottava riga: _____ (separatore)
       if (cur_prev==NULL)       
          lista_anagraf=cur;  //assegnamento che avviene solo al primo ciclo : TESTA DELLA LISTA (var globale)
       else   
          cur_prev->next_anagraf=cur;                   //cursori che ordinano la lista
       cur_prev=cur;
 }
 cur_prev->next_anagraf=NULL;                           //coda della lista inizializzata a NULL
 //fine caricamento lista anagrafica
 
 //caricamento per lista contravvenzioni 
 NODO_CONTRAVV *punt_prev=NULL;
 while (fin_c.getline(buffer,10)) {                    //la prima riga è vuota
       NODO_CONTRAVV *punt= new NODO_CONTRAVV;
       if (punt==NULL) {
          cout<<"\n\nATTENZIONE: Memoria disponibile insufficiente.\n\nI dati non sono stati caricati correttamente\n\n";
          system("PAUSE");
          return -1;
          }       
       fin_c.getline(buffer,10);                       //seconda riga: NUM_CONTRAVV
       punt->dati_contravv.num_contravv=atoi(buffer);
       fin_c.getline(buffer,80);                       //terza riga: DATA_CONTRAVV e LUOGO
       strncpy(data_buffer,buffer,2);
       data_buffer[2]='\0';
       punt->dati_contravv.data_contravv.giorno=atoi(data_buffer);
       strncpy(data_buffer,buffer+3,2);
       data_buffer[2]='\0';
       punt->dati_contravv.data_contravv.mese=atoi(data_buffer);
       strncpy(data_buffer,buffer+6,4);
       data_buffer[4]='\0';
       punt->dati_contravv.data_contravv.anno=atoi(data_buffer);
       strncpy(punt->dati_contravv.luogo,buffer+11,63);        
       fin_c.getline(buffer,20);                       //quarta riga: TARGA
       strncpy(punt->dati_contravv.targa,buffer,7);
       punt->dati_contravv.targa[7]='\0';
       fin_c.getline(buffer,128);                      //quinta riga: TIPO
       strncpy(punt->dati_contravv.tipo,buffer,127);
       punt->dati_contravv.tipo[127]='\0';       
       fin_c.getline(buffer,20);                       //sesta riga FLAG_ANAGRAF_INS e COD_PROPRIETARIO
       strncpy(flag_buffer,buffer,1);
       flag_buffer[1]='\0';
       if (strcmp(flag_buffer,"*")==0) {  //flag on
          strncpy(flag_buffer,buffer+2,16);
          cod=atol(flag_buffer);          
          NODO_ANAGRAF *cursore=lista_anagraf;                 //collegamento al nodo lista_anagraf corrispondente
          while (cursore!=NULL){                               // RICERCA NODO ANAGRAFICA
          if (cursore->dati_anagraf.cod_anagraf==cod)
             break;
          cursore=cursore->next_anagraf;
          }
          punt->dati_contravv.proprietario=cursore;            //se a causa di un errore non viene trovato il nodo cursore=NULL
          if (cursore!=NULL)
             punt->dati_contravv.flag_anagraf_ins=true;
          }
       else {                           //flag off
           punt->dati_contravv.flag_anagraf_ins=false;
           punt->dati_contravv.proprietario=NULL;
           }                                                               
       fin_c.getline(buffer,50);                       //settima riga: IMPORTO, FLAG_PAGAM_EFF e DATA_PAGAM
       strncpy(imp_buffer,buffer,15);
       imp_buffer[15]='\0';
       punt->dati_contravv.importo=atof(imp_buffer);
       strncpy(flag_buffer,buffer+16,1);
       flag_buffer[1]='\0';
       if (strcmp(flag_buffer,"*")==0) {  //flag on
          strncpy(data_buffer,buffer+18,2);
          data_buffer[2]='\0';
          punt->dati_contravv.data_pagam.giorno=atoi(data_buffer);
          strncpy(data_buffer,buffer+21,2);
          data_buffer[2]='\0';
          punt->dati_contravv.data_pagam.mese=atoi(data_buffer);
          strncpy(data_buffer,buffer+24,4);
          data_buffer[4]='\0';
          punt->dati_contravv.data_pagam.anno=atoi(data_buffer);
          punt->dati_contravv.flag_pagam_eff=true;
          }
       else {                           //flag off
           punt->dati_contravv.flag_pagam_eff=false; 
           punt->dati_contravv.data_pagam.giorno=0;
           punt->dati_contravv.data_pagam.mese=0;
           punt->dati_contravv.data_pagam.anno=0;          //inizializzazione a valore nullo
           } 
       fin_c.getline(buffer,90);                      //ottava riga: ____ separatore
       if (punt_prev==NULL) 
          lista_contravv=punt;                             //testa della lista (var globale)
       else
          punt_prev->next_contravv=punt;                   //cursori che popolano la lista
       punt_prev=punt;
 }
 punt_prev->next_contravv=NULL;                            //coda della lista
 //fine lista contravv
 
 fin_c.close();                   //chiusura dei due flussi
 fin_a.close();
 cout<<"\n\nCaricamento avvenuto correttamente.\n\n";
 system("PAUSE"); 
 return 0;                        //caricamento avvenuto
}


//Funzione salva(): salva i dati (scaricamento delle due liste su file); ritorna 0 se salvataggio a buon fine, 1 fallito, -1 interrotto da utente
int salva()
{
 ofstream fout_c;       //file contravvenzioni
 ofstream fout_a;       //file anagrafica        
 char chs;
 cout<<"\n SALVA\n_________\n\n";
 cout<<"[1] Salva  \n[2] Salva con nome...   \n[3] Non salvare\n\n";
 do {
    cout<<">"; cin>>chs;
    cin.ignore();
 } while(chs<'1'||chs>'3');
 switch (chs) {
        case '1': break; //i nomi dei file rimangono uguali a quelli caricati                  
        case '2': cout<<"Inserire il percorso in cui salvare i dati delle contravvenzioni:\n(premere INVIO per salvare nel file di default)\n";
                  cout<<">";
                  ins_str(nome_file_c,127);
                  if (strlen(nome_file_c)==0)
                     strcpy(nome_file_c,pathfile_c);
                  cout<<"\n\nInserisci il percorso in cui salvare i dati anagrafici:\n(premere INVIO per salvare nel file di default)\n";
                  cout<<">";
                  ins_str(nome_file_a,127);
                  if (strlen(nome_file_a)==0)
                     strcpy(nome_file_a,pathfile_a);            
                  break;
        case '3': return -1; //salvataggio interrotto da utente
        }
    
 fout_c.open(nome_file_c,ios::out);            //apertura flusso dati
 fout_a.open(nome_file_a,ios::out);
 if (fout_c.fail() || fout_a.fail()) {         //se salvataggio dei file fallisce (ad es file inesistente)
    cout<<"\n\n\n ! ATTENZIONE\n\nErrore durante il salvataggio dei file\nVerificare il percorso o il nome dei file e assicurarsi di avere i permessi per accedere ad essi\n\n";
    system("PAUSE");
    return 1;
    }
 
 //salvataggio dati 
 //lista anagrafica
 NODO_ANAGRAF *cur=lista_anagraf;                //testa della lista
 while (cur!=NULL) {                             //cur scorre nodo per nodo fino alla fine                
       fout_a<<endl;                                                                    //la prima riga è vuota
       fout_a<<cur->dati_anagraf.cod_anagraf<<endl;                                     //seconda riga: COD_ANAGRAF
       fout_a<<setw(31)<<left<<cur->dati_anagraf.cognome<<" "<<cur->dati_anagraf.nome<<endl;  //terza riga: COGNOME e NOME
       if (cur->dati_anagraf.data_di_nascita.giorno<10)
          fout_a<<"0";
       fout_a<<cur->dati_anagraf.data_di_nascita.giorno<<"/";
       if (cur->dati_anagraf.data_di_nascita.mese<10)
          fout_a<<"0";
       fout_a<<cur->dati_anagraf.data_di_nascita.mese<<"/"<<cur->dati_anagraf.data_di_nascita.anno<<endl;                     //quarta riga: DATA_DI_NASCITA
       fout_a<<setw(31)<<left<<cur->dati_anagraf.indirizzo<<" "<<setw(31)<<cur->dati_anagraf.citta<<" "<<setw(5)<<cur->dati_anagraf.cap<<" "<<cur->dati_anagraf.provincia<<endl;   //quinta riga: INDIRIZZO, CITTA', CAP, PROVINCIA        
       fout_a<<cur->dati_anagraf.codice_fiscale<<endl;                                  //sesta riga: COD_FISCALE
       fout_a<<cur->dati_anagraf.num_patente<<endl;                                     //settima riga: NUM_PATENTE
       fout_a<<"________________________________________________________________________________________"<<endl;  //ottava riga: separatore
       cur=cur->next_anagraf;                   //passaggio al nodo successivo
 }
 //fine salvataggio lista anagrafica
 
 //lista contravvenzioni  
 NODO_CONTRAVV *punt=lista_contravv;            //testa della lista
 while (punt!=NULL) {                           //punt scorre nodo per nodo la lista
       fout_c<<endl;                                           //la prima riga è vuota
       fout_c<<punt->dati_contravv.num_contravv<<endl;         //seconda riga: NUM_CONTRAVV
       if (punt->dati_contravv.data_contravv.giorno<10)
          fout_c<<"0";
       fout_c<<punt->dati_contravv.data_contravv.giorno<<"/";
       if (punt->dati_contravv.data_contravv.mese<10)
          fout_c<<"0";
       fout_c<<punt->dati_contravv.data_contravv.mese<<"/"<<punt->dati_contravv.data_contravv.anno<<" ";
       fout_c<<setw(11)<<punt->dati_contravv.luogo<<endl;      //terza riga: DATA_CONTRAVV e LUOGO                                                            
       fout_c<<punt->dati_contravv.targa<<endl;                //quarta riga: TARGA
       fout_c<<punt->dati_contravv.tipo<<endl;                 //quinta riga: TIPO
       if (punt->dati_contravv.flag_anagraf_ins)               //sesta riga FLAG_ANAGRAF_INS e COD_PROPRIETARIO
          fout_c<<"* "<<punt->dati_contravv.proprietario->dati_anagraf.cod_anagraf<<endl;
       else
           fout_c<<"- "<<endl;
       fout_c<<setw(15)<<setprecision(2)<<fixed<<punt->dati_contravv.importo; //settima riga: IMPORTO, FLAG_PAGAM_EFF e DATA_PAGAM
       if (punt->dati_contravv.flag_pagam_eff) {
          fout_c<<" * ";
           if (punt->dati_contravv.data_pagam.giorno<10)
              fout_c<<"0";
           fout_c<<punt->dati_contravv.data_pagam.giorno<<"/";
           if (punt->dati_contravv.data_pagam.mese<10)
              fout_c<<"0";
           fout_c<<punt->dati_contravv.data_pagam.mese<<"/"<<punt->dati_contravv.data_pagam.anno<<endl;
           }
       else
           fout_c<<" - "<<endl;
       fout_c<<"_______________________________________________________________________________________"<<endl; //ottava riga: separatore
       punt=punt->next_contravv;                   //passaggio a nodo successivo
 }       
 //fine salvataggio lista contravv
 
 fout_c.close();                   //chiusura dei due flussi
 fout_a.close(); 
 cout<<"\n\nSalvataggio avvenuto correttamente.\n\n";
 system("PAUSE");                  //salvataggio senza errori
 return 0;   
}





//Funzioni per l'interfaccia a menu

//Funzione menu_principale: scelta delle operazioni (chiede il caricamento dei dati nel caso l'utente non lo faccia da solo)
void menu_principale()
{   
 char ch;
 bool caricamento=false;
 do{
    cout<<"\n MENU' PRINCIPALE";
    cout<<"\n____________________\n\n";
    cout<<"[1] Gestione contravvenzioni\n";
    cout<<"[2] Gestione dati anagrafici\n";
    cout<<"[3] Gestione pagamenti\n";
    cout<<"[4] Cerca\n";
    cout<<"[5] Carica da file\n";
    cout<<"[6] Salva\n";
    cout<<"[7] Esci\n\n";
 
    do {
    cout<<">"; cin>>ch;
    cin.ignore();        
    }while(ch<'1'||ch>'7');
    if (ch!='5' && ch!='7' && caricamento==false) { //controlla che i dati siano stati caricati
       system("CLS");
       cout<<"Prima di procedere e' necessario caricare i dati\n\n";    
       if (carica()==0)       //caricamento dei dati 
          caricamento=true; //caricamento è avvenuto
    }
    if (caricamento || !caricamento && (ch=='5' || ch=='7')) {
       switch (ch) {
              case '1': menu_contravv();
                        break;
              case '2': menu_anagraf();
                        break;
              case '3': menu_pagam();
                        break;
              case '4': menu_cerca();
                        break;
              case '5': system("CLS");
                        if (carica()==0)
                           caricamento=true;
                        break;
              case '6': system("CLS");
                        salva();
                        break;
              case '7': if (caricamento)
                           esci(); 
                        break;
       }
    }
    system("CLS");
 } while(ch!='7');    
}



//Funzione menu_contravv: scelta operazioni da fare su contravvenzioni
void menu_contravv()
{   
 char ch;
 char all[3];
 int indice;
 do{
    system("CLS");
    cout<<"\n MENU' CONTRAVVENZIONI";
    cout<<"\n_________________________\n\n";
    cout<<"[1] Visualizza una contravvenzione\n";
    cout<<"[2] Inserisci una nuova contravvenzione\n";
    cout<<"[3] Modifica una contravvenzione\n";
    cout<<"[4] Elimina una contravvenzione\n";
    cout<<"[5] Menu' principale\n\n";
 
    do {
    cout<<">"; cin>>ch;
    cin.ignore();
    }while(ch<'1'||ch>'5');
    switch (ch) {
        case '1': system("CLS");
                  cout<<"\n VISUALIZZA CONTRAVVENZIONE\n____________________________\n";
                  cout<<"\nInserire il numero della contravvenzione da visualizzare\n[0 per visualizzarle tutte]\n>";
                  ins_int(&indice);
                  if (indice!=0) {
                     vis_contravv(lista_contravv,indice);
                     system("PAUSE");
                  }
                  else {
                        NODO_CONTRAVV *vis_all=lista_contravv;
                        do {                         
                            indice=vis_all->dati_contravv.num_contravv;
                            vis_contravv(lista_contravv,indice);
                            vis_all=vis_all->next_contravv;
                            cout<<"\nPremere invio per visualizzare la contravvenzione successiva, X per uscire... ";
                            ins_str(all,2);
                        } while (strcmp(all,"X") && strcmp(all,"x") && vis_all!=NULL);
                        if (strcmp(all,"X") && strcmp(all,"x")) //nota: comportamento di strcmp
                           {
                           cout<<"\nFine elenco contravvenzioni.\n";
                           system("PAUSE");
                           }
                       }                        
                  break;
        case '2': system("CLS");
                  cout<<"\n INSERIMENTO CONTRAVVENZIONE\n_____________________________\n";
                  if (ins_contravv(lista_contravv))
                     cout<<"\nErrore durante l'inserimento\n";
                  system("PAUSE");
                  break;
        case '3': system("CLS");
                  cout<<"\n MODIFICA CONTRAVVENZIONE\n_____________________________\n";
                  mod_contravv(lista_contravv);           
                  break;
        case '4': system("CLS");
                  cout<<"\n ELIMINA CONTRAVVENZIONE\n_____________________________\n";
                  canc_contravv();
                  break;
    }
    system("CLS");
 } while(ch!='5');    
}



//Funzione menu_anagraf: operazioni su dati anagrafici
void menu_anagraf()
{   
 char ch;
 int indice;
 bool esiste;            //variabili condivise tra la sezioni visualizza, modifica e cancella dati anagrafici (case 1 3 4)
 NODO_ANAGRAF *vis_a;    //
 char mdf[3];            //
 char all[3]; 
 do{
    system("CLS");
    cout<<"\n MENU' ANAGRAFICA";
    cout<<"\n_____________________\n\n";
    cout<<"[1] Visualizza dati anagrafici\n";
    cout<<"[2] Inserisci i dati anagrafici di una contravvenzione\n";
    cout<<"[3] Modifica dati anagrafici\n";
    cout<<"[4] Elimina dati anagrafici\n";
    cout<<"[5] Menu' principale\n\n";
 
    do {
    cout<<">"; cin>>ch;
    cin.ignore();
    }while(ch<'1'||ch>'5');
    switch (ch) {   
        case '1': system("CLS");
                  cout<<"\nVISUALIZZA DATI ANAGRAFICI\n______________________________\n";
                  esiste=true;
                  cout<<"\nInserire il codice dei dati anagrafici da visualizzare\n[0 per visualizzarli tutti]\n>";
                  ins_int(&indice);
                  if (indice!=0) {
                     vis_a=lista_anagraf;
                     while (esiste && vis_a->dati_anagraf.cod_anagraf!=indice) {      //è importante l'ordine della proposizione perchè in caso di falseo vis_a punta a null darebbe un crash
                           vis_a=vis_a->next_anagraf;
                           if (vis_a==NULL)
                              esiste=false;
                     }
                     if (esiste)
                        vis_anagraf(lista_anagraf,vis_a);
                     else 
                          cout<<"\nDati anagrafici inesistenti\n";
                     system("PAUSE");
                  }
                  else {
                        NODO_ANAGRAF *vis_all=lista_anagraf;
                        do {                         
                            
                            vis_anagraf(lista_anagraf,vis_all);
                            vis_all=vis_all->next_anagraf;
                            cout<<"\nPremere invio per visualizzare i dati successivi, X per uscire... ";
                            ins_str(all,2);
                        } while (strcmp(all,"X") && strcmp(all,"x") && vis_all!=NULL);
                        if (strcmp(all,"X") && strcmp(all,"x")) {
                           cout<<"\nFine elenco dati anagrafici.\n";
                           system("PAUSE");
                        }
                       }                                   
             
                  break;
        case '2': system("CLS");
                  cout<<"\nINSERIMENTO DATI ANAGRAFICI\n___________________________________\n";
                  
                  cout<<"\nInserisci il numero della contravvenzione a cui inserire i dati anagrafici, \noppure inserisci 0 per cercare tra quelle ancora senza dati anagrafici.\n>";
                  ins_int(&indice);
                  if (indice==0) {
                     cerca_no_anagraf(lista_contravv);
                     break;
                     }
                  if (lista_contravv!=NULL) {
                     NODO_CONTRAVV *cursore=lista_contravv;
                     while (cursore!=NULL) {
                              if (cursore->dati_contravv.num_contravv==indice) { 
                                 if (cursore->dati_contravv.flag_anagraf_ins) {  
                                    cout<<"\nQuesta contravvenzione ha gia' i dati anagrafici inseriti.\n";
                                    break; //caso di contravv con già inseriti i dati anagraf (nota: non è necessario l'else)
                                 }
                                 if ((cursore->dati_contravv.proprietario=ins_anagraf(lista_anagraf))!=NULL)  {  //inserimento dati                                          
                                    cursore->dati_contravv.flag_anagraf_ins=true;
                                    cout<<"\nDati aggiunti correttamente.\n";
                                    }
                                 break;   //dati aggiunti                                 
                              }
                              cursore=cursore->next_contravv;
                     }
                     if (cursore==NULL)
                        cout<<"\nLa contravvenzione cercata non esiste.\n";
                     system("PAUSE"); 
                     break; //necessario perchè il primo break interrompe solamente dal ciclo while
                  }
                  else
                      cout<<"\nErrore: non e' presente alcuna contravvenzione.\n";
                      system("PAUSE");
                      break;//caso di lista vuota
                 
        case '3': system("CLS");
                  cout<<"\nMODIFICA DATI ANAGRAFICI\n___________________________________\n";
                  int index;
                  esiste=true;
                  cout<<"\nInserire il codice dell'anagrafica per visualizzare i dati ed\neventualmente modificarli\n>";
                  ins_int(&index);
                  
                  //ricerca per codice e visualizzazione
                  vis_a=lista_anagraf;
                  while (esiste && vis_a->dati_anagraf.cod_anagraf!=index) {      //è importante l'ordine della proposizione perchè in caso di falseo vis_a punta a null darebbe un crash
                        vis_a=vis_a->next_anagraf;
                        if (vis_a==NULL)
                        esiste=false;
                     }
                  if (esiste) {
                     vis_anagraf(lista_anagraf,vis_a);
                     cout<<"\nPremere INVIO per modificare i dati della contravvenzione, X per uscire... ";
                     ins_str(mdf,2);
                     if (strcmp(mdf,"X") && strcmp(mdf,"x"))
                     mod_anagraf(lista_anagraf,index);     //funzione di modifica
                     }
                  else { 
                      cout<<"\nDati anagrafici inesistenti\n";
                      system("PAUSE");
                      }
                  break;

        case '4': system("CLS");
                  cout<<"\n ELIMINA DATI ANAGRAFICI\n_____________________________\n";
                  esiste=true;
                  cout<<"\nInserire il codice dell'anagrafica per visualizzare i dati ed\neventualmente eliminarli\n>";
                  ins_int(&indice);
                  
                  //ricerca per codice e visualizzazione
                  vis_a=lista_anagraf;
                  while (esiste && vis_a->dati_anagraf.cod_anagraf!=indice) {  
                        vis_a=vis_a->next_anagraf;
                        if (vis_a==NULL)
                        esiste=false;
                     }
                  if (esiste) {
                     vis_anagraf(lista_anagraf,vis_a);
                     cout<<"\nPremere INVIO per eliminare i dati della contravvenzione, X per uscire... ";
                     ins_str(mdf,2);
                     if (strcmp(mdf,"X") && strcmp(mdf,"x"))
                     canc_anagraf(indice);     //funzione di eliminazione dati
                     cout<<"\n --- Dati anagrafici eliminati ---\n";
                     system("PAUSE");
                     }
                  else { 
                      cout<<"\nDati anagrafici inesistenti\n";
                      system("PAUSE");
                      }
                  break;

    }
    system("CLS");
 } while(ch!='5');    
}



//Funzione menu_pagam: scelta operazioni relative ai pagamenti
void menu_pagam()
{   
 int indice;
 char ch;
 do{
    system("CLS");
    cout<<"\n MENU' PAGAMENTI";
    cout<<"\n___________________\n\n";
    cout<<"[1] Visualizza lo stato del pagamento di una contravvenzione\n";
    cout<<"[2] Inserisci un pagamento\n";
    cout<<"[3] Modifica dati pagamento\n";
    cout<<"[4] Elimina pagamento\n";
    cout<<"[5] Statistiche pagamenti\n";
    cout<<"[6] Menu' principale\n\n";
 
    do {
    cout<<">"; cin>>ch;
    cin.ignore();
    }while(ch<'1'||ch>'6');
    switch (ch) {
        case '1': system("CLS");
                  cout<<"\n STATO PAGAMENTI\n_____________________\n";
                  cout<<"\nInserisci il codice della contravvenzione di cui si vuole sapere se e' stato \neffettuato il pagamento:\n>"; 
                  ins_int(&indice);
                  vis_pagam(lista_contravv,indice);
                  system("PAUSE");
                  break;
        case '2': system("CLS");
                  cout<<"\n INSERIMENTO PAGAMENTO\n_________________________\n";
                  cout<<"\nInserisci il numero della contravvenzione a cui inserire la data di pagamento, \noppure inserisci 0 per cercare tra quelle ancora senza dati anagrafici.\n>";
                  ins_int(&indice);
                  if (indice==0) {
                     cerca_no_pagam(lista_contravv);
                     break;
                     }
                  ins_pagam(indice);
                  break;
        case '3': system("CLS");
                  cout<<"\n MODIFICA PAGAMENTO\n______________________\n";
                  cout<<"\nInserisci il numero della contravvenzione a cui modificare la data di pagamento\n>";
                  ins_int(&indice);
                  mod_pagam(lista_contravv,indice);
                  break;
        case '4': system("CLS");
                  cout<<"\n ELIMINA PAGAMENTO\n_____________________\n";
                  cout<<"\nInserisci il numero della contravvenzione a cui eliminare la data di pagamento\n>";
                  ins_int(&indice);
                  canc_pagam(lista_contravv,indice);
                  break;
        case '5': system("CLS");
                  cout<<"\n STATISTICHE PAGAMENTI\n_______________________\n";
                  bilancio(lista_contravv);
                  system("PAUSE");
                  break;
    }
    system("CLS");
 } while(ch!='6');    
}



//Funzione menu_cerca: interfaccia per le operazioni di ricerca
void menu_cerca()
{   
 char ch;
 do{
    system("CLS");
    cout<<"\n MENU' CERCA";
    cout<<"\n______________\n\n";
    cout<<"[1] Ricerca per contravvenzione\n";
    cout<<"[2] Ricerca per dati anagrafici\n";
    cout<<"[3] Ricerca le contravvenzioni senza dati anagrafici\n";
    cout<<"[4] Ricerca le multe non pagate\n";
    cout<<"[5] Menu' principale\n\n";
 
    do {
    cout<<">"; cin>>ch;
    cin.ignore();
    }while(ch<'1'||ch>'5');
    switch (ch) {
        case '1': //cerca_contravv;
                  break;
        case '2': //cerca_anagraf;
                  break;
        case '3': system("CLS");
                  cout<<"\n RICERCA CONTRAVVENZIONI SENZA DATI ANAGRAFICI\n_______________________________________________\n";
                  cerca_no_anagraf(lista_contravv);
                  break;
        case '4': system("CLS");
                  cout<<"\n RICERCA CONTRAVVENZIONI NON PAGATE\n____________________________________________\n";
                  cerca_no_pagam(lista_contravv);
                  break;
    }
    system("CLS");
 } while(ch!='5');    
}


//Funzione esci: permette di uscire dal programma e chiede se deve salvare
void esci()
{   
 system("CLS");
 cout<<"USCITA IN CORSO...\n\nSalvare i dati?\n\n";
 salva(); 
}




/*____________________________________________________________________________________________________________________________________________

******************* 
  NOTE IMPORTANTI
*******************

Caricamento e salvataggio file:
            I file devono esistere anche se vuoti e avere dimensione maggiore di 0byte (devono contenere almeno un carattere)
            Ovviamente non è possibile modificare/salvare file memorizzati su supporti ottici come CD o DVD (file in sola lettura)
            Se il programma, eseguito in una finestra di terminale, viene interrotto chiudendo questa finestra, i dati modificati non saranno salvati (a meno dell'esplicito salvataggio dell'utente)

Limiti del programma:
       E' possibile memorizzare al massimo "unsigned long int" elementi nelle due liste dinamiche; superato questo valore i codici non sono più univoci.       
       Un limite è dato dalla lunghezza fissa delle stringhe; dati eccessivamente lunghi possono portare a comportamenti errati del programma; comunque si è cercato di attribuire una dimensione ragionevole per i diversi tipi di variabile
       Le funzioni system fanno riferimento a comandi relativi al terminale di windows; pertanto il codice non è adatto a essere utilizzato per altri ambienti operativi
     
_____________________________________________________________________________________________________________________________________________*/
