Errore a Runtime fstream

di il
3 risposte

Errore a Runtime fstream

Buongiorno a tutti, essendo il mio primo post colgo l'occasione per presentarmi.
Sono alex e studio ingegneria gestionale, e mi fa piacere aver trovato una comunità come la vostra !

Ho un problema con un esercizio datomi dal prof, non sono qui per richiedere l'esercizio già fatto sia chiaro, ma ho un bel problema con un errore a run time.
Posto il codice:

http://pastebin.com/Fn2YfU7

Allora praticamente mediante la funzione carica() apro il file Abbonamenti.dat e inserisco tutte le varie informazioni degli abbonati, fin qui tutto bene.(con modalita' accesso diretto, un po inutile ma fatta giusto per scopi didattici)

Nel momento in cui voglio visualizzare ciò che ho salvato con la funzione visualizza(), sul prompt mi escono i vari record, l'ultimo dublicato e poi un bel errore a runtime, precisamente
"Eccezione non gestita a 0x5d40ad4a (msvcp100d.dll) in Rsame_25_07_2013_Esercizio1.exe: 0xC0000005: Violazione di accesso nella lettura del percorso 0x00b44a4c."

Quindi credo che l'errore sia nella funzione f.read(), soltanto che non riesco proprio a capire dove dato che mi sembra abbia fatto tutto correttamente.

Sperando in un vostro aiuto vi saluto tutti

3 Risposte

  • Re: Errore a Runtime fstream

    sempre_alex ha scritto:


    Allora praticamente mediante la funzione carica() apro il file Abbonamenti.dat e inserisco tutte le varie informazioni degli abbonati, fin qui tutto bene.
    Tutto male invece. Non puoi scrivere un oggetto complesso come una std::string in maniera binaria come faresti con una char q[30] (per esempio), ne tantomeno leggerla.
    Dato che Abbonamento contiene una struttura dati_a, che a sua volta contiene std::string, in scrittura puoi avere una corruzione dei dati (dipende dall'implementazione interna di std::string).
    Quando vai a leggere la stessa struttura abbonamento, però, le std::string non sono inizializzate e questo comporta l'errore di runtime.
    La soluzione più semplice è definire data_as come:
    
    struct dati_a{
            char cognome[64];
            char nome[64];
            char citta[64];
            char indirizzo[64];
            float prezzo;
    };
    
    e manipolare i dati di conseguenza. Purtroppo questo è uno dei pochi casi in cui non è possibile usare le std::string per la scrittura binaria su file.
    In alternativa puoi scrivere in formato testo (separato magari da un tab) in questo modo:
    
    void carica(){
           
            struct dati_a vals;
            Abbonamento abb;
            fstream f(file_abb,ios::in|ios::out);
            if(!f){
                cout<<"Errore nel file.\n";
                return;
             }
            cout<<"INSERIMENTO ABBONATI\n"<<endl;
            for(int i=0;i<=NUM_ABB-1;i++){
                    cout<<"ID: "<<i+1<<"\n";
                    vals.nome=request<string>("\tNome");
                    vals.cognome=request<string>("\tCognome");
                    vals.citta=request<string>("\tCitta");
                    vals.indirizzo=request<string>("\tIndirizzo");
                    vals.prezzo=request<float>("\tPrezzo");
     
                    abb.set(vals,i+1);
     
                    f << vals.nome << '\t' <<  vals.cognome << '\t';
                    f << vals.citta<< '\t' <<  vals.indirizzo<< '\t';
                    f << vals.prezzo<< endl;
            }
            f.close(); // non strettamente necessaria   
    }
    
    Ovviamente la funzione visualizza va totalmente cambiata.
    Devi leggere una riga alla volta, parserizzarla per trovare i vari token, inserire tali token in una struttura data_a, inserire tale struttura nella classe Abbonamento (c'è un costruttore apposta mi pare) e poi puoi stampare senza avere problemi.
  • Re: Errore a Runtime fstream

    Shodan ti ringrazio per la risposta, sinceramente questa cosa sul fatto che la string viene allocata dinamicamente e quindi crea problemi in fase di lettura(scrittura) mi mancava...dato che devo per forza utilizzare un file binario credo dovro utilizzare la prima soluzione...soltanto che si complica molto di più in quanto non potrò più utilizzare la funzione request e dovrò fare tutto con strcpy..

    Magari posso creare una funzione template che mi aiuti un po nel semplificare...
    Ti ringrazio ancora
  • Re: Errore a Runtime fstream

    Una soluzione che adotterei io per salvare capra e cavoli è usare una struttura binaria di appoggio.
    
    struct dati_a{
            string cognome;
            string nome;
            string citta;
            string indirizzo;
            float prezzo;
    };
    
    struct dati_bin{
            char cognome[64];
            char nome[64];
            char citta[64];
            char indirizzo[64];
            float prezzo;
    };
    
    ...
    
    void carica(){
           
            struct dati_a vals;
            struct dati_bin temp;
            Abbonamento abb;
            fstream f(file_abb,ios::in|ios::out|ios::binary);
            if(!f){
                cout<<"Errore nel file.\n";
                return;
             }
            cout<<"INSERIMENTO ABBONATI\n"<<endl;
            for(int i=0;i<=NUM_ABB-1;i++){
                    memset(&temp,0,sizeof(dati_bin);
                    
                    cout<<"ID: "<<i+1<<"\n";
                    vals.nome=request<string>("\tNome");
                    vals.cognome=request<string>("\tCognome");
                    vals.citta=request<string>("\tCitta");
                    vals.indirizzo=request<string>("\tIndirizzo");
                    vals.prezzo=request<float>("\tPrezzo");
    
                    abb.set(vals,i+1);
    
                    std::copy(vals.nome.begin(),vals.nome.end(),temp.nome);
                    std::copy(vals.cognome.begin(),vals.cognome.end(),temp.cognome);
                    std::copy(vals.citta.begin(),vals.citta.end(),temp.citta);
                    std::copy(vals.indirizzo.begin(),vals.indirizzo.end(),temp.indirizzo);
                    temp.prezzo = vals.prezzo;
    
                    f.write((char*)& temp,sizeof(dati_bin);
    
            }
            f.close(); // non strettamente necessaria   
    }
    
    In visualizza()
    
    void visualizza(){
            Abbonamento abb;
            data_a dat;
            data_bin temp;
            int index=0; 
            fstream f;
            f.open(file_abb,ios::in | ios::binary);
     
            while(f.read((char*)& temp,sizeof(data_bin)) && f.eof()==false) {
                    memset(&temp,0,sizeof(databin));
                    dat.nome = temp.nome;
                    dat.cognome = temp.cognome;
                    dat.citta = temp.citta;
                    dat.indirizzo= temp.indirizzo;
                    dat.indirizzo= temp.indirizzo;
                    dat.prezzo = temp.prezzo;
                    abb.set(dat,i++); 
                    abb.stampa();
            }
            f.close();
    }
    
    A prima vista pare complicato, in realtà è meno complicato di dover gestire le string del C con le varie strcpy, strlen etc.
Devi accedere o registrarti per scrivere nel forum
3 risposte