Estrarre numeri da stringhe ricavate da file+ posizionamento in vettori

di il
7 risposte

Estrarre numeri da stringhe ricavate da file+ posizionamento in vettori

Salve a tutti sono nuovo, vi scrivo perché dopo anni ho ripreso in mano la programmazione C e sono un po' nei pasticci.

il mio problema è riuscire, aprendo il file tipo come riportato sotto, ad estrapolare i dati che come si vede stanno nella parte centrale del file e memorizzare i numeri in un vettore. Mi spiego meglio il formato del file è simile a questo:

*Questa riga è di introduzione
*si riportano i dati
720			numero di passi
350			respiri in 10 minuti di corsa
10.3			metri al secondo durante lo scatto 
**********************************************************
non è esattamente il contenuto (è più lungo e diverso ma il formato è quello), poniamo venga salvato in "engine.txt"

Fino all'apertura del file e il relativo errore di apertura nessun problema, credo ci siano due problemi:
il primo credo salti la condizione di if delle righe contenenti l'asterisco (che non voglio scriva), il secondo quando voglio memorizzare i numeri 720 350 e 10.3 all'interno di un vettore. Io ho pensato ad una soluzione del genere, tralasciamo l'ottimizzazione che non importa (basta funzioni), mi sapete dire come mai non funziona? ho provato anche a usare numeri interi nel file, cambiando %f in %d e definendo il vettore int ma stampa sempre lo stesso numero che non è nel file.

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define dim 150
int main(){

FILE * f;

char riga[dim];
float dato;
int i,n;
float vett[15];


f=fopen("engine.txt","r");                //apre il file di input//

if (f == NULL) {                         //condizione di errore apertura file//

    printf("ERRORE nell'apertura del file");
    return 1;
}

i=0;
while(!feof(f) ){                    //condizione di ciclo fino all'EOF //

    fgets(riga,dim,f);
    if (riga[0] != '*');               /*salta le righe con */
    sscanf(riga,"%f",dato);                  //prendi il float presente in riga e mettilo in dato//
    vett[i]=dato;
    i++;
}

fclose(f);                          //Chiusura file//

for (n=0;n<i+1;n++)                 //stampa il vettore//
printf("%f",vett[i]);
return 0;
}

