Problema con programma che legge file

di il
44 risposte

44 Risposte - Pagina 3

  • Re: Problema con programma che legge file

    Con "salvato" intendi "mantenuto in memoria" o "registrato su disco"?
  • Re: Problema con programma che legge file

    Ma nel tuo caso non devi salvare nulla, devi solo elaborarli per trovare min max e media. Di che panico parli? Devi solo proporre del codice con i suggerimenti avuti altrimenti superiamo Natale chiacchierando del nulla
  • Re: Problema con programma che legge file

    Ho sbagliato tutto e non capisco dove ho sbagliato, comunque il codice è questo:
    #include <iostream>
    #include <string>
    #include <fstream>
    using namespace std;
    
    int main () {
    	string materia;
    	int voto;
    	string data;
    	ifstream libretto("libretto.txt");   //il mio file si chiama libretto e sono poco fantasiosa
    	
    	if (!libretto) {
    	cout<<"Errore! Il file non esiste!\n";
    	libretto.clear();
    	}
    	else {
    while (libretto >> materia >> voto >> data);   //la parte che dà problemi è questa perché se faccio leggere tutto il file funziona bene
    cout<<materia<<" "<<voto<<" "<<data<<endl;  //so che questo cout non ci dovrebbe essere ma lo metto per vedere il programma cosa fa
    	}
    	libretto.close();
    
    }
    Praticamente il programma parte ma mi fa vedere solo una scritta, sempre la stessa, più o meno è così:
    se nel file scrivo
    italiano 8 20/05/2012
    matematica 6 7/02/2013
    inglese 4 6/8/2012
    il programma mi fa vedere:
    matematica 0 6/8/2012
    sto cercando di correggerlo ma credo di non aver capito bene il concetto perché pensando che avesse letto solo la prima riga ho provato a mettere prima del while un altro while così:
    		while (!libretto.eof()) {
    while (libretto >> materia >> voto >> data);
    cout<<materia<<" "<<voto<<" "<<data<<endl;
    e mi fa vedere sempre la stessa scritta all'infinito
  • Re: Problema con programma che legge file

    Il primo codice andava bene, ma da questa linea

    while (libretto >> materia >> voto >> data);

    devi togliere il ; finale e deve essere

    while (libretto >> materia >> voto >> data)
  • Re: Problema con programma che legge file

    oregon ha scritto:


    Il primo codice andava bene, ma da questa linea

    while (libretto >> materia >> voto >> data);

    devi togliere il ; finale e deve essere

    while (libretto >> materia >> voto >> data)
    Okay grazie adesso provo a proseguire allora!
  • Re: Problema con programma che legge file

    Ok, parti dal fatto che avrai due variabili

    int maxvoto=0, minvoto=100;

    e aggiornale, ad ogni lettura, confrontandole con il voto letto.

    Inoltre avrai le variabili

    int somma=0, count=0, double media;

    nella variabile somma accumuli i voti, e nella count li conti. Alla fine del ciclo calcoli la media e presenti i risultati. Quasi finito.
  • Re: Problema con programma che legge file

    Oddio funziona!!
    Non riuscivo a capire dove posizionare i calcoli che doveva fare perché a volte mi dava errori strani, ma all'improvviso ha iniziato a funzionare aiuto
    Che ne dite? L'ho fatto bene o è un pasticcio? ahahahah io sono contenta perché fa quello che gli ho chiesto, comunque avevo capito che la consegna chiedesse che alla fine fosse visualizzato il voto con la materia in cui è stato preso e la data (altrimenti che senso aveva metterle?) perciò dicevo che volevo salvare da qualche parte tutti i dati. Comunque eccolo qui:
    #include <iostream>
    #include <string>
    #include <fstream>
    using namespace std;
    int main () {
       string materia, data;
       int voto;
       float media;
       int i = 0;
       int somma = 0;
       int maxvoto = 0;
       int minvoto = 100;
       ifstream libretto("libretto.txt");
       if (!libretto) {
       cout<<"Errore! Il file non esiste!\n";
       libretto.clear();
       }
       else {
    while (libretto >> materia >> voto >> data)
    {
    	i = i + 1;
    	somma = somma + voto; 
    	if (voto > maxvoto) {
    		maxvoto = voto;
    	}
    	if (voto < minvoto) {
    		minvoto = voto;
    	}
    	}
    	media = somma / i ;
    	cout<<"La media e\': "<<media<<endl;
    	cout<<"Il voto migliore e\': "<<maxvoto<<" mentre il peggiore e\': "<<minvoto<<endl;
    }
    
       libretto.close();
    
    }
  • Re: Problema con programma che legge file

    Ci sei quasi ... una correzione, scrivi

    media = (float)somma / i;

    per calcolare i decimali per la media.

    A questo punto, ti servono alcune variabili

    string maxmateria, maxdata;
    string minmateria, mindata;

    che devi assegnare con i relativi dati letti nelle relative if quando trovi i max e i min.
    Alla fine del ciclo li presenti a video con gli altri dati e l'esercizio è completo.

    Era semplicissimo, senza array, senza allocazione dinamica della memoria, classi, strutture, niente di difficile.
  • Re: Problema con programma che legge file

    oregon ha scritto:


    Ci sei quasi ... una correzione, scrivi

    media = (float)somma / i;

    per calcolare i decimali per la media.

    A questo punto, ti servono alcune variabili

    string maxmateria, maxdata;
    string minmateria, mindata;

    che devi assegnare con i relativi dati letti nelle relative if quando trovi i max e i min.
    Alla fine del ciclo li presenti a video con gli altri dati e l'esercizio è completo.

    Era semplicissimo, senza array, senza allocazione dinamica della memoria, classi, strutture, niente di difficile.
    Ah ecco perché la media usciva sempre intera mi sembrava strano... ho pensato vabbe ho scelto i numeri giusti comunque grazie mille!!
    Pensavo fosse molto più difficile, nella mia testa aveva proprio un'altra "forma" e mi è preso il panico più totale.. sapevo fare la maggior parte di queste cose ma non me ne rendevo conto adesso è proprio come lo volevo
    #include <iostream>
    #include <string>
    #include <fstream>
    using namespace std;
    int main () {
       string materia, data, maxmateria, maxdata, mindata, minmateria;
       int voto;
       float media;
       int i = 0;
       int somma = 0;
       int maxvoto = 0;
       int minvoto = 100;
       ifstream libretto("libretto.txt");
       if (!libretto) {
       cout<<"Errore! Il file non esiste!\n";
       libretto.clear();
       }
       else {
    while (libretto >> materia >> voto >> data)
    {
    	i = i + 1;
    	somma = somma + voto; 
    	if (voto > maxvoto) {
    		maxvoto = voto;
    		maxmateria = materia;
    		maxdata = data;
    	}
    	if (voto < minvoto) {
    		minvoto = voto;
    		minmateria = materia;
    		mindata = data;
    	}
    	}
    	media = (float)somma / i ;
    	cout<<"La media e\': "<<media<<endl;
    	cout<<"Il voto migliore e\': "<<maxvoto<<" in "<<maxmateria<<" preso in data: "<<maxdata<<endl;
    	cout<<"Mentre il peggiore e\': "<<minvoto<<" in "<<minmateria<<" preso in data: "<<mindata<<endl;
    }
       libretto.close();
    
    }
  • Re: Problema con programma che legge file

    Pensa che io invece, in C e non in C++, ho fatto una roba fuori dal mondo anche evitando l'allocazione dinamica, gli array e tutto il resto dell'armamentario! Il programma compilato è meno di 12 KB, però il codice (includendo i commenti) arriva a un pippolone assurdo di 360 righe di codice. Però mi sono divertito un sacco!

    Ancor più mi sono divertito nella versione in quella specie di C++, con la classe e con l'allocazione dinamica della memoria per caricare tutti i dati, arrivando a circa 400 righe di codice su tre file (e senza neppure prendere in considerazione l'individuazione del massimo/minimo e il calcolo della media).

    C'è da dire che ho inserito tutta una serie di passaggi per il controllo degli errori e della validità dei dati...

    Va be'...
  • Re: Problema con programma che legge file

    Beh ... ci sono volute 3 pagine ma abbiamo superato gli attacchi di panico e abbiamo evitato di presentare 400 righe al professore ... una missione quasi impossibile ma alla fine è andata ...
  • Re: Problema con programma che legge file

    AldoBaldo ha scritto:


    Pensa che io invece, in C e non in C++, ho fatto una roba fuori dal mondo anche evitando l'allocazione dinamica, gli array e tutto il resto dell'armamentario! Il programma compilato è meno di 12 KB, però il codice (includendo i commenti) arriva a un pippolone assurdo di 360 righe di codice. Però mi sono divertito un sacco!

    Ancor più mi sono divertito nella versione in quella specie di C++, con la classe e con l'allocazione dinamica della memoria per caricare tutti i dati, arrivando a circa 400 righe di codice su tre file (e senza neppure prendere in considerazione l'individuazione del massimo/minimo e il calcolo della media).

    C'è da dire che ho inserito tutta una serie di passaggi per il controllo degli errori e della validità dei dati...

    Va be'...
    Immagino, io riesco a fare codici lunghissimi per i programmi più semplici... una volta mi sono addirittura messa in testa di fare una matrice, senza avere idea di come farla (non sapevo manco che era una matrice...) e senza nemmeno usare il ciclo for perché mi era antipatico e ho detto tutto
    Però almeno quando non sei sotto stress per gli esami è divertente
  • Re: Problema con programma che legge file

    Guarda, voglio farmi e farvi del male... Questa è la versione in C...
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    #define LMAX_RIGA 1023 // ogni riga del file non deve eccedere questa lunghezza
    #define LMAX_NOME   31 // il nome dell'esame non deve eccedere questa lunghezza
    
    typedef struct {
        char  nome[LMAX_NOME+1];
        int   punti;
        char  giorno;
        char  mese;
        short anno;
    } Esame;
    
    const char *kStrNomeFile = "dati.txt"; // il nome del file da leggere
    const int kQElDaStringa  =  3; // la quantita' dei dati per ogni esame
    const int kMaxPunti      = 30; // il punteggio massimo per ogni esame
    
    /** ==> PROTOTIPI <==========================================================**/
    
    int acquisisci_dati_da_stringa( Esame *e, const char *d, char sep, char sepDt );
    int acquisisci_nome( Esame *e, const char *n );
    int acquisisci_punteggio( Esame *e, const char *p );
    int acquisisci_data_da_stringa( Esame *e, const char *d, char sepDt );
    int acquisisci_data( Esame *e, char g, char m, short a );
    void visualizza_dati_esame( Esame *e );
    
    int conta_righe_file_dati( const char *nf );
    int quantita_elementi_in_stringa( const char *d, char sep );
    int quantita_spazi_iniziali_in_stringa( const char *d );
    int long_da_stringa( const char *d, long *n );
    int anno_bisestile( int anno );
    
    /*==============================================================================
    Legge dati formattati dal file chiamato kStrNomeFile e li mostra in console.
    Somma i punteggi e mostra un resoconto complessivo degli esiti.
    In caso di errore, mostra in console gli opportuni messaggi di avviso.
    ==============================================================================*/
    
    int main() {
        char buff[LMAX_RIGA+1];
        FILE *f    = NULL;
        Esame e    = {0};
        int ptTot  = 0;
        int qEsami = 0;
        int qRighe = 0;
    
        qRighe = conta_righe_file_dati( kStrNomeFile );
    
        f = fopen( kStrNomeFile, "r" );
    
        if( NULL != f ) {
            while( NULL != fgets(buff,LMAX_RIGA,f) ) {
                if( buff[strlen(buff)-1] != '\n' && !feof(f) ) break;
    
                if( acquisisci_dati_da_stringa(&e,buff,'\t','/') ) {
                    visualizza_dati_esame( &e );
    
                    ++qEsami;
                    ptTot += e.punti;
                }
                else {
                    break;
                }
            }
    
            fclose( f );
    
            if( qRighe == qEsami ) {
                float media = ((float)ptTot)/((float)qEsami);
                printf( "Totale esami sostenuti: %5d\n", qEsami );
                printf( "Totale punteggi esami:  %5d / %d\n", ptTot, kMaxPunti );
                printf( "Media punteggi esami:   %5.1f / %d\n\n", media, kMaxPunti );
            }
            else {
                printf( "Errore: dati non validi alla riga %d.\n\n", qEsami+1 );
            }
        }
        else {
            printf( "Errore: file non aperto.\n\n" );
        }
    
        return 0;
    }
    
    /*==============================================================================
    Data una stringa formattata d e i caratteri separatori sep e sepDt, "compila" la
    struttura di tipo Esame puntata dal parametro e coi dati letti, controllandone
    la validita'.
    Se la lettura va a buon fine, restituisce 1.
    Se la lettura fallisce, restituisce 0.
    ==============================================================================*/
    
    int acquisisci_dati_da_stringa( Esame *e, const char *d, char sep, char sepDt ) {
        if( NULL != e && NULL != d ) {
            if( kQElDaStringa == quantita_elementi_in_stringa(d,sep) ) {
                size_t ld = strlen( d );
                char *s = (char*) malloc( ld+1 );
    
                if( NULL != s ) {
                    Esame eTmp; // per immagazzinare temporaneamente i dati letti
                    char *ptr;  // un puntatore ausiliario
                    int ok;
    
                    strcpy( s, d );
    
                    *(ptr=strchr(s,sep)) = '\0'; // cambia il separ. con '\0'
    
                    if( (ok=acquisisci_nome(&eTmp,s)) ) {
                        s = ptr+1; // supera il separatore
                        *(ptr=strchr(s,sep)) = '\0'; // cambia il separ. con '\0'
    
                        if( (ok=acquisisci_punteggio(&eTmp,s)) ) {
                            s = ptr+1; // supera il separatore
                            ok = acquisisci_data_da_stringa( &eTmp, s, sepDt );
                        }
                    }
    
                    free( s );
    
                    if( ok ) *e = eTmp;
    
                    return ok;
                }
            }
        }
    
        return 0;
    }
    
    /*==============================================================================
    Copia nel campo nome della struttura di tipo Esame puntata dal parametro e la
    stringa puntata dal parametro n. Se e' il caso, tronca la stringa in modo che
    non ecceda la capacita' massima prevista.
    Se la copia va a buon fine, restituisce 1.
    Se la copia fallisce, restituisce 0.
    ==============================================================================*/
    
    int acquisisci_nome( Esame *e, const char *n ) {
        if( NULL != e && NULL != n ) {
            size_t ln;
    
            memset( e->nome, 0, LMAX_NOME+1 );
    
            n += quantita_spazi_iniziali_in_stringa( n );
            ln = strlen( n );
    
            if( ln <= LMAX_NOME ) {
                strncpy( e->nome, n, LMAX_NOME );
            }
            else {
                strncpy( e->nome, n, LMAX_NOME-3 );
                strcat( e->nome, "..." );
            }
    
            return 1;
        }
    
        return 0;
    }
    
    /*==============================================================================
    Copia nel campo punti della struttura di tipo Esame puntata dal parametro e il
    valore numerico ricavato dalla conversione della stringa puntata dal parametro
    p, verificando che tale valore sia compreso tra 0 e kMaxPunti.
    Se la copia va a buon fine, restituisce 1.
    Se la copia fallisce, restituisce 0.
    ==============================================================================*/
    
    int acquisisci_punteggio( Esame *e, const char *p ) {
        if( NULL != e && NULL != p ) {
            long nTmp;
    
            if( 0 != long_da_stringa(p,&nTmp) ) {
                if( nTmp >= 0 && nTmp <= kMaxPunti ) {
                    e->punti = nTmp;
                    return 1;
                }
            }
        }
    
        return 0;
    }
    
    /*==============================================================================
    Copia nei campi giorno, mese e anno della struttura di tipo Esame puntata dal
    parametro e la data ricavata dalla conversione della stringa puntata dal
    parametro p, verificando che tale valore rappresenti una data valida.
    Se la copia va a buon fine, restituisce 1.
    Se la copia fallisce, restituisce 0.
    ==============================================================================*/
    
    int acquisisci_data_da_stringa( Esame *e, const char *d, char sepDt ) {
        if( NULL == e || NULL == d ) return 0;
    
        if( 3 == quantita_elementi_in_stringa(d,sepDt) ) {
            char gTmp, mTmp;
            short aTmp;
            long nTmp;
            int letti;
    
            if( (letti=long_da_stringa(d,&nTmp)) ) gTmp = nTmp; else return false;
    
            d += letti+1; // +1 per andare oltre al separatore
    
            if( (letti=long_da_stringa(d,&nTmp)) ) mTmp = nTmp; else return false;
    
            d += letti+1; // +1 per andare oltre al separatore
    
            if( (letti=long_da_stringa(d,&nTmp)) ) aTmp = nTmp; else return false;
    
            return acquisisci_data( e, gTmp, mTmp, aTmp );
        }
    
        return 0;
    }
    
    /*==============================================================================
    Funzione di supporto per acquisisci_data_da_stringa().
    Verifica che i valori passati tramite i tre parametri g, m e a rappresentino una
    data valida, quindi li copia nei campi giorno, mese e anno della struttura di
    tipo Esame puntata dal parametro e.
    Se la copia va a buon fine, restituisce 1.
    Se la copia fallisce, restituisce 0.
    ==============================================================================*/
    
    int acquisisci_data( Esame *e, char g, char m, short a ) {
        if( NULL == e ) return 0;
    
        if( g>0 && m>0 && a>0 ) {
            if( m>12 ) return 0;
    
            switch( m ) { /* verifica gli intervalli dei valori per il giorno */
                case 2: // mese di febbraio
                    if( g<(29+anno_bisestile(a)) )
                        break;
                    else return 0;
                case 4: case 6: case 9: case 11: // mesi di 30 gg massimo
                    if( g<31 )
                        break;
                    else return 0;
                default: // tutti gli altri mesi
                    if( g>31 ) return 0;
            }
    
            e->giorno = g;
            e->mese   = m;
            e->anno   = a;
    
            return 1;
        }
    
        return 0;
    }
    
    /*==============================================================================
    Mostra in console il contenuto della struttura di tipo Esame puntata dal
    parametro e. Se e e' NULL, la funzione non fa nulla.
    ==============================================================================*/
    
    void visualizza_dati_esame( Esame *e ) {
        if( NULL != e ) {
            printf( "esame: %s\n", e->nome );
            printf( "punti: %d/%d\n", e->punti, kMaxPunti );
            printf( "data:  %02d/%02d/%04d\n\n", e->giorno, e->mese, e->anno );
        }
    }
    
    /*==============================================================================
    Dato il nome di un file nf, conta la quantita' delle righe in esso contenute.
    L'identificazione delle righe avviene contando le ricorrenze del carattere '\n'.
    Un file, anche vuoto, contiene sempre almeno una riga (per quanto vuota).
    La quantita' delle righe viene restituita come valore di ritorno.
    ==============================================================================*/
    
    int conta_righe_file_dati( const char *nf ) {
        FILE *f = NULL;
        int c, qr = 1;
    
        if( NULL == nf ) return 0;
    
        f = fopen( nf, "r" );
        if( NULL == f ) return 0;
    
        for( c=fgetc(f); c!=EOF; c=fgetc(f) )
            qr += '\n' == c;
    
        fclose( f );
        return qr;
    }
    
    /*==============================================================================
    Conta e restituisce come valore di ritorno la quantita' degli elementi presenti
    nella stringa puntata dal parametro d, identificandoli in base alle ricorrenze
    del carattere passato tramite il parametro sep.
    ==============================================================================*/
    
    int quantita_elementi_in_stringa( const char *d, char sep ) {
        int qEl = 0;
    
        if( NULL != d )
            for( ++qEl; *d; ++d )
                qEl += sep==*d;
    
        return qEl;
    }
    
    /*==============================================================================
    Conta e restituisce come valore di ritorno la quantita' degli spazi iniziali
    presenti nella stringa puntata dal parametro d, identificandoli in base al
    responso della funzione isspace().
    ==============================================================================*/
    
    int quantita_spazi_iniziali_in_stringa( const char *d ) {
        if( NULL != d ) {
            const char *ptr = d;
            while( isspace(*ptr) ) ++ptr;
            return ptr-d;
        }
    
        return 0;
    }
    
    /*==============================================================================
    Copia nel valore di tipo long int puntato dal parametro n il valore numerico
    ricavato dalla conversione della stringa puntata dal parametro d.
    Se la copia va a buon fine, restituisce la quantita' dei caratteri letti dalla
    stringa puntata da d. Se la copia fallisce, restituisce 0.
    ==============================================================================*/
    
    int long_da_stringa( const char *d, long *n ) {
        if( NULL != d && NULL != n ) {
            char *fine;
            long nTmp;
    
            nTmp = strtol( d, &fine, 10 );
    
            if( fine != d ) {
                *n = nTmp;
                return fine-d;
            }
        }
    
        return 0;
    }
    
    /*==============================================================================
    Restituisce 1 se l'anno passato tramite l'unico parametro e' un anno bisestile,
    0 in caso contrario.
    ==============================================================================*/
    
    int anno_bisestile( int anno ) {
        if( anno > 1582 ) /* calendario gregoriano */
            return (!(anno%400)) || ( (!(anno%4)) && (anno%100) );
        else /* calendario giuliano (non fa la verifica dei 400 anni) */
            return (!(anno%4)) && (anno%100);
    }
    MANICOMIOOOOO!
  • Re: Problema con programma che legge file

    E ora, la versione corredata da una "graziosissima" classe...

    file main.cpp
    #include <stdlib.h>
    #include <stdio.h>
    
    #include "classe_esame.h"
    
    #define LMAX_RIGA 1023 // ogni riga del file non deve eccedere questa lunghezza
    
    const char kStrNomeFile[] = "dati.txt"; // il nome del file da leggere
    
    /** ==> PROTOTIPI <==========================================================**/
    
    Esame *carica_dati_esami( const char *nf, int *qe );
    void stampa_resoconto_esami( Esame *e, int qe );
    int conta_righe_file_dati( const char *nf );
    
    /*==============================================================================
    Legge dati formattati dal file chiamato kStrNomeFile.
    Se il caricamento va a buon fine, stampa un elenco dei dati letti.
    ==============================================================================*/
    
    int main() {
        int qe;
    
        Esame *e = carica_dati_esami( kStrNomeFile, &qe );
    
        if( NULL != e ) {
            stampa_resoconto_esami( e, qe );
            delete[] e; e = NULL;
        }
    
        return 0;
    }
    
    /*==============================================================================
    Dato il nome di un file nf ne carica il contenuto in un array di oggetti di tipo
    Esame allocato dinamicamente.
    Se l'operazione va a buon fine, restituisce il puntatore all'array degli oggetti
    allocati e debitamente "compilati", collocando all'indirizzo puntato dal
    parametro qe la quantita' degli elementi dell'array allocato.
    In caso d'errore, restituisce NULL e non modifica lo spazio di memoria puntato
    dal parametro qe.
    ==============================================================================*/
    
    Esame *carica_dati_esami( const char *nf, int *qe ) {
        if( NULL==nf || NULL==qe ) return NULL;
    
        int qr = conta_righe_file_dati( kStrNomeFile );
        if( 0 == qr ) return NULL;
    
        Esame *e = NULL;
        FILE *f = fopen( nf, "r" );
    
        if( NULL != f ) {
            try {
                char buff[LMAX_RIGA+1];
                int i;
    
                e = new Esame[qr];
    
                for( i=0; i<qr; ++i ) {
                    if( !fgets(buff,LMAX_RIGA,f) )
                        break;
    
                    if( !e[i].AcquisisciDatiDaStringa(buff,'\t','/') )
                        break;
                }
    
                fclose( f ); // non ci serve piu'
    
                if( i == qr ) {
                    *qe = i; // comunica la quantita' degli esami letti
                }
                else {
                    printf( "File \"%s\": errore alla riga %d.\n\n", nf, i+1 );
                    delete[] e; e = NULL;
                }
            } catch( ... ) {
                fclose( f );
                return NULL;
            }
        }
    
        return e;
    }
    
    /*==============================================================================
    Mostra in console il contenuto degli oggetti di tipo Esame presenti nell'array
    puntato dal parametro e. Il parametro qe indica la quantita' degli elementi di
    tipo Esame presenti nell'array.
    Se e e' NULL e/o qe e' minore o uguale a 0, la funzione non fa nulla.
    ==============================================================================*/
    
    void stampa_resoconto_esami( Esame *e, int qe ) {
        if( NULL != e && qe > 0 ) {
            int i;
    
            for( i=0; i<qe; ++i ) {
                printf( "esame: %s\n", e[i].Nome() );
                printf( "punti: %d/%d\n", e[i].Punteggio(), Esame::kMaxPunti );
                printf( "data:  %s\n\n", e[i].Data('-') );
            }
        }
    }
    
    /*==============================================================================
    Dato il nome di un file nf, conta la quantita' delle righe in esso contenute.
    L'identificazione delle righe avviene contando le ricorrenze del carattere '\n'.
    Un file, anche vuoto, contiene sempre almeno una riga (per quanto vuota).
    La quantita' delle righe viene restituita come valore di ritorno.
    ==============================================================================*/
    
    int conta_righe_file_dati( const char *nf ) {
        if( NULL == nf ) return 0;
    
        FILE *f = fopen( nf, "r" );
        if( NULL == f ) return 0;
    
        int qr = 1;
    
        for( int c=fgetc(f); c!=EOF; c=fgetc(f) )
            qr += '\n' == c;
    
        fclose( f );
        return qr;
    }
    file classe_esame.h
    #ifndef CLASSE_ESAME_H
    #define CLASSE_ESAME_H
    
    class Esame {
        public:
            Esame();
            Esame( const char *n, int pt, char g, char m, short a );
            Esame( const char *d, char sep, char sepData );
            virtual ~Esame();
    
            bool Nome( const char *n );
            const char *Nome( void ) { return nome; }
    
            bool Punteggio( int p );
            bool Punteggio( const char *d );
            int Punteggio( void ) { return punti; }
    
            bool Data( char g, char m, short a );
            bool Data( const char *d, char sep );
            void Data( char *g, char *m, short *a );
            const char *Data( char sep, int formato = 224 );
    
            bool AcquisisciDatiDaStringa( const char *d, char sep, char sepData );
    
            static const int kLMaxNome;
            static const int kQElDaStringa;
            static const int kMaxPunti;
            static int QuantitaElementiInStringa( const char *d, char sep );
            static int QuantitaSpaziIniziali( const char *d );
            static int LongDaStringa( const char *d, long *n );
            static bool Bisestile( int a );
    
        protected:
    
        private:
            char  nome[32]; // 32: kLMaxNome+1
            int   punti;
            char  giorno;
            char  mese;
            short anno;
    };
    
    #endif // CLASSE_ESAME_H
    file classe_esame.cpp
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    #include "classe_esame.h"
    
    const int Esame::kLMaxNome       =  31;
    const int Esame::kQElDaStringa   =   3;
    const int Esame::kMaxPunti       =  30;
    
    Esame::Esame() {
        memset( nome, 0, sizeof(nome) );
        punti  = 0;
        giorno = 0;
        mese   = 0;
        anno   = 0;
    }
    
    Esame::Esame( const char *n, int pt, char g, char m, short a ) {
        if( !Nome(n) )         throw "Nome esame non valido";
        if( !Punteggio(pt) )   throw "Punteggio esame non valido";
        if( !Data(g,m,a) )     throw "Data esame non valida";
    }
    
    Esame::Esame( const char *d, char sep, char sepData ) {
        if( !AcquisisciDatiDaStringa(d,sep,sepData) )
            throw "Dati da stringa non validi";
    }
    
    Esame::~Esame() {
        //dtor
    }
    
    bool Esame::Nome( const char *n ) {
        if( NULL != n ) {
            size_t ln;
    
            memset( nome, 0, LMAX_NOME+1 );
    
            n += QuantitaSpaziIniziali( n );
            ln = strlen( n );
    
            if( ln <= kLMaxNome ) {
                strncpy( nome, n, kLMaxNome );
            }
            else {
                strncpy( nome, n, kLMaxNome-3 );
                strcat( nome, "..." );
            }
    
            return true;
        }
    
        return false;
    }
    
    bool Esame::Punteggio( int p ) {
        if( p>=0 && p<=kMaxPunti ) {
            punti = p;
            return true;
        }
    
        return false;
    }
    
    bool Esame::Punteggio( const char *d ) {
        if( NULL != d ) {
            long nTmp;
            
            if( 0 != LongDaStringa(d,&nTmp) )
                return Punteggio( nTmp );
        }
    
        return false;
    }
    
    bool Esame::Data( char g, char m, short a ) {
        if( g>0 && m>0 && a>0 ) {
            if( m>12 ) return false;
    
            switch( m ) { /* verifica gli intervalli dei valori per il giorno */
                case 2: // mese di febbraio
                    if( g<(29+Bisestile(a)) )
                        break;
                    else return false;
                case 4: case 6: case 9: case 11: // mesi di 30 gg massimo
                    if( g<31 )
                        break;
                    else return false;
                default: // tutti gli altri mesi
                    if( g>31 ) return false;
            }
    
            giorno = g;
            mese   = m;
            anno   = a;
    
            return true;
        }
    
        return false;
    }
    
    bool Esame::Data( const char *d, char sep ) {
    
        if( 3 == QuantitaElementiInStringa(d,sep) ) {
            char gTmp, mTmp;
            short aTmp;
            long nTmp;
            int letti;
    
            if( (letti=LongDaStringa(d,&nTmp)) ) gTmp = nTmp; else return false;
    
            d += letti+1; // +1 per andare oltre al separatore
    
            if( (letti=LongDaStringa(d,&nTmp)) ) mTmp = nTmp; else return false;
    
            d += letti+1; // +1 per andare oltre al separatore
    
            if( (letti=LongDaStringa(d,&nTmp)) ) aTmp = nTmp; else return false;
    
            return Data( gTmp, mTmp, aTmp );
        }
    
        return false;
    }
    
    void Esame::Data( char *g, char *m, short *a ) {
        if( NULL != g ) *g = giorno;
        if( NULL != m ) *m = mese;
        if( NULL != a ) *a = anno;
    }
    
    const char *Esame::Data( char sep, int formato ) {
        static char d[16];
        int g = giorno;
        int m = mese;
        int a = anno;
    
        switch( formato ) {
           case 112: sprintf( d, "%d%c%d%c%02d", g, sep, m, sep, a%100 ); break;
           case 222: sprintf( d, "%02d%c%02d%c%02d", g, sep, m, sep, a%100 ); break;
           case 114: sprintf( d, "%d%c%d%c%04d", g, sep, m, sep, a ); break;
           default: sprintf( d, "%02d%c%02d%c%04d", g, sep, m, sep, a );
        }
    
        return d;
    }
    
    bool Esame::AcquisisciDatiDaStringa( const char *d, char sep, char sepData ) {
        if( NULL != d ) {
            if( kQElDaStringa == QuantitaElementiInStringa(d,sep) ) {
                size_t ld = strlen( d );
                char *s = (char*) malloc( ld+1 );
    
                if( NULL != s ) {
                    Esame eTmp; // per immagazzinare temporaneamente i dati letti
                    char *ptr;  // un puntatore ausiliario
                    bool ok;
    
                    strcpy( s, d );
    
                    *(ptr=strchr(s,sep)) = '\0'; // cambia il separ. con '\0'
    
                    if( (ok=eTmp.Nome(s)) ) {
                        s = ptr+1; // supera il separatore
                        *(ptr=strchr(s,sep)) = '\0'; // cambia il separ. con '\0'
    
                        if( (ok=eTmp.Punteggio(s)) ) {
                            s = ptr+1; // supera il separatore
                            ok = eTmp.Data( s, sepData );
                        }
                    }
    
                    free( s );
    
                    if( ok ) *this = eTmp;
    
                    return ok;
                }
            }
        }
    
        return false;
    }
    
    int Esame::QuantitaElementiInStringa( const char *d, char sep ) {
        int qEl = 0;
    
        if( NULL != d )
            for( ++qEl; *d; ++d )
                qEl += sep==*d;
    
        return qEl;
    }
    
    int Esame::QuantitaSpaziIniziali( const char *d ) {
        if( NULL != d ) {
            const char *ptr = d;
            while( isspace(*ptr) ) ++ptr;
            return ptr-d;
        }
    
        return 0;
    }
    
    int Esame::LongDaStringa( const char *d, long *n ) {
        if( NULL != d && NULL != n ) {
            char *fine;
            long nTmp;
    
            nTmp = strtol( d, &fine, 10 );
    
            if( fine != d ) {
                *n = nTmp;
                return fine-d;
            }
        }
    
        return 0;
    }
    
    bool Esame::Bisestile( int a ) {
        if( a > 1582 ) /* calendario gregoriano */
            return (!(a%400)) || ( (!(a%4)) && (a%100) );
        else /* calendario giuliano (non fa la verifica dei 400 anni) */
            return (!(a%4)) && (a%100);
    }
    Per quanto possa sembrare impossibile... funziona! MANICOMIO 2!
  • Re: Problema con programma che legge file

    Il bello è che ho fatto la prova intercorso, la traccia era praticamente identica a quella che vi ho mandato, solo con un'aggiunta: creare una struttura, un vettore di struct, 4 funzioni, un vettore di stringhe e altra roba che adesso non ricordo... praticamente lo voleva come questo lungo 400 righe? AHAAHAHAH
Devi accedere o registrarti per scrivere nel forum
44 risposte