001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<float.h>
004:
005: // definizione struttura per #2
006: // di fatto usero' un array di queste struct in cui l'indice dell'elemento corrisponde all'ID sensore
007: struct sensore
008: {
009: unsigned short nmis; // numero misure
010: double avg; // valor medio
011: double min, max; // minimo e massimo
012: unsigned short ncresc; // lunghezza massima sequenza crescente
013: unsigned int newest; // data misura piu' recente (la memorizzo come singolo unsigned int senza spezzettare in giorno, mese e anno)
014: };
015:
016: int confrontadate(unsigned int, unsigned int); // funzione che uso per confrontare le date delle misure, per leggibilita'
017: unsigned short giorno(unsigned int); // estrae il giorno dalla data memorizzata come unsigned int
018: unsigned short mese(unsigned int); // estrae il mese dalla data memorizzata come unsigned int
019: unsigned short anno(unsigned int); // estrae l'anno dalla data memorizzata come unsigned int
020:
021: int main(int argc, char **argv){
022:
023: // per #1 capisco se nome file era passato su linea comando altrimenti chiedo all'utente
024: FILE *fp;
025: if(argc < 2)
026: {
027: char nome_file[1000];
028: printf("Inserisci il nome del file da analizzare: ");
029: scanf("%s", nome_file);
030: fp = fopen(nome_file, "r");
031: }
032: else
033: {
034: fp = fopen(argv[1], "r");
035: }
036: // Nota: in base al testo potevo comunque limitarmi a una sola delle due alternative
037:
038: if(!fp)
039: {
040: perror("");
041: exit(EXIT_FAILURE);
042: }
043:
044: // #3 definisco array vuoto
045: struct sensore *dati = NULL;
046: int nsensors = 0;
047:
048: // temporanei per lettura da file
049: unsigned int data; // di fatto e' vedibile come numero e l'intervallo possibile e' coerente con un unsigned int ~ 20 milioni
050: unsigned int sensor; // id sensore
051: double misura;
052:
053: unsigned int ndati = 0;
054: while(fscanf(fp, "%u;%u;%lf", &data, &sensor, &misura) == 3)
055: {
056: ++ndati;
057: if(sensor >= nsensors) // nell'array l'elemento di indice 'sensor' ancora non e' presente, devo allargare l'array
058: {
059: dati = realloc(dati, sizeof(struct sensore)*(sensor+1));
060: // devo inizializzare quanto aggiunto all'array
061: // ma non e' detto che io abbia aggiunto un solo valore
062: for(int i = nsensors; i < (sensor + 1); ++i)
063: {
064: dati[i].nmis = 0;
065: dati[i].avg = 0;
066: dati[i].min = 1001; // oltre intervallo specifiche
067: dati[i].max = -1001; // sotto intervallo specifiche
068: dati[i].newest = 0; // valore insensato per data ma comunque sufficientemente basso
069: }
070: nsensors = sensor + 1;
071: }
072:
073: // aggiorno elemento corrispondente al sensore
074: dati[sensor].nmis++;
075: dati[sensor].avg += misura; // in fase di lettura accumulo qui i valori, la media vera e propria la calcolerò finita la lettura
076:
077: // aggiorno eventualmente massimo e minimo valore letto
078: if(misura < dati[sensor].min)
079: dati[sensor].min = misura;
080:
081: if(misura > dati[sensor].max)
082: dati[sensor].max = misura;
083:
084:
085: // stessa cosa per la data, ma qui sfrutto opportuna funzione per confrontare
086: if(confrontadate(dati[sensor].newest, data) < 0)
087: dati[sensor].newest = data;
088: }
089: fclose(fp);
090:
091: // a valle della lettura calcolo media
092: for(int i = 0; i < nsensors; ++i)
093: {
094: if(dati[i].nmis)
095: dati[i].avg = dati[i].avg/dati[i].nmis;
096: }
097:
098: // #4 stampo dati inerenti struttura
099: printf("Ho letto dal file '%s' %d misure distribuite su %d sensori\n", argv[1], ndati, nsensors);
100: for(int i = 0; i < nsensors; ++i)
101: {
102: if(dati[i].nmis)
103: printf("#%02d: %3u misur%c, media %8g, min. %8g, max. %8g, ultimo %02u/%02u/%4u\n",
104: i, // id sensore
105: dati[i].nmis, // numero misure di quel sensore
106: (dati[i].nmis>1?'e':'a'), // lo uso per scrivere misure o misura
107: dati[i].avg, // media
108: dati[i].min, // minimo
109: dati[i].max, // massimo
110: giorno(dati[i].newest), // giorno ultima misura
111: mese(dati[i].newest), // mese ultima misura
112: anno(dati[i].newest) // anno ultima misura
113: );
114: else
115: printf("#%02d: NA\n", i);
116: }
117:
118: // #5 stampo occupazione memoria. Devo considerare: dimensione area allocata, dimensione puntatore e dimensione variabile d'appoggio per stimare numero elementi)
119: printf("Occupazione memoria: %ld byte\n", sizeof(dati[0])*nsensors + sizeof(dati) + sizeof(nsensors));
120:
121: return 0;
122: }
123:
124:
125: // nelle seguenti funzioni sfrutto divisioni intere e moduli per spezzettare la data in giorni, mese, anno
126: // ad esempio supponiamo che la data sia il 9 febbraio 2023. Nel file avro' avuto 09022023. Se lo leggo come numero otterro' 9022023
127: // il giorno lo ricavo semplicamente dividendo (divisione intera) per 1000000 -> 9022023/1000000 = 9
128: // l'anno e' il resto della divisione intera per 10000 -> 9022023%10000 = 2023
129: // il mese e' un po' piu complesso, prima prendo il resto della divisione per 1000000 -> 9022023%1000000 = 022023 (ovvero 22023)
130: // e quindi divido (sempre divisione intera) per 10000 -> 22023/10000 = 2
131:
132: unsigned short giorno(unsigned int data)
133: {
134: return data/1000000; // le prime due cifre sono il giorno, posso usare la divisione intera per 1000000 per estrarle
135: }
136:
137: unsigned short mese(unsigned int data)
138: {
139: return (data%1000000)/10000; // prendo le 6 cifre meno significative con il resto della divisione intera per 1000000 e poi elimino le 4 meno significative dividendo per 10000
140: }
141:
142: unsigned short anno(unsigned int data)
143: {
144: return data%10000; // le 4 cifre meno significative sono l'anno, le estraggo con il resto della divisione per 10000
145: }
146:
147: // prendo in ingresso le due date come unsigned int
148: // sfrutto le funzioni precedentemente definite per estrarre giorno, mese e anno
149: // e poi li confronto
150: // la funzione restituisce 0 se le due date sono identiche
151: // < 0 se a precede b
152: // > 0 nel caso opposto
153: int confrontadate(unsigned int a, unsigned int b)
154: {
155: unsigned short aa = anno(a);
156: unsigned short ab = anno(b);
157:
158: unsigned short ma = mese(a);
159: unsigned short mb = mese(b);
160:
161: unsigned short ga = giorno(a);
162: unsigned short gb = giorno(b);
163:
164: if(aa != ab)
165: return aa-ab;
166:
167: if(ma != mb)
168: return ma-mb;
169:
170: return ga-gb;
171: }
172: