001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<string.h>
004: 
005: // per semplicita' di lettura definisco costante per memorizzare numero comuni
006: #define NCOMUNI (7900)
007: 
008: // PUNTO 1: definisco struct con dati singolo comune
009: struct comune
010: {
011:   char *nome, provincia[3], codice[5];
012: };
013: 
014: // prototipi funzioni definite dopo la main()
015: struct comune leggiriga(FILE *);
016: void stampacomuni(struct comune *);
017: void stampaprovincia(struct comune *, char *);
018: void ordinacomuni(struct comune *);
019: 
020: int main(int argc, char **argv){
021: 
022:   // PUNTO 1: definisco array struct per memorizzare tutti i 7900 comuni
023:   struct comune dati[NCOMUNI];
024: 
025:   FILE *fp;
026:   fp = fopen("comuni.csv", "r");
027:   if(!dati)
028:   {
029:     perror("");
030:     exit(EXIT_FAILURE);
031:   }
032: 
033:   //PUNTO 2: invoco funzione definita e riempo struttura dati
034:   for(int i = 0; i < NCOMUNI; ++i)
035:   {
036:     dati[i] = leggiriga(fp);
037:     // NOTA: il contenuto di una struct puo' essere copiato tranquillamente anche se
038:     // contiene array all'interno
039:   }
040: 
041:   // PUNTO 3: invocazione funzione stampacomuni()
042:   //stampacomuni(dati);
043: 
044:   // PUNTO 4: invocazione di debug della funzione stampaprovincia()
045:   stampaprovincia(dati, "BZ");
046: 
047:   // PUNTO 5: invocazione e stampa array ordinato
048:   ordinacomuni(dati);
049:   stampacomuni(dati);
050: 
051: 
052: 
053:   return 0;
054: }
055: 
056: // PUNTO 2
057: struct comune leggiriga(FILE *input)
058: {
059:   // temporanei per lettura dal file
060:   char nome_tmp[1000];
061:   char provincia_tmp[3];
062:   char codice_tmp[5];
063: 
064:   // provo a leggere dal file, memorizzo quanto restituito dallla fscanf() per controllare se lettura e' andata a buon fine
065:   int check = fscanf(input, " %[^;];%[^;];%s", nome_tmp, provincia_tmp, codice_tmp);
066:   // come interpretare la stringa di formato (lo spazio iniziale e' per evitare che lo '\n' finisca nelle stringhe: 
067:   // 1. leggo primo elemento fino al primo ; escluso,
068:   // 2. salto un ;, 
069:   // 3. leggo il secondo elemento fino al primo ; escluso, 
070:   // 4. salto un ;
071:   // 5. leggo la terza stringa fino alla fine della linea
072:   
073:   // controllo di aver letto 3 elementi e in caso negativo esco
074:   if(check != 3)
075:   {
076:     printf("ERRORE: non sono riuscito a leggere dal file...\n");
077:     exit(EXIT_FAILURE);
078:   }
079: 
080: 
081:   // definisco struct da restituire
082:   struct comune tmp;
083: 
084:   // sigla provincia e codice catasto posso tranquillamente copiarli in quanto lunghezza gia' definita
085:   strcpy(tmp.provincia, provincia_tmp);
086:   strcpy(tmp.codice,    codice_tmp);
087: 
088:   // per nome comune prima devo allocare
089:   tmp.nome = malloc(sizeof(char) * (strlen(nome_tmp) + 1));
090:   // solo dopo posso copiare
091:   strcpy(tmp.nome,      nome_tmp);
092: 
093:   return tmp;
094: }
095: 
096: // PUNTO 3
097: void stampacomuni(struct comune *a)
098: {
099:   printf("ELENCO COMUNI:\n");
100:   // banale ciclo di stampa
101:   for(int i = 0; i < NCOMUNI; ++i)
102:     printf(" %60s %s %s\n", a[i].nome, a[i].provincia, a[i].codice); 
103: 
104: }
105: 
106: // PUNTO 4
107: 
108: // funzione di appoggio necessaria per la qsort()
109: int confrontocomuni(const void *a, const void *b)
110: {
111:   // converto tipo puntatori
112:   const struct comune *primo   = (const struct comune *)a;
113:   const struct comune *secondo = (const struct comune *)b;
114: 
115:   // sfrutto e ritorno direttamente risultato strcmp()
116:   return strcmp(primo->provincia, secondo->provincia);
117: }
118: 
119: void stampaprovincia(struct comune *a, char *sigla)
120: {
121:   printf("ELENCO COMUNI DELLA PROVINCIA ""%s"":\n", sigla);
122:   // banale ciclo di stampa
123:   for(int i = 0; i < NCOMUNI; ++i)
124:     if(! strcmp(a[i].provincia, sigla) )
125:       printf(" %60s %s %s\n", a[i].nome, a[i].provincia, a[i].codice); 
126: 
127: }
128: 
129: // PUNTO 5
130: void ordinacomuni(struct comune *a)
131: {
132:   qsort(a, NCOMUNI, sizeof(struct comune), confrontocomuni);
133: }
134: