File binario

di Anonimizzato28727 il
8 risposte
Salve, ho realizzato un programma dove ho inserito le funzioni ScrivereFile e CalcolareDimensioneFile.
Ho dovuto realizzare la funzione ScrivereFile perchè nella traccia dell'esercizio c'è scritto di considerare di avere un file binario scritto nel seguente modo:
139 13 3
123 24 3
94 15 3
133 21 2
118 22 4
116 24 4
Queste sono le funzioni:
void ScrivereFile(FILE **fd, char nomefile[]){
	int buffer[] = {139,13,3,123,24,3,94,15,3,133,21,2,118,22,4,116,24,4};

	fwrite(buffer, sizeof(int), 18, *fd);
	fseek(*fd, 0, SEEK_SET);

	return;
}

void CalcolareDimensioneFile(FILE *fp, VettoreDati *d){
	int vett[3];
	int res;
	int cont = 0;
	int i = 0;

	while(1){
		res = fread(vett, sizeof(int), 3, fp);
        /*test*/printf("%d %d %d\n",vett[i], vett[i + 1], vett[i + 2]);
		cont++;
		if (res != 3){
			cont--;
			break;
		}
	}

	d->dimensione = cont;
	printf("dim: %d \n",d->dimensione);
	fseek(fp, 0, SEEK_SET);

	return;
}
Perchè quando mi stampa la dimensione dice che dim è uguale a 341?
Il risultato corretto dovrebbe essere 6 (ovvero il numero di triple presenti nel file).

