Acquisizione di un file csv in C

di il
6 risposte

Acquisizione di un file csv in C

Ciao...sono nuovo della programmazione e avrei il seguente problema:
realizzare in C un programmino che mi legga un file excel (esportato con csv) e inserisca i campi delle celle in una matrice.

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {

FILE *fp;
if(argc!=2) {
printf("Hai dimenticato di inserire il nome.\n");
exit(1);
}
if ((fp = fopen(argv[1],"r"))==NULL) {
printf("impossibile aprire il file.\n");
exit(1);
}

adesso non so come proseguire...pensavo di leggere come stringhe le righe del csv (con fgets) e poi individuare e incasellare i campi...come mi consigliate di procedere??..grazie

6 Risposte

  • Re: Acquisizione di un file csv in C

    Ciao,

    La cosa probabilmente più semplice è leggere singolarmente le righe con fgets e poi separare i campi utilizzando la strtok().

    La funzione in questione la puoi chiamare in un ciclo e restituirà un puntatore ai vari token (gli fornisci una lista di delimitatori - nel caso dei csv sarà il carattere ',' ) e NULL quando avrà terminato il parsing... la stringa originale viene modificata (i delimitatori vengono sostituiti da un \0 e viene ritornato il puntatore alla sottostringa così creata). Col token ottenuto (sarà ovviamente una stringa) poi puoi operare una conversione numerica (con atoi, atof ecc) o qualsiasi altra operazione ti interessi...

    Per maggiori informazioni ti rimando ad MSDN (su cd oppure online ad ), in cui puoi trovare anche un semplice esempio di utilizzo.

    Ciaociao
  • Re: Acquisizione di un file csv in C

    Grazie bottomap!!...sono riuscito in parte a risolvere:
    
    #include<stdlib.h>
    #include<stdio.h>
    #include<string.h>
    
    int main(int argc, char *argv[]) {
    
    FILE *fp;
    char buf[100];
    char *res;
    char *a;
    char *mat[3][4];
    int i=0;
    int j; 
    char del[]=",";
    
    if(argc!=2) {
        printf("Hai dimenticato di inserire il nome.\n");
        exit(1);
    }
    if ((fp = fopen(argv[1],"r"))==NULL) {
        printf("impossibile aprire il file.\n");
        exit(1);
    }
    while(1) {
        res=fgets(buf, 100, fp);
        if( res==NULL )
            break;
        printf("%s", buf);
        a=strtok(buf,del);
        mat[i][0]=a;
        printf("\n\n %s", mat[i][0]);
        for (j=1;j<4;j++) {
             a=strtok(NULL,del);
             mat[i][j]=a;
             printf("\n\n %s", mat[i][j]);                
        }
        i++; 
    }
    for (i=0;i<3;++i) {
        for (j=0;j<4;++j) {
            printf(" %3s",mat[i][j]);   
        } 
        printf("\n");
    }
    fclose(fp);
    return 0;
    }
    
    non riesco a capire perche la visualizzazione finale non funziona, ma quella all'interno del ciclo while si...ovvero alla fine la matrice non è corretta...
  • Re: Acquisizione di un file csv in C

    Mi spiego meglio...

    ho provato a utilizzare un csv di esempio:
    
    ds,h,y,u
    fs,g,t,o
    fg,hhg,i,sa3
    
    l'output proveniente dal ciclo while è correttamente:
    
    ds,h,y,u
    ds
    h
    y
    u
    
    fs,g,t,o
    fs
    g
    t
    o
    
    fg,hhg,i,sa3
    fg
    hhg
    i
    sa3
    
    ma quando uso i cicli for per la visualizzazione ho:
    
    fg hhg g  i
    fg hhg g  i
    fg hhg i  sa3
    
    quindi la matrice non è quella che dovrebbe essere...non capisco perchè
  • Re: Acquisizione di un file csv in C

    Ciao,

    Ti è sfuggito probabilmente quanto ti ho detto nel post... la strtok non crea stringhe, restituisce puntatori all'interno del buffer, pertanto se il contenuto del buffer cambia (a seguito di una fget) i precedenti puntatori fanno riferimento al nuovo contenuto...

    Se hai necessità di salvarti i token da qualche parte dovrai copiarli in stringhe separate (allocate alla bisogna)... oppure usare buf separati per le fgets. In entrambi i casi avrai bisogno di un contenitore di supporto (uno std::vector sarebbe ottimo, altrimenti una semplice lista).

    La cosa più semplice (benché provochi una certa frammentazione nella memoria) mi pare invece una cosa del genere:
    a=strtok(...,...);
    char *nuova=new char[strlen(a)+1]; // o malloc in caso
    strcpy(nuova,a);
    mat[..][..]=nuova;

    Ricordando però che al termine dell'utilizzo dovrai liberare la memoria in questione con l'opportuna delete (o free) sui singoli elementi della matrice.

    Ciaociao
  • Re: Acquisizione di un file csv in C

    bottomap ha scritto:


    Ciao,

    Ti è sfuggito probabilmente quanto ti ho detto nel post... la strtok non crea stringhe, restituisce puntatori all'interno del buffer, pertanto se il contenuto del buffer cambia (a seguito di una fget) i precedenti puntatori fanno riferimento al nuovo contenuto...

    Se hai necessità di salvarti i token da qualche parte dovrai copiarli in stringhe separate (allocate alla bisogna)... oppure usare buf separati per le fgets. In entrambi i casi avrai bisogno di un contenitore di supporto (uno std::vector sarebbe ottimo, altrimenti una semplice lista).

    La cosa più semplice (benché provochi una certa frammentazione nella memoria) mi pare invece una cosa del genere:
    a=strtok(...,...);
    char *nuova=new char[strlen(a)+1]; // o malloc in caso
    strcpy(nuova,a);
    mat[..][..]=nuova;

    Ricordando però che al termine dell'utilizzo dovrai liberare la memoria in questione con l'opportuna delete (o free) sui singoli elementi della matrice.

    Ciaociao
    Ti ringrazio...alla fine ho utilizzato malloc...un'ultima cosa poi non rompo più ...non sono sicuro di aver utilizzato correttamente free..
    
    ...
    for (i=0;i<x;++i) {
        for (j=0;j<y;++j) {
            free(mat[i][j]);
        } 
    }
    
    grazie ancora...ciaoooo
  • Re: Acquisizione di un file csv in C

    Ciao,

    Si, può andare più che bene... se ogni singolo elemento della matrice lo hai allocato con una malloc, la cosa giusta da fare è proprio quella doppia for con la free degli elementi (che ovviamente non andranno più usati dopo tale operazione).

    Ciaociao
Devi accedere o registrarti per scrivere nel forum
6 risposte