MasterDrive.it   
Vai indietro   MasterDrive.it > Software Development > C/C++



Rispondi
 
Strumenti della discussione Modalità di visualizzazione
Vecchio 23-01-2010, 18:19   #1 (permalink)
Nuovo della community

 
7 Messaggi

Simonemigliore novizio della comunita' ( + 10 )
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

Simonemigliore non è in linea   Bookmark and Share Rispondi quotando
Vecchio 23-01-2010, 18:31   #2 (permalink)
Moderatore Globale

 L'avatar di M.A.W. 1968

 
319 Messaggi

M.A.W. 1968 e' una persona affidabile ( + 250 )M.A.W. 1968 e' una persona affidabile ( + 250 )M.A.W. 1968 e' una persona affidabile ( + 250 )
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.

• "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.
M.A.W. 1968 non è in linea   Bookmark and Share Rispondi quotando
Vecchio 23-01-2010, 18:33   #3 (permalink)
Nuovo della community

 
7 Messaggi

Simonemigliore novizio della comunita' ( + 10 )
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 a 18:48.
Simonemigliore non è in linea   Bookmark and Share Rispondi quotando
Vecchio 23-01-2010, 19:47   #4 (permalink)
Nuovo della community

 
7 Messaggi

Simonemigliore novizio della comunita' ( + 10 )
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");   
}
Simonemigliore non è in linea   Bookmark and Share Rispondi quotando
Vecchio 23-01-2010, 20:20   #5 (permalink)
Moderatore Globale

 L'avatar di M.A.W. 1968

 
319 Messaggi

M.A.W. 1968 e' una persona affidabile ( + 250 )M.A.W. 1968 e' una persona affidabile ( + 250 )M.A.W. 1968 e' una persona affidabile ( + 250 )
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.

• "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.
M.A.W. 1968 non è in linea   Bookmark and Share Rispondi quotando
Vecchio 23-01-2010, 20:40   #6 (permalink)
Nuovo della community

 
7 Messaggi

Simonemigliore novizio della comunita' ( + 10 )
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 a 01:20.
Simonemigliore non è in linea   Bookmark and Share Rispondi quotando
Vecchio 24-01-2010, 03:24   #7 (permalink)
Moderatore Globale

 L'avatar di M.A.W. 1968

 
319 Messaggi

M.A.W. 1968 e' una persona affidabile ( + 250 )M.A.W. 1968 e' una persona affidabile ( + 250 )M.A.W. 1968 e' una persona affidabile ( + 250 )
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.

• "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.
M.A.W. 1968 non è in linea   Bookmark and Share Rispondi quotando
Vecchio 24-01-2010, 12:49   #8 (permalink)
Utente della community

 L'avatar di xardas

 
219 Messaggi

xardas novizio della comunita' ( + 10 )
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
__________________
__________________________________________________ ___________________
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-

Ultima modifica di xardas : 24-01-2010 a 13:33.
xardas non è in linea   Bookmark and Share Rispondi quotando
Vecchio 24-01-2010, 17:39   #9 (permalink)
Moderatore Globale

 L'avatar di M.A.W. 1968

 
319 Messaggi

M.A.W. 1968 e' una persona affidabile ( + 250 )M.A.W. 1968 e' una persona affidabile ( + 250 )M.A.W. 1968 e' una persona affidabile ( + 250 )
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.

• "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.
M.A.W. 1968 non è in linea   Bookmark and Share Rispondi quotando
Vecchio 25-01-2010, 12:55   #10 (permalink)
Utente della community

 L'avatar di xardas

 
219 Messaggi

xardas novizio della comunita' ( + 10 )
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-
xardas non è in linea   Bookmark and Share Rispondi quotando
Rispondi

Strumenti della discussione
Modalità di visualizzazione

Regole d'invio
Non puoi inserire discussioni
Non puoi inserire repliche
Non puoi inserire allegati
Non puoi modificare i tuoi messaggi

BB code è attivo
Le smilies sono attive
Il codice IMG è attivo
il codice HTML è disattivato
Trackbacks are attivo
Pingbacks are attivo
Refbacks are disattivato

Salto del forum


Tutti gli orari sono GMT +1. Attualmente sono le 17:36.


Powered by vBulletin versione 3.8.0
Copyright © 2000 - 2010, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.2.0

Valid XHTML 1.0 Transitional  Creative Commons License

Eccetto dove diversamente specificato, i contenuti pubblicati in questa comunità sono rilasciati sotto Licenza
Creative Commons Attribuzione-Non commerciale-Condividi allo stesso modo 2.5 Italia License.
La comunita' di MasterDrive.it non e' responsabile di eventuali imprecisioni presenti nelle pagine.