8 Risposte

  • A me dà 6 ma ho modificato il tuo codice.

    Nella prima funzione non usi il nomefile e non si capisce perché usi un doppio puntatore.

    Nella seconda funzione, non uso il secondo parametro perché non conosco la struttura che usi.

    Manca totalmente il main.
  • Effettivamente il doppio puntatore e il nomefile non servono, questo é il codice completo.
    /*Un file binario contiene il numero di presenze degli studenti alle lezioni di un corso.
    Ogni elemento del file contiene 3 valori. Come esempio si consideri il seguente file.
    139 13 3
    123 24 3
    94 15 3
    133 21 2
    118 22 4
    116 24 4
    Il primo valore rappresenta il numero di studenti presenti, il secondo e il terzo rispettivamente giorno e
    mese della lezione (si suppone che le lezioni abbiano luogo tutte nello stesso anno solare).
    Si noti che il file non e’ ordinato.
    Si scriva una funzione che prende come parametro il nome del file (sicuramente presente su disco) e
    restituisce il numero di studenti della prima lezione del corso (cioè la lezione la cui data è minima
    tra quelle presenti nel file). Nell’esempio la funzione deve restituire 133, cioè il numero di presenze
    del 21 febbraio.
    La funzione deve restituire 0 nel caso che qualche data abbia contenuto non valido: valore del mese maggiore
    di 12, oppure valore del giorno maggiore del numero di giorni del mese (ad esempio 23/14, 31/06).*/
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define DIM 1000
    #define LEN 3
    #define MESI 12
    
    typedef struct{
    	int presenze;
    	int giorno;
    	int mese;
    }Dati;
    
    typedef struct{
    	Dati *elenco;
    	int dimensione;
    }VettoreDati;
    
    typedef struct{
    	int giornidelmese[MESI];
    }VerificaGiorni;
    
    void ScrivereFile(FILE *fd);
    int NumeroStudentiPrimaLezione(char nomefile[], VettoreDati *p, VerificaGiorni calendario);
    int LeggereFile(FILE **fp, char nomefile[]);
    void CalcolareDimensioneFile(FILE *fp, VettoreDati *d);
    void AllocareMemoriaElenco(Dati **elenco, int dim);
    int VerificaCorrettezzaGiornoEMese(int giorno, int mese, VerificaGiorni calendario);
    int TrovareNumeriStudentiPrimaLezione(VettoreDati *p);
    
    int main(void){
    	char nomefile[DIM];
    	int num;
    	VettoreDati tabulato;
    	VerificaGiorni calendario = {{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
    
    	strcpy(nomefile, "dati.dat");
    
    	num = NumeroStudentiPrimaLezione(nomefile, &tabulato, calendario); /*restituisce il numero di studenti della prima lezione del corso,
    													restituisce 0 nel caso in cui qualche data abbia contenuto non valido*/
    
    	printf("numero presenze della prima lezione> %d\n",num);
    
    	system("pause");
    	return 0;
    }
    
    int NumeroStudentiPrimaLezione(char nomefile[], VettoreDati *p, VerificaGiorni calendario){
    	FILE *fp;
    	int esito;
    	int vett[LEN];
    	int res;
    	int i = 0;
    	int j = 0;
    	int num;
    	int k = 1;
    
    	esito = LeggereFile(&fp, nomefile);
    	printf("esito> %d\n",esito);
    
    	if (esito == 0){
    		printf("return");
    		return esito;
    	}
    
    	ScrivereFile(fp); //necessario per svolgere la traccia
    
    
    	CalcolareDimensioneFile(fp, p);
    	AllocareMemoriaElenco(&p->elenco, p->dimensione);
    	printf("dim: %d \n",p->dimensione);
    
    	do{
    		j = 0;
    		res = fread(vett, sizeof(int), 3, fp);
    		printf("res> %d\n",res);
    		if (res == LEN){
    			(p->elenco + i)->presenze = vett[j];
    			printf("presenze %d\n",(p->elenco + i)->presenze);
    			(p->elenco + i)->giorno = vett[j + 1];
    			printf("giorno %d\n",(p->elenco + i)->giorno);
    			(p->elenco + i)->mese = vett[j + 2];
    			printf("mese %d\n",(p->elenco + i)->mese);
    			k = VerificaCorrettezzaGiornoEMese((p->elenco + i)->giorno, (p->elenco + i)->mese, calendario);
    			printf("k> %d\n",k);
    			i++;
    		}
    	}while (res == LEN && k == 1);
    
    	fseek(fp, 0, SEEK_SET);
    
    	num = TrovareNumeriStudentiPrimaLezione(p);
    
    	return num;
    }
    
    int LeggereFile(FILE **fp, char nomefile[]){
    	int i = 1;
    	if ((*fp = fopen(nomefile, "r+")) == NULL){
    		i = 0;
    	}
    
    	return i;
    }
    
    void ScrivereFile(FILE *fd){
    	int buffer[] = {139,13,3,123,24,3,94,15,3,133,21,2,118,22,4,116,24,4};
    
    	fwrite(buffer, sizeof(int), 18, fd);
    	fseek(fd, 0, SEEK_SET);
    
    	return;
    }
    
    void CalcolareDimensioneFile(FILE *fp, VettoreDati *d){
    	int vett[LEN];
    	int res;
    	int cont = 0;
    	int i = 0;
    
    	while(1){
    		res = fread(vett, sizeof(int), 3, fp);
    		printf("%d %d %d\n",vett[i], vett[i + 1], vett[i + 2]);
    		cont++;
    		if (res != LEN){
    			cont--;
    			break;
    		}
    	}
    
    	d->dimensione = cont;
    	printf("1dim: %d \n",d->dimensione);
    	fseek(fp, 0, SEEK_SET);
    
    	return;
    }
    
    void AllocareMemoriaElenco(Dati **elenco, int dim){
    	*elenco = malloc (dim * sizeof(Dati));
    
    	return;
    }
    int VerificaCorrettezzaGiornoEMese(int giorno, int mese, VerificaGiorni calendario){
    	int i = 1;
    	if (mese > 12 || mese < 1){
    		return 0;
    	}
    	if ((giorno > *(calendario.giornidelmese + mese - 1)) || giorno < 1){
    		return 0;
    	}
    
    	return i;
    }
    
    int TrovareNumeriStudentiPrimaLezione(VettoreDati *p){
    	int i = 0;
    	int j;
    	int min = (p->elenco + i)->mese;
    
    	while (i < MESI){
    		if (min > (p->elenco + i)->mese){
    			min = (p->elenco + i)->mese;
    			j = i;
    		}
    		i++;
    	}
    
    	return (p->elenco + j)->presenze;
    }
    
  • La fopen per un file binario deve includere la b, quindi

    "rb+"

    Ma attenzione, con "rb+" il file deve esistere per essere aperto. Per crearlo deve essere "wb+"
  • Ho provato a scrivere rb+ ma continua a stampare dim> 341.
    Inoltre questa printf
    printf("%d %d %d\n",vett, vett[i + 1], vett[i + 2]);
    dopo aver stampato i valori presenti nel file, mi stampa tanti zeri che non dovrebbe stampare.
  • Il file con rb+ deve esistere. Se non esiste va creato con wb. Il codice che hai postato apre prima il file ma se non esiste si ferma.

    Quale ambiente e compilatore usi?
  • 
    #define MESI 12
    
    typedef struct{
    	int giornidelmese[MESI];
    }VerificaGiorni;
    
    int main(void){
    	VerificaGiorni calendario = {{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
    
    Questi codice è "boilerplate"

    È meglio scrivere (non siamo in Java che deve essere tutto incapsulato)
    
    const int giornidelmese[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    int main(void){
    
    Ricordati che il boilerplate ha un costo: quando commetti un piccolo errore, passi molto tempo ad individuarlo.
  • Il file binario l'ho creato a mano, ovvero su eclipse ho creato un file con estensione .dat, é sbagliato?
  • Apri il file con un editor esadecimale e vedi cosa hai creato
Devi accedere o registrarti per scrivere nel forum
8 risposte