PDA

View Full Version : [C] problema con un esercizio


Count_z3r0
14-09-2004, 16:20
salve a tutti, ho un problema con un esercizio trovato online

dunque ogni riga(max 20) del file EFFEMERIDI.TXT contiene:
-la data del rilevamento astronomico nel formato gg/mm/aaaa
-una stringa di orari nel formato hh:mm in cui sono specificati: l'orario del crepuscolo, l'orario del sorgere e l'orario del tramonto della Luna
-una stringa che rappresenta un numero che determina la fase (da 0,00 a 1,00. 1,00 luna piena)

e ho due tipi di strutture:
rilievo destinato a contenere i dati di una riga del file EFFEMERIDI.TXT
rilievi che contiene un array di strutture di tipo rilievo e il numero di
righe effettivamente lette.

ora io devo creare una funzione leggi che: dato il nome di un file riempie una struttura di tipo rilievi contenente le righe lette dal file. La funzione restituisce 1 se l'operazione è andata a buon fine, altrimenti restituisce 0.

dunque ho così costruito le due struct:
typedef struct {
int giorno, mese, anno, orec, minutic, ores, minutis, oret, minutit;
float fase;
}rilievo;

typedef struct {
rilievo r[MAX];
int num;
}rilievi;


i problemi insorgono sulla funzione leggi.
in rete ho trovato questa soluzione:

int leggi(char nomefile[],rilievi *r)
{
FILE* f;
if((f=fopen(nomefile, "r"))==NULL){printf("Errore durante l'apertura del
file %s", nomefile);return 0;}
for(r->num=0;;r->num++)
if(fscanf(f,"%d/%d/%d%d:%d%d:%d%d:%d%f\n",
&r->r[r->num].giorno, &r->r[r->num].mese, &r->r[r->num].anno,
&r->r[r->num].orec, &r->r[r->num].minutic,
&r->r[r->num].ores, &r->r[r->num].minutis,&r->r[r->num].oret,
&r->r[r->num].minutit, &r->r[r->num].fase)==EOF) break;
fclose(f);
return 1;
}

ma non riesco a capire il significato di tutte quelle &r->r[r->num] , cioè che cosa fanno??! la funzione dovrebbe essere corretta, nascosto però è per me il suo funzionamento.



mi scuso per il lungo post, ma la questione è molto importante per me e volevo essere il più chiaro possibile.
vi ringrazio anticipatamente :)

anx721
14-09-2004, 17:29
Non ho letto tutto il tipo, ati spiego il senso di &r->r[r->num] :

la funzione fscanf legge dei dati da un file e li memorizza in delle variabili. Per memorizzare un dato in una variabile bisona passare il puntatore alla variabile, che si ottiene tramite l'operatore &. Quindi con

&r->r[r->num]

si passa l'indirizzo di r -> r[r -> num]


In

r->r[r->num]

r -> r indica il campo r della variabile r passata come argomento (una scelta infelice del nome, fa si che il paramntro della funzione e il campo della struttra hanno lo setsso nome..ma in r->r le due r sono cose diverse, la prima r indica la variabile passata alla funzione, la seconda r indica il campo r di quella variabile che è un puntatore a rilievi).

Ziosilvio
14-09-2004, 17:51
Originariamente inviato da Count_z3r0
int leggi(char nomefile[],rilievi *r)
{
FILE* f;
if((f=fopen(nomefile, "r"))==NULL) {
printf("Errore durante l'apertura del file %s",
nomefile);
return 0;
}
for(r->num=0;;r->num++)
if(fscanf(f,"%d/%d/%d%d:%d%d:%d%d:%d%f\n",
&r->r[r->num].giorno,
&r->r[r->num].mese,
&r->r[r->num].anno,
&r->r[r->num].orec,
&r->r[r->num].minutic,
&r->r[r->num].ores,
&r->r[r->num].minutis,
&r->r[r->num].oret,
&r->r[r->num].minutit,
&r->r[r->num].fase)==EOF)
break;
fclose(f);
return 1;
}
Azzardo una traduzione in pseudocodice:
- cerca di aprire il file in lettura e restituisci "falso" se non ci riesci;
- leggi piu' stringhe che puoi nel formato dato, immagazzinando i valori letti nel vettore r;
- chiudi il file e restituisci "vero".

Passiamo alla fscanf: come sai, essa ha come argomenti un puntatore a file, una stringa di formato, e una sequenza di puntatori.
Qui la stringa di formato e':
"%d/%d/%d%d:%d%d:%d%d:%d%f\n"
cioe: "un intero decimale, una barra, un intero decimale, una barra, un intero decimale, un intero decimale, due punti, un intero decimale, un intero decimale, due punti, un intero decimale, un intero decimale, due punti, un intero decimale, un float, un carattere di andata a capo"; cioe' il formato che serve a te.

I campi con la & hanno tutti la forma:
&r->r[r->num].x
Ora, la & ha priorita' minore degli altri operatori di questa espressione, che percio' equivale a:
&(r->(r[r->num].x))
cioe': la zona di memoria in cui si trova il campo x dell'elemento di ordine r->num del campo r dell'oggetto puntato da r; in altre parole, il campo che devi aggiornare con i dati letti dal file.

Per ora dovrebbe bastare.
Dai anche un'occhiata alla guida in linea del tuo compilatore (o alle man page di Linux) e tieni sotto mano un buon manuale di linguaggio C, ad esempio il K&R.

Count_z3r0
14-09-2004, 19:29
vi ringrazio entrambi siete stati chiarissimi :)
penso proprio di avere capito!

thanx