7 Risposte

  • Re: Estrarre numeri da stringhe ricavate da file+ posizionamento in vettori

    Riprendendo i tuoi esempi di codice e di file di testo, io utilizzerei la funzione al posto della funzione sscanf( ), e in particolare:
    vett[i] = strtof(riga, NULL);
    La variabile "dato" non è necessaria.
  • Re: Estrarre numeri da stringhe ricavate da file+ posizionamento in vettori

    Quando fai sscanf(riga,"%f",dato) sbagli, perché dovresti indicare l'indirizzo della variabile dato, non il suo valore. Così: sscanf(riga,"%f",&dato);

    In più, dovresti fare in modo che quando nel ciclo si individua una riga che inizia con '*' tutti i passi successivi del ciclo stesso vengano saltati, se no inserisci della porcheria in vett. Io farei così:
    while( !feof(f) ){ // condizione di ciclo fino all'EOF
        fgets( riga, dim, f );
    
        if( '*' == riga[0] != '*' )
            continue; { // evita che vengano lette le righe con * iniziale
           
        sscanf( riga, "%f", &dato ); // prendi il float da riga e mettilo in dato
        vett[i] = dato;
        i++;
    }
    Oppure andrebbe bene anche così:
    while( !feof(f) ){ // condizione di ciclo fino all'EOF
        fgets( riga, dim, f );
    
        if( riga[0] != '*' ) { // evita che vengano lette le righe con * iniziale
            sscanf( riga, "%f", &dato ); // prendi il float da riga e mettilo in dato
            vett[i] = dato;
            i++;
        }
    }
    Per brevità, anche se non cambia niente, potresti fare a meno della variabile dato e "inglobare" l'incremento di i nel sscanf().
    while( !feof(f) ){ // condizione di ciclo fino all'EOF
        fgets( riga, dim, f );
    
        if( riga[0] != '*' ) // evita che vengano lette le righe con * iniziale
            sscanf( riga, "%f", &vett[i++] ); // prendi il float da riga e mettilo in vett
    }
    Sempre per brevità, potresti sostituire il while con un for, così:
    for( i=0; !feof(f); ){ // condizione di ciclo fino all'EOF
        fgets( riga, dim, f );
    
        if( riga[0] != '*' ) // evita che vengano lette le righe con * iniziale
            sscanf( riga, "%f", &vett[i++] ); // prendi il float da riga e mettilo in vett
    }
    In uscita dal for (o dal while, se lo preferisci) hai in i la quantita' dei dati effettivamente letti, per cui per mostrare il contenuto di vett non dovresti andare fino a i+1, bensì solo fino a i:
    for( n=0; n<i; n++ ) // stampa il vettore
        printf( "%f", vett[i] );

    Ancora, se guardi bene, con vett stai mandando in console per tre volte l'ultimo valore letto. Invece di vett dovresti usare vett[n], perché è n il contatore che stai usando per "scorrere" il vettore.
    for( n=0; n<i; n++ ) // stampa il vettore
        printf( "%f", vett[n] );

    In questo modo ti ritrovi con i tre valori in coda, ma "appiccicati" uno all'altro. Dovresti inserire nella stringa di formato di printf() un qualche carattere distanziatore, ad esempio:
    for( n=0; n<i; n++ ) // stampa il vettore
        printf( "%f\n", vett[n] );

    Altre cose...

    In genere, nei libri sul C che ho letto, le macro si indicano con caratteri tutti maiuscoli, tipo DIM anziché dim.

    Userei una macro anche per indicare la quantità massima dei valori ammissibili, ad esempio definendo un MAX_VALORI anziché usare direttamente 15, e aggiungerei un controllo "antisfondamento" nel ciclo di lettura in vett[].

    Potrebbe essere utile segnalare l'eventuale impossibilità di leggere tutti i valori presenti nel file.
  • Re: Estrarre numeri da stringhe ricavate da file+ posizionamento in vettori

    Grazie delle risposte, sbattendoci tante volte la testa forse ho "risolto" ma ho anche letto cosa mi avete scritto.

    Per quanto riguarda lo strtok(), ho paura che mi prenda si il numero dalla riga delfile che legge, ma in formato stringa! mi sbaglio? intendo anziché leggere il numero 623 leggerebbe i caratteri 6 2 3 \0.

    Il resto si mi son accorto di non aver utilizzato l'indirizzo in dato con "&" e si l'ho usato come appoggio, si potrebbe fare più corto.
    il problema stava nel ; dell'if che leggeva la condizione e la chiudeva subito credo.

    ho modificato il codice come segue
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    #define DIM 150
    #define MAX 100
    int main(){
    
    FILE * f;
    
    char riga[DIM];
    float dato;
    int i;
    float vett[MAX];
    f=fopen("engine.txt","r");                //apre il file di input//
    
    if (f == NULL) {                         //condizione di errore apertura file//
        printf("ERRORE nell'apertura del file");
        return 1;}
    i=0;
    while(!feof(f) ){                    //condizione di ciclo fino all'EOF //
        fgets(riga,DIM,f);
        if (riga[0] != '*' ){             /*salta le righe con */
        sscanf(riga,"%f",&dato);                  //prendi il float presente in riga e mettilo in dato//
        vett[i]=dato;                        //prendi il valore di dato e mettila nell'i-esima cella del vettore definito float//
        printf("%f \n",vett[i]);                // stampa l'i-esimo valore del vettore//
        i++;}
    }
    fclose(f);
    
        printf("\n \n%d",i);                 //verifica il numero di cicli//
    return 0;
    }
    
    adesso torna e se stampo ad esempio vett [3], dopo la stampa della variabile i quindi una volta chiuso il file, tiene in memoria il valore del numero della 4 riga senza asterishi, come giusto che sia.
    Ho corretto l'indirizzo utilizato i caratteri per le dimensioni del vettore come suggerito.

    ne approfitto per chiedervi un'altra cosa nel file esiste un numero che è scritto come "7.45D-8" come posso rappresentarlo? dovrebbe essere 0.0000000745, ma anche mettendo "double" dove ho scritto float e %lf al posto di %f con il numero 0.0000000745 mi scrive 0.000000.
  • Re: Estrarre numeri da stringhe ricavate da file+ posizionamento in vettori

    gio944 ha scritto:


    Per quanto riguarda lo strtok()....
    Non so se ti riferisci al mio intervento/suggerimento, nel caso sottolineo che la funzione da me proposta è: strtof ()
    e non strtok() !
  • Re: Estrarre numeri da stringhe ricavate da file+ posizionamento in vettori

    Pardon, non ho letto bene! hai ragione.
    se avessi invece una serie di numeri sulla stessa riga e volessi metterlo ognuno in un vettore differente con strtof come si può fare?
    una cosa del genere.
    .
    .
    12.2 54.3 32.5 primo concorrente
    .
    .

    Con sscanf io avrei fatto una cosa del genere
    
    sscanf(riga,"%f %f %f", &vett1[i], &vett2[i], &vett3[i])
    
    ovviamente con riga, i inizializzati e i incrementato dopo ogni riga
  • Re: Estrarre numeri da stringhe ricavate da file+ posizionamento in vettori

    La quantità delle cifre dopo la virgola può essere modificanda agendo sulla stringa di formato in printf().

    Ad esempio...

    printf("%.2f",3.1415926535897932384626433832795) visualizza in console 3.14

    printf("%.8f",3.1415926535897932384626433832795) visualizza in console 3.14159265

    In genere se non specifichi la quantità di cifre dopo la virgola, il valore predefinito è 6, per cui...

    printf("%f",3.1415926535897932384626433832795) visualizza 3.141592

    http://www.cplusplus.com/reference/cstdio/printf
  • Re: Estrarre numeri da stringhe ricavate da file+ posizionamento in vettori

    Vorrei solo segnalare che nel tuo codice iniziale, e in particolare le due righe afferenti alla stampa dei risultati nel vettore "vett[ ]", da un lato con comprendo perché in " n<i+1 " poni quell'addizione di un'unità, dall'altro la seconda riga va corretta così:
    printf("%f\n",vett[n]);
Devi accedere o registrarti per scrivere nel forum
7 risposte