[C] Errore fseek()

di il
22 risposte

[C] Errore fseek()

Salve a tutti, è il primo post che faccio, quindi perdonatemi se sarò impreciso o non chiaro..

Sono uno studente iscritto al primo anno di Ingegneria Informatica e sono alle prese con un progetto: Devo realizzare un programma che simula un sistema di archiviazione dei farmaci prescritti ad una lista di pazienti dal medico curante.
Il programma inizialmente richiede il login di un medico, carica in memoria tutti i pazienti associati al medico che ha effettuato il login (prendendo i record da un file binario "pazienti") per poi presentare un menu al medico che gli permette di agire sui record dei pazienti.

Alla chiusura, il programma deve salvare nel file "pazienti" le modifiche effettuate (sovrascrivendo quindi tutti i record dei pazienti associati al medico che ha fatto accesso al sistema, ma senza perdere i dati dei pazienti già presenti nel file-archivio)

Ora, tutte le funzioni sono state scritte e funzionano correttamente.... tranne il salvataggio X.x
Logicamente e sintatticamente non riesco a trovare errori ed eseguendo il debug del codice, ho notato che la fseek che dovrebbe riportare il file pointer all'inizio del record appena letto, per poi sovrascriverlo, non funziona correttamente..
In pratica, verificando con una ftell prima e dopo la fseek la posizione del file pointer sembrerebbe tutto normale, ma andando poi a verificare a cosa punta il file pointer, noto che punta ad una posizione diversa da quella a cui dovrebbe, e di conseguenza la successiva fwrite scrive in posizione sbagliata e corrompe il file (oltre a far entrare in un ciclo infinito il programma con la fread che gestisce il ciclo)...

Ormai non so più cosa provare, ho fatto tutti i controlli a cui potevo pensare, ma non sono riuscito ad andare oltre X.x
Qualche idea?

Allego il codice della funzione salva:
int salva(Paziente pazienti[],int dimP,int medico) 
{
	FILE *fp=NULL;
	int i=0,pos,dim;
	Paziente p;
	fp= fopen("pazienti","rb+");
	if(fp==NULL)
	{
		printf("Errore nell'apertura dell'archivio pazienti\n");
		return(0);
	}	
	
	dim=sizeof(Paziente); //Usata per il debug

	do
	{
		fread(&p,sizeof(Paziente),1,fp);
		dim=sizeof(p); //Usata per il debug (controllavo che dim(p) fosse costante)
		pos=ftell(fp); //Usata per il debug (verifica posizione settata da fseek)
		if(p.medico_curante == medico) //medico è un numero che identifica il medico, e deve corrispondere a p.medico_curante
		{
 			fseek(fp,(-1)*(sizeof(p)),SEEK_CUR);
			pos=ftell(fp); //Usata per il debug
			fwrite(&pazienti[i],sizeof(Paziente),1,fp);
			i++;
		}
   }
	while(!feof(fp));
	fclose(fp);
	return(1);
 }
EDIT: Una piccola nota che non so se possa erssere utile o no: La dimensione della struct Paziente è di 9700 byte.

