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 la malloc; dim è una variabile il cui valore iniziale può essere un numero a piacere (per esempio 4);
  • comincia a leggere il file con il solito ciclo while e le funzioni fgets e sscanf (vedi S8.6)
  • all'interno del ciclo while, quando il numero di righe lette e memorizzate è pari a dim, aumenta il valore di dim (per esempio raddoppiandolo) e usa la realloc 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 di char non serve la &)

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 chiamare leggi_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.