Stazione di monitoraggio 4
..:: Versione con numero di righe arbitrario ::..
Un dispositivo di rilevazione misura diversi parametri ambientali per mezzo di sensori. I dati misurati vengono memorizzati in un file insieme all'istante temporale nel quale sono rilevati (detto, in gergo, timestamp).
Ciascuna riga del file ha il seguente formato:
AAAA-MM-GG hh:mm:ss.ms ID TEMP UMID VEL
Il significato dei diveri elementi è riportato nella seguente tabella.
Valore | Significato | Tipo | Intervallo/dimensione |
---|---|---|---|
AAAA | anno | intero | |
MM | mese | intero | [1..12] |
GG | giorno | intero | [1..31] |
hh | ore | intero | [0..23] |
mm | minuti | intero | [0..59] |
ss | secondi | intero | [0..59] |
ms | millisecondi | intero | [0..999] |
ID | identificativo del dispositivo | stringa | max 10 caratteri |
TEMP | temperatura [gradi] | float | |
UMID | umidità [%] | intero | [0..100] |
VEL | velocità del vento [m/s] | float | >= 0 |
Un esempio di contenuto del file è il seguente:
2019-03-03 23:59:10.120 ID000 17.5 20% 0.4
2019-03-02 07:41:59.001 ID001 16.9 22% 0.2
2019-03-01 12:10:00.000 ID002 22.5 21% 0.3
Scrivere un programma che legga il file nel formato illustrato e stampi a video i valori richiesti nei seguenti quesiti.
Suggerimenti generali
In questo esercizio il numero di righe presenti nel file non è noto a priori.
La lettura di tutte le righe può essere fatta allocando con malloc
il vettore che ospita i dati, e ri-allocando con realloc
il vettore per estenderne la dimensione qualora il numero di righe da leggere crescesse oltre le dimensioni del vettore correntemente allocato.
1) Identificativi
Il programma deve stampare a video tutti gli indentificativi in ordine invertito rispetto al loro ordine nel file. La stampa avvenga utilizzando il formato come nell'esempio seguente:
[IDENTIFICATIVI]
ID002
ID001
ID000
Suggerimenti generali
Dovendo stampare i dati in ordine inverso rispetto al loro ordine nel file, i dati vanno prima caricati in memoria per poterli poi stampare.
In questo caso, non c'è modo di conoscere a priori il numero di righe presenti nel file, ne' è possibile calcolarne il numero massimo. Pertanto il vettore per ospitare i dati letti non può essere allocato prima di iniziare la lettura perché non se ne conosce la dimensione.
Puoi utilizzare il seguente metodo:
- alloca inizialmente un vettore di
dim
elementi utilizzando lamalloc
;dim
è una variabile il cui valore iniziale può essere un numero a piacere (per esempio4
); - comincia a leggere il file con il solito ciclo
while
e le funzionifgets
esscanf
(vedi S8.6) - all'interno del ciclo
while
, quando il numero di righe lette e memorizzate è pari adim
, aumenta il valore didim
(per esempio raddoppiandolo) e usa larealloc
per aumentare la dimensione del vettore - ricorda che per estrarre una stringa con
sscanf
si usa lo specificatore%s
(S8.6!- nella
sscanf
, la variabile stringa nella quale memorizzare il nome estratto va passato per riferimento (e visto che si tratta di un vettore dichar
non serve la&
)
- nella
Il nome del file da leggere sarà l'argomento argv[1]
del main
(vedi S6.9), mentre per aprire il file in lettura con fopen
(S8.2.1).
Puoi creare una funzione di lettura dichiarata come la segue:
struct misura *leggi_file(FILE *f, int *n);
La funzione restituisce un puntatore a struttura di tipo struct misura
, che contiene l'indirizzo del primo elemento del vettore di strutture allocato tramite malloc
all''interno della funzione e usato per ospitare i dati letti.
Gli argomenti della funzione, invece, sono due:
f
: il file da leggere, già aperto in lettura prima di chiamareleggi_file
(S8.2.1)n
: l'indirizzo di un intero che viene usato per restituire, tramite passaggio per riferimento, il numero di elementi memorizzati nel vettore.
Per la stampa degli identificativi puoi definire una funzione come la seguente:
void stampa_elenco(struct misura *elenco, int n);
alla quale passare il vettore (parametro elenco
) e il numero di elementi in esso contenuti (n
).
Nel main
:
- dichiara la variabile puntatore a
struct misura
per puntare al vettore di strutture; - apri il file con
fopen
- chiama la funzione
leggi_file
ed effettua la lettura - passa il vettore alla
stampa_elenco
per la stampa
Verifica manuale
La verifica del funzionamento del programma può essere fatta manualmente, utilizzando il file di input file4.txt come esempio, richiamando l'eseguibile come segue:
./a.out file4.txt
Verifica automatica
Si può utilizzare il tool pvcheck
di verifica automatica per testare il corretto funzionamento del programma (maggiori informazioni circa l'uso di pvcheck
sono disponibili qui).
Il file contenente i test è misure4.test.
Il comando da eseguire per il test è il seguente:
pvcheck -f misure4.test ./a.out
Nella prossima pagina potrai esaminare un esempio di soluzione dell'esercizio.