22 Risposte

  • Re: [C] Errore fseek()

    Com'è definito la struttura Paziente. Ha dei campi dinamici o sono tutti statici?
  • Re: [C] Errore fseek()

    Grazie della risposta rapida
    No, sono tutti statici, non abbiamo utilizzato variabili dinamiche all'interno del programma
  • Re: [C] Errore fseek()

    I tipi utilizzati sono i seguenti:
    //Struct contenente una data espressa in giorno, mese e anno, come interi
    typedef struct
    {
    	int giorno;
        int mese;
        int anno;
    } Data;
    
    //Struct contenente i dati di un singolo farmaco
    typedef struct
    {
        char nome[15];
        char principio_attivo[15];
        char interazioni[50];					/* questo campo contiene il nome di farmaci o di componenti che possono interagire con il farmaco stesso*/
        char indicazioni[50];
        char formefarmaceutiche[50];
    } Farmaco;
    
    //Struct contenente la singola prescrizione
    typedef struct
    {
    	Data data;								//Data nella quale il farmaco è stato prescritto
    	Farmaco farmaco;						//Farmaco prescritto, preso dall'archivio dei farmaci
    } Prescrizione;
    
    //Struct contenente i dati di un generico paziente
    typedef struct
    {
        char nome[15];
        char cognome[15];
        char telefono[11];
        Prescrizione cartella_clinica[50];		/*contiene tutti i farmaci prescritti al paziente*/
        char terapia[50];
        int medico_curante;						/*il medico è espresso come numero perche il programma gestirà i medici tramite un numero da 1 a 3*/
    } Paziente;
  • Re: [C] Errore fseek()

    Fai questa prova.All'inizio file .cpp aggiungi
    
    #include <assert.h>
    
    poi cambia la funzione salva così.
    
        int salva(Paziente pazienti[],int dimP,int medico)
        {
           FILE *fp=NULL;
           int i=0,pos,dim;
           Paziente p;
           fp= fopen("pazienti","rb+");
           if(fp==NULL)
           {
              printf("Errore nell'apertura dell'archivio pazienti\n");
              return(0);
           }   
           
           dim=sizeof(Paziente); //Usata per il debug
    
           do
           {
              fread(&p,sizeof(Paziente),1,fp);
              dim=sizeof(p); //Usata per il debug (controllavo che dim(p) fosse costante)
              pos=ftell(fp); //Usata per il debug (verifica posizione settata da fseek)
              if(p.medico_curante == medico) //medico è un numero che identifica il medico, e deve corrispondere a p.medico_curante
              {
                 assert(dim == sizeof(pazienti[i]));
                 fseek(fp,(-1)*(sizeof(p)),SEEK_CUR);
                 pos=ftell(fp); //Usata per il debug
                 fwrite(&pazienti[i],sizeof(pazienti[i]),1,fp);
                 i++;
              }
           }
           while(!feof(fp));
           fclose(fp);
           return(1);
        }
    
    Se il programma si pianta con un assert significa che hai salvato male precedentemente (magari con struttura che aveva meno campi) e devi creare un nuovo file da capo.
  • Re: [C] Errore fseek()

    Allora, ho fatto come mi hai detto, ho eseguito il programma generando dei nuovi files di test (ho scritto un programma che chrea 3 archivi con dati random, per avere dei test files sempre disponibili)
    Il programma sembra eseguire il salvataggio correttamente, come faceva anche prima (in certi casi crasha, in altri no, conclude l'esecuzione ma distrugge l'archivio pazienti)
    In realtà, analizzando l'archivio pazienti con un hex editor, si vede che lascia intatti tutti i record precedenti al primo record relativo al medico con il quale ho eseguito il login, poi dove dovrebbe sovrascrivere il vecchio record, aggiorna la prima parte dei dati, ma non completa la scrittura del record. Invece riempie il file di "0xCC"...
  • Re: [C] Errore fseek()

    in certi casi crasha
    qui ti voglio. Quando crasha lo fa per colpa del assert oppure perche i è andato oltre l'array. Bisogna vedere cosa contiene paziente in quel momento.
  • Re: [C] Errore fseek()

    In caso di crash in debug mode basta vedere il call stack e ti posiziona all'ultima riga che ha generato il crash. Così almeno puoi vedere o stato delle variabili prima la scrittura.
  • Re: [C] Errore fseek()

    Se puoi posta un programma anche piccolo (non tutto il listato) che dimostra il problema. Così almeno posso provare a farlo girare e vedere se c'è qualche errore.
  • Re: [C] Errore fseek()

    Uhm, posto tutto il codice del programma:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<assert.h>
    /*--------------------------------------------------*/
    /* definizione strutture							*/
    /*--------------------------------------------------*/
    
    #define TENTATIVI 4; //Numero di tentativi ( meno uno )per inserire la password 
    
    //Struct contenente una data espressa in giorno, mese e anno, come interi
    typedef struct
    {
    	int giorno;
        int mese;
        int anno;
    } Data;
    
    //Struct contenente i dati di un singolo farmaco
    typedef struct
    {
        char nome[15];
        char principio_attivo[15];
        char interazioni[50];					/* questo campo contiene il nome di farmaci o di componenti che possono interagire con il farmaco stesso*/
        char indicazioni[50];
        char formefarmaceutiche[50];
    } Farmaco;
    
    //Struct contenente la singola prescrizione
    typedef struct
    {
    	Data data;								//Data nella quale il farmaco è stato prescritto
    	Farmaco farmaco;						//Farmaco prescritto, preso dall'archivio dei farmaci
    } Prescrizione;
    
    //Struct contenente i dati di un generico paziente
    typedef struct
    {
        char nome[15];
        char cognome[15];
        char telefono[11];
        Prescrizione cartella_clinica[50];		/*contiene tutti i farmaci prescritti al paziente*/
        char terapia[50];
        int medico_curante;						/*il medico è espresso come numero perche il programma gestirà i medici tramite un numero da 1 a 3*/
    } Paziente;
    
    //Stringa contenente il nome del Medico curante
    typedef char Medico[35];
    
    //Struct contenente nome utente e password di un medico
    typedef struct
    {
        Medico nome;
        char password[10];
    } aut_medici;
    
    /*--------------------------------------------------*/               
    /* prototipi di funzione							*/
    /*--------------------------------------------------*/
    
    int carica_utenti(Medico archivio_medici[],FILE *fm);
    int salva(Paziente pazienti[],int dimP,int medico);
    int autenticazione(Medico archivio_medici[]);
    int inizializzazione_strutture(int medico,Farmaco farmaci[],Paziente pazienti[],FILE *ff,FILE *fp,int *dimF,int *dimP);
    int visualizza_farmaco(char far[], Farmaco farmaci[],int dimF);
    void verifica_interazioni(char farmaco[],char farmaco1[],Farmaco farmaci[],int dimF);
    int inserisciPrescrizione(char f1[],char Npaz[],char Cpaz[],Paziente pazienti[],int dimP, Farmaco farmaci[], int dimF);
    void cerca_data(char Npaz[],char Cpaz[],char f[],Paziente pazienti[],Data *d,int dimP);
    
    /*--------------------------------------------------*/
    /*programma principale								*/
    /*--------------------------------------------------*/
    
    int main()
    {
    	int		scelta;							//Contiene il codice legato alla scelta sul menu del programma
    	int		esito;							//Variabile usata per controllare la buona riuscita delle funzioni
    	int		i = TENTATIVI;					//Numero di tentativi residui per inserire la password 
    	int		ris;							//Come esito...
    	int		medico;							//Codice del medico che ha effettuato l'accesso al sistema
    	int		dimFarmaci;						//
    	int		dimPazienti;					//
    	char	farmaco[15];					//
    	char	farmaco1[15];					//
    	char	Npaz[15];						//Nome del paziente a cui prescrivere un farmaco
    	char	Cpaz[15];						//Cognome del paziente a cui prescrivere un farmaco
    	char	f[20];							//
    	FILE	*ff = NULL;						//File pointer all'archivio dei farmaci (file binario "farmaci" nella cartella di esecuzione del programma)
    	FILE	*fm = NULL;						//File pointer all'archivio credenziali dei medici (file binario "medici" nella cartella di esecuzione del programma)
    	FILE	*fp = NULL;						//File pointer all'archivio dei pazienti (file binario "pazienti" nella cartella di esecuzione del programma)
    	Paziente pazienti[50];					//Array contenente TUTTI i pazienti (max 50) = Archivio Pazienti
    	Farmaco farmaci[100];					//Array contenente TUTTI i farmaci (max 100) = Archivio Farmaci
    	char f1[15];								//Nome del farmaco prescritto al paziente nella funzione "inserisci_prescrizione"
    	Medico	archivio_medici[3];				//Array contenente TUTTI i medici (in questo caso sono proprio 3)
    	Data	d;								//
    
    
    
    
    	/*carico credenziali dei medici*/
    	fm = fopen("medici","rb");
    	if(fm == NULL) //Errore nell'apertura delle credenziali
    	{
    		printf("inizializzazione fallita : lista medici vuota\n\n");
    		system("pause");
    		return(1);
    	}
    
    	else
    	{
           
    		esito = carica_utenti(archivio_medici,fm);
    		if(esito == 0) //Non ho potuto caricare i medici in memoria. Esco.
    		{
    			printf("caricamento utenti non riuscito, il programma terminera'\n");
    			system("pause"); 
    			return(1);
    		}
        }
    	fclose(fm); //(fm non serve più aperto)
    	printf("inizializzazione utenti completata!\n");
    
    	/*Autenticazione: mi restituisce 1,2,3 per indicare un medico, -1 se i dati inseriti sono sbagliati*/
    	do
    	{
    		medico = autenticazione(archivio_medici);
        
    		if(medico==-1)
    		{
    			i--;
    			printf("dati inseriti non corretti, %d tentativi rimanenti",i);
    		}
        }
    	while((i!=0)&&(medico<0));
     if(i==0)
     {
      printf("numero tentativi esauriti: il programma terminerà\n");
    		system("pause"); 
    		return(1);
     }
    	/*Inizializzazione_strutture: restituisce 0 se il caricamento da file non avviene correttamente, ha come parametro 
    	la variabile medico che gli permettera' di caricare solo i dati interessati dal medico indicato*/
    
    	//Apro gli archivi dei pazienti e dei file
    	ff = fopen("farmaci","rb");
    	fp = fopen("pazienti","rb");
    	if(ff !=NULL)
    	{
    		if(fp !=NULL)
    		{
    			esito = inizializzazione_strutture(medico,farmaci,pazienti,ff,fp,&dimFarmaci,&dimPazienti);            
    
    			if(esito == 0)
    			{
    				printf("inizializzazione non riusciuta, il programma terminera'\n");
    				system("pause");
    				return(1);
    			}
    			system("cls");
    			printf("\ninizializzazione completata!\n");
    			
    		}
    		else  
    			printf("inizializzazione fallita : lista pazienti vuota\n\n");
    	}
    	else 
    		printf("inizializzazione fallita : lista farmaci vuota\n\n");
    
    	fclose(ff);
    	fclose(fp);
    
    	fp = NULL;
    
    	//ora 'farmaci' contiene tutti i possibili farmaci, mentre 'pazienti' 
    	//contiene tutti i pazienti associati al medico che ha eseguito il programma
    
    
    	/*menu' ciclico*/ //Ora inizia il main cycle del programma, l'inizializzazione è terminata
    	do
    	{
    		printf("digita 1 per vedere la scheda di un farmaco\n");
    		printf("digita 2 per verificare interazioni fra farmaci\n");
    		printf("digita 3 per prescrivere un farmaco\n");
    		printf("digita 4 per visualizzare la data di prescrizione del farmaco \n");
    		printf("digita 0 per uscire\n");
        
    		scanf("%d",&scelta);
        
    		switch (scelta)
    		{
    			case 1: //Visualizzazione della scheda di un farmaco
    				system("cls");
    				printf("                SCHEDE FARMACI\n\n");
                 
    				printf("inserisci il nome del farmaco interessato\n");
    				scanf("%s",farmaco);
                 
    				ris = visualizza_farmaco(farmaco,farmaci,dimFarmaci);
    				if(ris == 0)
    				{
    					printf(" farmaco non trovato\n");
    				}
    				break;
                 
    			case 2: //Verifico se due farmaci (inseriti da me) hanno interazioni
    				system("cls");
    				printf("                INTERAZIONI FARMACI\n\n");
                 
    				printf("\ninserisci il nome del primo farmaco: ");
    				scanf("%s",farmaco);
                 
    				printf("\ninserisci il nome del secondo farmaco: ");
    				scanf("%s",farmaco1);
                 
    				verifica_interazioni(farmaco,farmaco1,farmaci,dimFarmaci);
    				break;
                 
    			case 3: //Prescrivo un farmaco ad un paziente
    				system("cls");
    				printf("                PRESCRIZIONE FARMACI\n\n");
                 
    				//1) A chi prescrivere?
    				printf("\n inserire nome paziente: ");
    				scanf("%s",Npaz);
    				printf("\n inserire cognome paziente: ");
    				scanf("%s",Cpaz);
    				
    				//2) Cosa prescrivere?
    				printf("\n inserire nome farmaco: ");
    				scanf("%s",f1);
                 
    				//3) Prescrivo...
    				ris = inserisciPrescrizione(f1, Npaz, Cpaz, pazienti, dimPazienti, farmaci, dimFarmaci);
    				if(ris == 0)
    				{
    					printf("paziente non presente nella lista pazienti, inserimento non effettuato\n");
    				}
    				else 
    					printf("inserimento effettuato correttamente\n");
    				break;
                 
    			case 4: //Verifico la data di prescrizione di un farmaco
       				d.giorno = 0;
    				//1) Chi?
    				printf("\n inserire nome paziente: ");
    				scanf("%s",Npaz);
    				printf("\n inserire cognome paziente: ");
    				scanf("%s",Cpaz);
                 
    				//2) Cosa?
    				printf("\n inserire nome farmaco: ");
    				scanf("%s",f);
               
    				//3) Quando gliel'ho prescritto? (sempre che gliel'abbia prescritto..)
    				cerca_data(Npaz,Cpaz,f,pazienti,&d,dimPazienti);
                 
    				if(d.giorno!=0)
    				{
                        printf("\nil farmaco e' stato prescitto il %d / %d / %d\n\n",d.giorno,d.mese,d.anno);
    				}
    				break;
    
    			case 0: //Salva ed esci
    				ris = salva(pazienti,dimPazienti,medico);
    				if(ris ==0)
    				{
    					printf("errore nell archiviazione dei dati\n");
    				}
    				else
    				{	
    					system("cls");
    					printf("archiviazione completata correttamente\n");
                    }
    		}
        }
    	while(scelta != 0);
    
    	system("pause");
    	return 0;
    }
    
    /*--------------------------------------------------*/
    /* implementazione funzioni							*/
    /*--------------------------------------------------*/
    
    /*
    Funzione: carica_utenti
    
    Descrizione: La funzione accede all'archivio dei medici (rappresentato da un file binario) 
    	e carica l'intero archivio in memoria (nella variabile archivio_medici).
    
    Dati restituiti: il numero di medici caricati in memoria.
    
    Note: Si suppone che il file handle passato come parametro punti ad un file correttamente
    	aperto.
    */
    int carica_utenti(Medico archivio_medici[], FILE *fm)
    {
    	Medico m;								//Variabile temporanea usata nella lettura del record dal file
    	int i = 0;								//Contatore del numero di medici
    
    	fread(&m,sizeof(Medico),1,fm);
    	while(!feof(fm))
    	{
    		strcpy(archivio_medici[i],m);
    		fread(&m,sizeof(Medico),1,fm);
    		i++;
    	}
    	return(i);
    }
    
    /*
    Funzione: autenticazione
    
    Descrizione: La funzione esegue il login al sistema, richiedendo nome utente e password
    	e controllando se essi sono presenti nell'archivio delle credenziali.
    
    Dati restituiti: la posizione del record all'interno del file di credenziali, oppure -1
    	se il record non è stato trovato.
    
    */
    int autenticazione(Medico archivio_medici[])
    {
    	aut_medici s, b;						//Variabili contenenti i dati di accesso di un medico (s è letto dall'archivio, b è inserito dall'utente)
    	FILE *fam;								//File Handle per il file contenente i dati di autenticazione
    	int cont = 0, i = 1;					//Contatori (cont = il record è stato trovato, i = codice associato al medico nell'archivio delle credenziali)
    
    	fam = fopen("medici","rb");
    	if(fam == NULL)
    	{
    		//Non ho trovato il file da aprire
    		printf(" errore nel caricamento dei dati dei medici\n");
    	}
    
    	else
    	{
    		//Il file è stato aperto correttamente, richiedo nome utente e password
    		system("cls");
    		printf("\ninserire il nome: ");
    		scanf("%s",b.nome);
    		printf("\ninserire la password: ");
    		scanf("%s",b.password);
     
    
    		fread(&s,sizeof(aut_medici),1,fam);
    		while( ( !feof(fam) ) && ( cont == 0 ) )
    		{
    			if( ( strcmp(s.nome,b.nome)==0 ) && ( strcmp(s.password,b.password) == 0 )) 
    			{
    				cont++;
    				return i;
    			}
    			fread(&s,sizeof(aut_medici),1,fam);
    			i++;
    		}
      return(-1); 
     }       
    }
    /*
    Funzione: inizializzazione_strutture
    
    Descrizione: Carica in memoria i record dei farmaci e dei pazienti dall'archivio del sistema, MA SOLO I PAZIENTI RELATIVI AL 
    	MEDICO SPECIFICATO COME PARAMETRO
    
    Dati restituiti:	- Numero di farmaci caricati in memoria (inserito in dimF)
    					- Numero di pazienti caricati in memoria (inserito in dimP)
    					- Codice di avvenuta esecuzione: 0 se ci sono stati errori (il file dei pazienti era vuoto), 1 altrimenti
    
    Si suppongono i file in ingresso correttamente aperti.
    */
    int inizializzazione_strutture(int medico, Farmaco farmaci[], Paziente pazienti[], FILE *ff, FILE *fp, int *dimF, int *dimP)
    {               
    	Farmaco f;								//Variabile di appoggio per la lettura dall'archivio dei farmaci
    	Paziente p;								//Variabile di appoggio per la lettura dall'archivio dei pazienti
    	int i=0;								//Contatore
    
    	/* farmaci: */ //Carico tutti i farmaci in memoria
    	fread(&f,sizeof(Farmaco),1,ff);
    	while(!feof(ff))
    	{
    		farmaci[i] = f;
    		fread(&f,sizeof(Farmaco),1,ff);
    		i++;
    	}
    	*dimF = i;
    		if(i==0)
    	{
    		return(0);
    	}   
    	/* pazienti: */ 
    	i=0;
    	fread(&p,sizeof(Paziente),1,fp);
    	while(!feof(fp))
    	{
    		if((p.medico_curante )== medico)
    		{
    			pazienti[i] = p;
    			i++;
    		}
    		fread(&p,sizeof(Paziente),1,fp);
    	}
    	*dimP = i;
    	if(i==0)
    	{
    		return(0);
    	}            
    	return(1);
    } 
    /*
    Funzione: salva
    
    Descrizione: Salva le modifiche fatte all'archivio pazienti e chiude il programma
    
    Dati restituiti: 0 se fallisce, 1 altrimenti
    
    Note: ERRORE: Scazza nel salvare il numero del dottore.
    
    */
    
    /*int salva(Paziente pazienti[],int dimP,int medico) 
    {
    	FILE *fp=NULL;
    	int i=0,pos,dim;
    	Paziente p;
    	fp= fopen("pazienti","rb+");
    	if(fp==NULL)
    	{
    		printf("Errore nell'apertura dell'archivio pazienti\n");
    		return(0);
    	}	
    	
    	dim=sizeof(Paziente);
    
    	do
    	{
    		fread(&p,sizeof(Paziente),1,fp);
    		dim=sizeof(p);
    		pos=ftell(fp);
    		if(p.medico_curante == medico)
    		{
     			fseek(fp,(-1)*(sizeof(p)),SEEK_CUR);
    			pos=ftell(fp);
    			fwrite(&pazienti[i],sizeof(Paziente),1,fp);
    			i++;
    		}
        }
    	while(!feof(fp));
    	fclose(fp);
    	return(1);
     }
    */
    
    int salva(Paziente pazienti[],int dimP,int medico)
    {
        FILE *fp=NULL;
        int i=0,pos,dim;
        Paziente p;
        fp= fopen("pazienti","rb+");
        if(fp==NULL)
        {
            printf("Errore nell'apertura dell'archivio pazienti\n");
            return(0);
        }   
           
        dim=sizeof(Paziente); //Usata per il debug
    
        do
        {
            fread(&p,sizeof(Paziente),1,fp);
            dim=sizeof(p); //Usata per il debug (controllavo che dim(p) fosse costante)
            pos=ftell(fp); //Usata per il debug (verifica posizione settata da fseek)
            if(p.medico_curante == medico) //medico è un numero che identifica il medico, e deve corrispondere a p.medico_curante
            {
                assert(dim == sizeof(pazienti[i]));
                fseek(fp,(-1)*(sizeof(p)),SEEK_CUR);
                pos=ftell(fp); //Usata per il debug
                fwrite(&pazienti[i],sizeof(pazienti[i]),1,fp);
                i++;
            }
        }
        while(!feof(fp));
        fclose(fp);
        return(1);
    }
    
    Il programma per generare dei file di test invece è il seguente:
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define NUM_FARMACI_ARCHIVIO 50
    #define NUM_MEDICI_ARCHIVIO 3 //Non basta cambiare questa per generare + medici, perchè non sono generati casualmente
    #define NUM_PAZIENTI_ARCHIVIO 25
    #define NUM_FARMACI_PER_PAZIENTE 10
    
    //Struct contenente una data espressa in giorno, mese e anno, come interi
    typedef struct
    {
    	int giorno;
        int mese;
        int anno;
    } Data;
    
    //Struct contenente i dati di un singolo farmaco
    typedef struct
    {
        char nome[15];
        char principio_attivo[15];
        char interazioni[50];					/* questo campo contiene il nome di farmaci o di componenti che possono interagire con il farmaco stesso*/
        char indicazioni[50];
        char formefarmaceutiche[50];
    } Farmaco;
    
    //Struct contenente la singola prescrizione
    typedef struct
    {
    	Data data;								//Data nella quale il farmaco è stato prescritto
    	Farmaco farmaco;						//Farmaco prescritto, preso dall'archivio dei farmaci
    } Prescrizione;
    
    //Struct contenente i dati di un generico paziente
    typedef struct
    {
        char nome[15];
        char cognome[15];
        char telefono[11];
        Prescrizione cartella_clinica[50];		/*contiene tutti i farmaci prescritti al paziente*/
        char terapia[50];
        int medico_curante;						/*il medico è espresso come numero perche il programma gestirà i medici tramite un numero da 1 a 3*/
    } Paziente;
    
    //Stringa contenente il nome del Medico curante
    typedef char Medico[35];
    
    //Struct contenente nome utente e password di un medico
    typedef struct
    {
        Medico nome;
        char password[10];
    } aut_medici;
    
    typedef char Stringa10[10];
    typedef char Stringa15[15];
    typedef char Stringa35[35];
    typedef char Stringa50[50];
    
    //Necessario per Farmaci:
    Stringa15 PrincipiAttivi[10] = { "Principio01", "Principio02", "Principio03", "Principio04", "Principio05", "Principio06", "Principio07", "Principio08", "Principio09", "Principio10" };
    Stringa50 ArrIndicazioni[5] = { "Indicaz1", "Indicaz2", "Indicaz3", "Indicaz4", "Indicaz5" };
    Stringa50 ArrForme[5] = { "FF1", "FF2", "FF3", "FF4", "FF5" };
    
    //Necessario per Medici:
    Stringa35 NomiMedici[3] = { "M1", "M2", "M3" };
    Stringa10 Password[3] = { "a", "b", "c" };
    
    //Necessario per Pazienti
    Stringa15 ArrNomi[20] = { "Paolo", "Luca", "Massimiliano", "Andrea", "Sara", "Giovanni", "Gino", "Ugo", "Giulio", "Francesco", "Ferdinando", "Simone", "Giulia", "Laura", "Martina", "Francesca", "Elvisa", "Ermenegilda", "Carolina", "Fabiana" };
    Stringa15 ArrCognomi[20] = { "Garolla", "Marchesini", "Marra", "Mola", "Lugarini", "Semenzato", "Crepaldi", "Pasquali", "Milani", "Rossi", "Verdi", "Bianchi", "Morandin", "Soncin", "Siviero", "Cavallaro", "Labarbuta", "Canova", "Malfatti", "Zerbin" };
    Stringa50 ArrTerapie[5] = { "T1", "T2", "T3", "T4", "T5" };
    
    Farmaco RandFarmaco()
    {
    	Farmaco temp;
    	Stringa50 S50temp;
    	Stringa15 S15temp;
    	static int i = 0;
    	strcpy( temp.formefarmaceutiche, ArrForme[rand()%5] );
    	strcpy( temp.indicazioni, ArrIndicazioni[rand()%5] );
    	sprintf( S50temp, "Interazione%d", rand()%20 );
    	strcpy( temp.interazioni, S50temp );
    	sprintf( S15temp, "Farmaco%d", i++ );
    	strcpy( temp.nome, S15temp );
    	strcpy( temp.principio_attivo, PrincipiAttivi[rand()%10] );
    	
    	return temp;
    }
    
    Paziente RandPaziente(Farmaco ArchivioFarmaci[])
    {
    	Paziente temp;
    	int i = 0;
    	static int telefono = 123;
    	char Numero[11];
    	for( i=0; i<50; i++ )
    		strcpy( temp.cartella_clinica[i].farmaco.nome, "0" );
    	for( i=0; i<NUM_FARMACI_PER_PAZIENTE; i++ )
    	{
    		temp.cartella_clinica[i].farmaco = ArchivioFarmaci[rand()%NUM_FARMACI_ARCHIVIO]; //Sono possibili duplicati, ma non dovrebbe essere un problema..
    		temp.cartella_clinica[i].data.anno = (rand()%12)+2000;
    		temp.cartella_clinica[i].data.mese = (rand()%12)+1;
    		temp.cartella_clinica[i].data.giorno = (rand()%30)+1;
    	}
    	strcpy( temp.cognome, ArrCognomi[rand()%20] );
    		temp.medico_curante= (rand()%NUM_MEDICI_ARCHIVIO) +1;
    	strcpy( temp.nome, ArrNomi[rand()%20] );
    	sprintf( Numero, "%d", telefono++ );
    	strcpy( temp.telefono, Numero );
    	strcpy( temp.terapia, ArrTerapie[rand()%5] );
    	
    	return temp;
    }
    
    void InitArchivi( Farmaco ArchivioFarmaci[], Paziente ArchivioPazienti[], aut_medici ArchivioMedici[] )
    {
    	int i;
    	for( i=0; i<NUM_FARMACI_ARCHIVIO; i++ )
    		ArchivioFarmaci[i] = RandFarmaco();
    	for( i=0; i<NUM_PAZIENTI_ARCHIVIO; i++ )
    		ArchivioPazienti[i] = RandPaziente( ArchivioFarmaci );
    	for( i=0; i<NUM_MEDICI_ARCHIVIO; i++ )
    	{
    		strcpy( ArchivioMedici[i].nome, NomiMedici[i] );
    		strcpy( ArchivioMedici[i].password, Password[i] );
    	}
    }
    
    void ToTxt( Farmaco ArchivioFarmaci[], Paziente ArchivioPazienti[], aut_medici ArchivioMedici[] )
    {
    	FILE *FarmaciDB = NULL, *MediciDB = NULL, *PazientiDB = NULL;
    	int i, j;
    
    	//Scrittura del file 'farmaci.txt'
    	FarmaciDB = fopen( "farmaci.txt", "w" );
    	fprintf( FarmaciDB, "Nome,Principio_Attivo,Interazioni,Indicazioni,Forme_Farmaceutiche\n" );
    	for( i=0; i<NUM_FARMACI_ARCHIVIO; i++ )
    		fprintf(FarmaciDB, "%s,%s,%s,%s,%s\n", ArchivioFarmaci[i].nome, ArchivioFarmaci[i].principio_attivo, ArchivioFarmaci[i].interazioni, ArchivioFarmaci[i].indicazioni, ArchivioFarmaci[i].formefarmaceutiche );
    	fclose( FarmaciDB );
    
    	//Scrittura del file 'medici.txt'
    	MediciDB = fopen( "medici.txt", "w" );
    	fprintf( MediciDB, "Nome,Password\n" );
    	for( i=0; i<NUM_MEDICI_ARCHIVIO; i++ )
    		fprintf( FarmaciDB, "%s,%s\n", ArchivioMedici[i].nome, ArchivioMedici[i].password );
    	fclose( MediciDB );
    
    	//Scrittura del file 'pazienti.txt'
    	PazientiDB = fopen( "pazienti.txt", "w" );
    	fprintf( PazientiDB, "Nome,Cognome,Telefono,Terapia,Medico_Curante,Farmaci_Assunti\n" );
    	for( i=0; i<NUM_PAZIENTI_ARCHIVIO; i++ )
    	{
    		fprintf( PazientiDB, "%s,%s,%s,%s,%d", ArchivioPazienti[i].nome, ArchivioPazienti[i].cognome, ArchivioPazienti[i].telefono, ArchivioPazienti[i].terapia, ArchivioPazienti[i].medico_curante );
    		for( j=0; j<NUM_FARMACI_PER_PAZIENTE; j++ )
    			fprintf( PazientiDB, ",%s - %d/%d/%d", ArchivioPazienti[i].cartella_clinica[j].farmaco.nome, ArchivioPazienti[i].cartella_clinica[j].data.giorno, ArchivioPazienti[i].cartella_clinica[j].data.mese, ArchivioPazienti[i].cartella_clinica[j].data.anno);
    		fprintf( PazientiDB, "\n" );
    	}
    	fclose( PazientiDB );
    
    }
    
    int main()
    {
    	Farmaco ArchivioFarmaci[NUM_FARMACI_ARCHIVIO];
    	Paziente ArchivioPazienti[NUM_PAZIENTI_ARCHIVIO];
    	aut_medici ArchivioMedici[NUM_MEDICI_ARCHIVIO];
    	FILE *FarmaciDB = NULL, *MediciDB = NULL, *PazientiDB = NULL;
    
    	srand(time(NULL));
    	InitArchivi( ArchivioFarmaci, ArchivioPazienti, ArchivioMedici );
    
    	//Scrittura file 'farmaci'
    	if( (FarmaciDB = fopen( "farmaci", "wb" )) == NULL )
    	{
    		printf( "Failed to create 'farmaci', quitting.\n");
    		system("PAUSE");
    	}
    
    	fwrite( ArchivioFarmaci, sizeof(Farmaco), NUM_FARMACI_ARCHIVIO, FarmaciDB );
    	fclose( FarmaciDB );
    
    	//Scrittura file 'pazienti'
    	if( (PazientiDB = fopen( "pazienti", "wb" )) == NULL )
    	{
    		printf( "Failed to create 'pazienti', quitting.\n");
    		system("PAUSE");
    	}
    
    	fwrite( ArchivioPazienti, sizeof(Paziente), NUM_PAZIENTI_ARCHIVIO, PazientiDB );
    	fclose( PazientiDB );
    
    	//scrittura file 'medici'
    	if( (MediciDB = fopen( "medici", "wb" )) == NULL )
    	{
    		printf( "Failed to create 'medici', quitting.\n");
    		system("PAUSE");
    	}
    
    	fwrite( ArchivioMedici, sizeof(aut_medici), NUM_MEDICI_ARCHIVIO, MediciDB );
    	fclose( MediciDB );
    
    	//Scrittura corrispettivi files di testo
    	ToTxt( ArchivioFarmaci, ArchivioPazienti, ArchivioMedici );
    
    	system("PAUSE"); 
    	return 0;
    }
    
    Ho tolto dal primo programma le implementazioni delle funzioni che non danno problemi, per snellire un po' la cosa, ma resta comunque molto codice X.x Però ora come ora non saprei come semplificare il programma mantenendolo funzionante..
    Col secondo programma puoi generare 6 file, 3 che sono gli archivi binari e 3 .txt con gli stessi dati, per visualizzare velocemente il contenuto degli altri file (vanno aperti con excel, i valori sono tutti separati da virgola..)
  • Re: [C] Errore fseek()

    Per quanto riguarda il crash, non mi è mai capitato in debug mode..
    Mi è capitato una volta o due facendo girare il programma compilato, ma se lo avvio in debug mode termina l'esecuzione senza dare segnalazioni di errori...
  • Re: [C] Errore fseek()

    Come sospettavo. Il programma scrive OK tutti i campi faccendo sta modifica.
    
    int salva(Paziente pazienti[],int dimP,int medico)
        {
            FILE *fp=NULL;
            int i=0,pos,dim;
            Paziente p;
            fp= fopen("pazienti","rb+");
            if(fp==NULL)
            {
                printf("Errore nell'apertura dell'archivio pazienti\n");
                return(0);
            }   
               
            dim=sizeof(Paziente); //Usata per il debug
    
            do
            {
                fread(&p,sizeof(Paziente),1,fp);
                dim=sizeof(p); //Usata per il debug (controllavo che dim(p) fosse costante)
                pos=ftell(fp); //Usata per il debug (verifica posizione settata da fseek)
    			if(p.medico_curante == medico) //medico è un numero che identifica il medico, e deve corrispondere a p.medico_curante
                {
                    assert(dim == sizeof(pazienti[i]));
                    fseek(fp,pos - dim,SEEK_SET);
                    fwrite(&(pazienti[i]),sizeof(pazienti[i]),1,fp);
                    i++;
                }
            }
            while(!feof(fp));
            fclose(fp);
            return(1);
        }
    
    il problema qual'è: Non sai quando fermarti, nel senso che non sai la grandezza dell array Pazienti e succede che da un certo i - in poi, pazienti non è una struttura valida e tiene solo CC (in debug mode significa non inizializzato). Quindi nella funzione salva li devi passare anche quanti pazienti sto dottore ha se no vai a caso e corrompi i dati.
  • Re: [C] Errore fseek()

    Il programma per generare i dati mi ha creato 26 pazienti. Adesso se modifico la funzione salva così:
    
        int salva(Paziente pazienti[],int dimP,int medico)
        {
            FILE *fp=NULL;
            int i=0,pos,dim;
            Paziente p;
            fp= fopen("pazienti","r+b");
            if(fp==NULL)
            {
                printf("Errore nell'apertura dell'archivio pazienti\n");
                return(0);
            }   
               
            dim=sizeof(Paziente); //Usata per il debug
    
            do
            {
                fread(&p,sizeof(Paziente),1,fp);
                dim=sizeof(p); //Usata per il debug (controllavo che dim(p) fosse costante)
                pos=ftell(fp); //Usata per il debug (verifica posizione settata da fseek)
    			if(p.medico_curante == medico) //medico è un numero che identifica il medico, e deve corrispondere a p.medico_curante
                {
                    assert(dim == sizeof(pazienti[i]));
                    fseek(fp,pos - dim,SEEK_SET);
                    fwrite(&(pazienti[i]),sizeof(pazienti[i]),1,fp);
                    i++;
                }
            }
            while(i < 26);
            fclose(fp);
            return(1);
        }
    
    tutto mi funziona anche al prossimo avvio del programma. CVD.
  • Re: [C] Errore fseek()

    Adesso è uscito un altro problema. Se io modifico la funzione salva così
    
        int salva(Paziente pazienti[],int dimP,int medico)
        {
            FILE *fp=NULL;
            int i=0;
          
            fp= fopen("pazienti","w+");
            if(fp==NULL)
            {
                printf("Errore nell'apertura dell'archivio pazienti\n");
                return(0);
            }   
               
             for(i = 0; i < 26; i++)
    		{
    			fwrite(&pazienti[i],sizeof(Paziente),1,fp);
    		}
            fclose(fp);
            return(1);
        }
    
    
    Quindi senza modificare niente, dovrei vedere il file di uscita uguale a quello di entrata, invece non è così. Quindi la lettura file viene fatta male e il problema non è nel salvataggio.
  • Re: [C] Errore fseek()

    Uhm, ho provato a ricompilare e testare il programma con la funzione che tu mi hai postato, ma continua a dare lo stesso problema..
    Comunque, sebbene sia un controllo giusto e che inserirò nella versione finale del programma, il controllo sulla i non dovrebbe essere necessario, in quanto tutti gli elementi in pazienti[] sono stati precedentemente estratti dal file archivio, quindi, se ho ad esempio 10 record relativi al medico 3 nell'archivio, avrò esattamente 10 elementi in pazienti[], quindi, teoricamente, dovrebbe uscire dal do-while raggiungendo l'EOF.
    Il programma non prevede l'aggiunta di nuovi pazienti, quindi il caso in cui pazienti[] contiene un numero di elementi diverso dal numero di elementi nel file (relativi al medico corrente) non dovrebbe essere possibile.... (Non so se mi sono spiegato proprio bene.. O.o )
Devi accedere o registrarti per scrivere nel forum
22 risposte