+ Rispondi
Pagina 1 di 2 1 2 UltimaUltima
Risultati da 1 a 10 di 14

Discussione: Lettura da file delimited

  1. #1
    Nuovo della community
    reputazione complessiva: 1 1

    Messaggi
    7

    Lettura da file delimited

    salve ragazzi, un saluto a tutto il forum dato che sono nuovo,
    ho un problema simile, avrei necessità di caricare una sequenza di numeri contenuti nel file di test "prova.txt" in un vettore.
    es.
    nel file di testo è contenuta la stringa:
    32 65 98 98 54 21 35

    e dovrei caricarli nel vettore "numeri" tale che:
    numeri[0] = 32
    numeri[1] = 65
    numeri[2] = 98
    .
    .
    .
    ecc ecc
    potreste darmi una mano?
    grazie a tutti

  2. #2
    Moderatore Globale L'avatar di M.A.W. 1968
    reputazione complessiva: 19 19

    Messaggi
    373
    Blogs
    14
    Benvenuto nel forum.

    Accodare una richiesta ad un thread esistente, in genere, non è una buona idea. Lo è ancora meno quando il thread in oggetto risale al 2006. Consiglio di dare un'occhiata al nostro Regolamento.


    Riguardo al problema specifico, qual è la difficoltà riscontrata ? Proponi il codice che hai prodotto nello sforzo di risolvere il problema, e discutiamolo insieme.
    Tutti gli utenti sono pregati di prendere visione del Regolamento del Forum e di rispettarlo.

    Sì, un blog ce l'ho perfino io: gli è che mi manca il tempo...

    • "Die ganzen Zahlen hat der liebe Gott gemacht, alles andere ist Menschenwerk." (Leopold Kronecker)
    • "A Mathematician is a machine for turning coffee into theorems." (Pal Erdös)
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

  3. #3
    Nuovo della community
    reputazione complessiva: 1 1

    Messaggi
    7
    si scusa, non sono molto pratico sui forum, adesso accodo il codice

    Codice:
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int numeri[100];
     
    int importa_dati_file()
    {
        FILE *f = fopen("numeri.txt", "r");
        if(f == NULL)
        {
            printf("Errore nel leggere il file!\n");
            return 0;
        }
     
        fread (numeri,sizeof(int),100,f);
        for(int i=0; i<10;i++)
        printf("%c",numeri[i]);
        fclose(f);
    }; 
     
     
    int main()
    {
        importa_dati_file();
     
        system("PAUSE"); 
    }
    il problema e che mi estrae numeri che non centrano nulla...
    sul file ci sono i seguenti numeri:
    32 65 98 54 87 21 6 32 5

    ma in output mi spunta:
    35 813



    mmhaa...?
    Ultima modifica di M.A.W. 1968; 23-01-2010 alle 18:48

  4. #4
    Nuovo della community
    reputazione complessiva: 1 1

    Messaggi
    7
    ci sono riuscito... anche se la soluzione è un pò grezza, esegue alla perfezione il suo compito...

    Codice:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char numeri[100];
    int num_dati;
    char *vettore;
    int vettoreint[100];
    
    int importa_dati_file()
    {
    
        
        FILE *f = fopen("numeri.txt", "r");
        	if(f == NULL)
        	{
        		printf("Errore nel leggere il file!\n");
        		return 0;
        	}
    
    	num_dati = fread (numeri,sizeof(char),100,f);
    
        vettore = strtok(numeri," ");
    
    
        
       //converte da char a int i numeri 
       for(int i=0; vettore != NULL; i++)
     {
       vettoreint[i]=atoi(vettore);
       vettore = strtok(NULL, " ");
     }
        
        
        //stampa vettore
        for(int i=0; vettoreint[i]!=0; i++)
                printf("\n%i",vettoreint[i]);
    
    };   
    
    
    
    
    int main()
    {
        importa_dati_file();
    
        system("PAUSE");   
    }

  5. #5
    Moderatore Globale L'avatar di M.A.W. 1968
    reputazione complessiva: 19 19

    Messaggi
    373
    Blogs
    14
    In effetti, il ricorso a strtok() è un escamotage probabilmente eccessivo, come d'altro canto è eccessiva (e inerentemente poco robusta) quella fread() dimensionata per 100 char.

    Suggerisco di ripensare il codice e optare per una soluzione più elegante ed efficace che faccia uso di fgets(). Inoltre sarà molto didattico sperimentare soluzioni alternative alla strtok().
    Tutti gli utenti sono pregati di prendere visione del Regolamento del Forum e di rispettarlo.

    Sì, un blog ce l'ho perfino io: gli è che mi manca il tempo...

    • "Die ganzen Zahlen hat der liebe Gott gemacht, alles andere ist Menschenwerk." (Leopold Kronecker)
    • "A Mathematician is a machine for turning coffee into theorems." (Pal Erdös)
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

  6. #6
    Nuovo della community
    reputazione complessiva: 1 1

    Messaggi
    7
    si infatti, è stata allocata a 100 per una semplice prova, adesso sistemo il codice è metto qualcosa di meno osceno...

    il problema e che non riesco a leggere solamente i numeri, ma carattere per carattere...

    per adesso il programma si comporta nel seguente modo:

    1) importa i dati e memorizza ogni singolo carattere in ogni cella dell'array "numeri" di tipo char.

    2)divide tutta la stringa in "tok" ogni volta che trova il carattere spazio e memorizza tutti i tok in ogni cella dell'array "vettoreint" convertendoli prima in formato int.

    conoscete qualche metodo più elegante per fare il medesimo lavoro?
    Ultima modifica di M.A.W. 1968; 24-01-2010 alle 01:20

  7. #7
    Moderatore Globale L'avatar di M.A.W. 1968
    reputazione complessiva: 19 19

    Messaggi
    373
    Blogs
    14
    Ho buttato giù brevemente una possibile infrastruttura di test per sviluppare il discorso.

    Codice:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    #define BUFF_SIZE  128
    #define MAX_NUMERI 100
    #define DELIMS " \t\n\r"
    
    int PopolaArray1(const char *Buff, int *Array, const int Limite)
    {
        int i = 0;
        char *p;
    
        /*
           Ai soli fini del test: la strtok() non è priva
           di side effects, mentre a noi occorre riusare Buff.
        */
        char *b = strdup(Buff);
    
        p = strtok(b, DELIMS);
    
        while ((NULL != p) && (i < Limite))
        {
            Array[i++] = atoi(p);
            p = strtok(NULL, DELIMS);
        }
    
        return (i);
    }
    
    int PopolaArray2(const char *Buff, int *Array, const int Limite)
    {
        int i = 0;
        int val = atoi(Buff);
    
        /*
           La atoi è molto potente anche da sola, ma ha una
           notevole limitazione...
        */
        while (0 != val)
        {
            Array[i++] = val;
            while (isdigit(*Buff++));
            val = atoi(Buff);
        }
    
        return (i);
    }
    
    int PopolaArray3(const char *Buff, int *Array, const int Limite)
    {
        return (0);
    }
    
    void StampaArray(int *Array, int Limite)
    {
        int i;
    
        printf("# L'array letto contiene %d interi:\n", Limite);
        for (i = 0; i < Limite; ++i)
        {
            printf("Array[%d] = %d\n", i, Array[i]);
        }
    }
    
    int main(void)
    {
        FILE *fin;
        char buff[BUFF_SIZE];
        int numeri[MAX_NUMERI];
        int tot_numeri;
    
        puts("# Apertura del file");
        fin = fopen("prova.txt", "r");
    
        if (NULL == fin)
        {
            fputs("Errore durante l'apertura del file !", stderr);
            return (1);
        }
    
        if (NULL == fgets(buff, BUFF_SIZE, fin))
        {
            fputs("Errore di lettura dal file !", stderr);
            return (2);
        }
    
        fclose(fin);
    
        printf("\n# Lettura, metodo 1\n# Buffer: [%s]\n", buff);
        tot_numeri = PopolaArray1(buff, numeri, MAX_NUMERI);
        if (tot_numeri)
        {
            StampaArray(numeri, tot_numeri);
        }
    
        printf("\n# Lettura, metodo 2\n# Buffer: [%s]\n", buff);
        tot_numeri = PopolaArray2(buff, numeri, MAX_NUMERI);
        if (tot_numeri)
        {
            StampaArray(numeri, tot_numeri);
        }
    
        printf("\n# Lettura, metodo 3\n# Buffer: [%s]\n", buff);
        tot_numeri = PopolaArray3(buff, numeri, MAX_NUMERI);
        if (tot_numeri)
        {
            StampaArray(numeri, tot_numeri);
        }
    
        getchar();
        return (0);
    }
    La questione è purtroppo molto semplice nella sua primitiva brutalità: più sono destrutturati i dati, più la programmazione necessaria al parsing tenderà ad essere inelegante e difensiva.
    In generale quindi si tende a separare i numeri tramite CR/LF (uno per riga), oppure usando quantità predefinite di caratteri di interpunzione come ';' o tabulazioni '\t', si cerca inoltre di comunicare all'inizio del file o per ogni linea quanti sono i dati (questo evita il ricorso a pesanti e macchinosi parser a due step)...
    Soprattutto, si tende ad usare file di dati in formati binari ben strutturati e non semplici file ASCII, ovunque possibile.


    Illustrare un sia pur semplice parser numerico talmente robusto da "macinare" senza errori le peggiori schifezze che l'utonto riesce ad infilare in un banale file di testo "delimited" va decisamente al di là delle possibilità del forum. Tuttavia, si possono prendere in considerazione un paio di soluzioni di base, che comunque - per robustezza, e stante la natura sostanzialmente low level del C - non possono esimersi dal procedere carattere per carattere nell'analisi del buffer di input.

    La terza soluzione, lasciata come semplice esercizio per il lettore interessato, prevede l'uso di sscanf().
    Tutti gli utenti sono pregati di prendere visione del Regolamento del Forum e di rispettarlo.

    Sì, un blog ce l'ho perfino io: gli è che mi manca il tempo...

    • "Die ganzen Zahlen hat der liebe Gott gemacht, alles andere ist Menschenwerk." (Leopold Kronecker)
    • "A Mathematician is a machine for turning coffee into theorems." (Pal Erdös)
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

  8. #8
    Utente della community L'avatar di xardas
    reputazione complessiva: 5 5

    Messaggi
    230
    Ciao !

    Oltre a quanto consigliato da M.A.W. 1968, potresti ricorrere alla comoda fscanf();
    Se sai già quanti elementi ci sono nel file, e di che tipo (mi pare che sia il tuo caso), puoi impostare la fscanf() in modo che ti legga tutti i valori con una sola chiamata, quindi una cosa del tipo :
    Codice:
    fscanf(f,"%d %d %d %d %d %d %d",&numeri[0],numeri[1],numeri[2],numeri[3],numeri[4],numeri[5],numeri[6]);
    Altrimenti se non sai quanti elementi ci sono, puoi adottare una strada del genere :
    Codice:
    for(int i=0;!feof(f);++i){fscanf(f,"%d",&numeri[i]);}
    Chiaramente per la seconda soluzione dovrai dimensionare l'array numeri[] in modo da evitare l'overflow. L'ideale quindi, piuttosto che usare array statici esageratamente grandi, sarebbe ricorrere all'alocazione dinamica della memoria. Ovviamente devi implementare un algoritmo che ti restituisca il numero di interi presenti nel tuo file di testo, e al momento non mi viene in mente nessuna soluzione 'rapida'.

    Tuttavia una alternativa molto elastica potrebbe essere lo std::vector<>
    Lo std::vector è un vettore dinamico sul quale puoi con dei metodi appositi aggiungere o eliminare dinamicamente degli oggetti dalla coda del suddetto (inclusi quindi anche gli interi). Questo signigica che anche se non sai a priori quanti elementi dovrai caricare, puoi inserirglieli passo passo in una for, e farti stampare successivamente il contenuto trattandolo esattamente come un array convenzionale.

    Una cosa del tipo:
    Codice:
    #include<vector>
    std::vector<int> numeri;
    
    bool LeggiValori(char *path)
    {
    FILE *in=NULL;
    if(!(in=fopen(path,"rt"))){return false;}
    while(!feof(in))
    {
    int n;
    fscanf(in,"%d",&n);
    numeri.push_back(n);
    }
    fclose(in);
    return true;
    }
    
    void StampaValori()
    {
    for(int i=0;i<numeri.size();++i){printf("elemento[%d] = %d\n",i,numeri[i]);}
    }
    
    void FastStampaValori()//versione ottimizzata della StampaValori() con l'ausilio degli iteratori
    {
    for(std::vector<int>::iterator it=numeri.begin();it!=numeri.end;++it){printf("%d\n",*it);}
    }
    Ecco un link sugli array dinamici: Dynamic Memory
    E un buon reference sullo std::vector: vector - C++ Reference
    Spero di essere stato utile
    Ciao !

    ps:
    Ho notato che la discussione a preso piega sul fatto di leggere i dati come caratteri (char %c), e convertirli poi ad interi (con l' atoi() consigliata da M.A.W.), tuttavia non ho capito se è proprio voluto o non riuscivi a farlo direttamente leggendoli come interi ...
    Nel caso chiedo scusa per il fraintendimento
    Ultima modifica di xardas; 24-01-2010 alle 13:33
    __________________________________________________ ___________________
    La programmazione è uno dei tanti modi di esprimere la propria creatività, ed è un'arte.

    In questo siamo comuni, dai pittori ai poeti, dagli scultori fino ai programmatori ...
    Di mente siamo completamente diversi, ma di anima siamo tutti CREATIVI

    Firmato :
    -Xardas Black Raven-

  9. #9
    Moderatore Globale L'avatar di M.A.W. 1968
    reputazione complessiva: 19 19

    Messaggi
    373
    Blogs
    14
    Attenzione: la fscanf() assieme a sua cugina scanf(), è fortemente deprecata e non deve essere utilizzata.

    La soluzione da te proposta, appropriatamente modificata per l'uso di sscanf(), costituisce in pratica una soluzione all'esercizio sopra assegnato per il terzo metodo di lettura.

    Allo stesso modo, l'utilizzo della sola feof() come condizione di permanenza in un loop può riservare delle sorprese (tipicamente letture duplicate) poiché la sua modalità di funzionamento implica una lettura oltre la fine del file.


    Infine "l'algoritmo di conteggio" al quale alludi è solo una dellle tante varianti basate su strtok() o su un parser ad hoc, e costituisce esattamente "il primo passo" di un parser a due step del quale accennavo sopra.

    Last, but not least: si parla di C, non hanno attinenza metodi e classi del C++.
    Tutti gli utenti sono pregati di prendere visione del Regolamento del Forum e di rispettarlo.

    Sì, un blog ce l'ho perfino io: gli è che mi manca il tempo...

    • "Die ganzen Zahlen hat der liebe Gott gemacht, alles andere ist Menschenwerk." (Leopold Kronecker)
    • "A Mathematician is a machine for turning coffee into theorems." (Pal Erdös)
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

  10. #10
    Utente della community L'avatar di xardas
    reputazione complessiva: 5 5

    Messaggi
    230
    Beh, me la sono cercata... non avrei dovuto intromettermi
    Riguardo alla fscanf() e scanf() non sapevo fossero deprecate, le ho sempre usate senza problemi.

    Ad ogni modo l'ho voluta proporre perchè mi pare di aver capito che il problema di Simonemigliore sia che non riesce a caricare i numeri come formato int, ma solamente come carattere.

    Inoltre credo che i dati nel suo file file siano disposti ordinatamente, e il fatto di partire a leggere carattere per carattere rilevando gli spazi non sia per un fatto di 'parsing', ma una sorta di soluzione che a provato a mettere in atto non riuscendo a leggere direttamente i numeri come int.

    Non sono però sicuro di queste affermazioni, e come ho detto anche a fine del mio precedente post, aspettiamo conferma da parte di Simonemigliore ...

    Anche riguardo al linguaggio, avevo appunto notato che la discussione avesse preso piega sul C, ma dato che Simonemigliore non mi pare abbia specificato di stare programmando in C (ne da titolo, ne da suo primo post) ho pensato che non sarebbe stato un problema fornire soluzioni in parte di C++. (che si rivelano piuttosto comode)

    Ad ogni modo anche qui non sono sicuro, forse ho visto male io ...
    Da quel che ho capito poi questa discussione era stata attaccata in una del 2006, quindi forse era stato specificato prima che venisse correttamente tagliata.

    Spero solo che alcune soluzioni da me proposte possano tornare utili.
    Magari modificandole come ha suggerito M.A.W. 1968

    Non mi resta che augurarvi buona continuazione.
    Ciao !
    __________________________________________________ ___________________
    La programmazione è uno dei tanti modi di esprimere la propria creatività, ed è un'arte.

    In questo siamo comuni, dai pittori ai poeti, dagli scultori fino ai programmatori ...
    Di mente siamo completamente diversi, ma di anima siamo tutti CREATIVI

    Firmato :
    -Xardas Black Raven-

+ Rispondi
Pagina 1 di 2 1 2 UltimaUltima

Permessi di Scrittura

  • Tu non puoi inviare nuove discussioni
  • Tu non puoi inviare risposte
  • Tu non puoi inviare allegati
  • Tu non puoi modificare i tuoi messaggi