Uso dei file e array dinamici in C

di il
14 risposte

Uso dei file e array dinamici in C

Ciao, ho un problema sul seguente programma che ho realizzato per caricare dei dati da file CSV all'interno di un array di struct (un array di utenti caratterizzati da nome, cognome e anno di nascita)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_SIZE 15
#define SURNAME_SIZE 15
#define BUFFER_SIZE 1048

typedef struct{
    char nome[NAME_SIZE];
    char cognome[SURNAME_SIZE];
    int anno;
}Utente;

int caricaDatiDaFile(FILE*, Utente *utenti); //ritorna il numero di utenti caricati da file CSV, passo l'array di utenti per riferimento

int main()
{
    FILE *file;
    Utente *utenti;
    if( (file=fopen("nomi.csv", "r")) == NULL ){
        puts("Errore nell'apertura del file da leggere\n");
    }else{
        caricaDatiDaFile(file, utenti);
    }
    puts(utenti[1].cognome); //stampa di prova (non stampa nulla, stampa solo all'interno della funzione
    fclose(file);
    return 0;
}

int caricaDatiDaFile(FILE *file, Utente *utenti){
    utenti = calloc(1, sizeof(Utente)); //allocazione dinamica
    char *nome, *cognome, *anno_t;
    char buffer[BUFFER_SIZE];
    int anno, i = 0;
    while(fgets(buffer, BUFFER_SIZE, file) != NULL){ //parsificazione del file csv per ottenere i singoli campi (nome, cognome e anno di nascita)
        nome = strtok(buffer, ";");
        cognome = strtok(NULL, ";");
        anno_t = strtok(NULL, ";");
        anno = atoi(anno_t);
        strcpy(utenti[i].nome, nome);
        strcpy(utenti[i].cognome, cognome);
        utenti[i].anno = anno;
        i++;
        utenti = realloc(utenti, (i+1) * sizeof(Utente));
    }
    printf("Utenti caricati: %d\n", i);
    puts(utenti[1].cognome); //stampa di prova (funziona correttamente, nessun problema nella lettura del file csv
    return i;
}
quando provo a stampare un utente all'interno della funzione, tutto ok, ma se provo fuori dalla funzione, niente da fare. Ho sicuramente sbagliato il passaggio dell'array per riferimento, ma non riesco a capire cosa e ci sto sbattendo da giorni, grazie mille in anticipo

14 Risposte

  • Re: Uso dei file e array dinamici in C

    Se anche di fronte alla soluzione fornita nell'altro thread ancora non ti ci raccapezzi, la vedo dura...
  • Re: Uso dei file e array dinamici in C

    Sembra che tu non abbia capito che devi usare un doppio puntatore **
    Eppure nell'altro thread eri arrivato a questa conclusione...
  • Re: Uso dei file e array dinamici in C

    Non funziona neanche col doppio puntatore **

    in pratica, il problema originario l'ho avuto con questo programma, quell'altro programma di esempio l'ho usato solo per capire in generale come funzionasse il passaggio per riferimento per poi passare a questo sui file e applicare la stessa procedura

    il problema è che pur mettendo il doppio puntatore mi dà errore dicendomi "did you mean to use "->"?" all'interno della funzione, ma niente da fare anche così, ecco spiegato
  • Re: Uso dei file e array dinamici in C

    Infatti con il puntatore a struttura si usa ->, non il punto. Ristudiati bene i puntatori, poi riprovaci e posta il codice. Mi sa che non li hai capiti bene, perché insisti a chiamare i parametri con lo stesso nome delle variabili, quindi secondo me è meglio ripartire da zero, altrimenti al prossimo imprevisto sei di nuovo a piedi
  • Re: Uso dei file e array dinamici in C

    Va bene, grazie mille lo stesso
  • Re: Uso dei file e array dinamici in C

    Allora, ho fatto le stesse modifiche che avevo fatto sull'altro programma di esempio, ma niente da fare, ecco il codice aggiornato:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define NAME_SIZE 15
    #define SURNAME_SIZE 15
    #define BUFFER_SIZE 1048
    
    typedef struct{
        char nome[NAME_SIZE];
        char cognome[SURNAME_SIZE];
        int anno;
    }Utente;
    
    int caricaDatiDaFile(FILE*, Utente **utenti);
    
    int main()
    {
        FILE *file;
        Utente *utenti;
        int n;
        if( (file=fopen("nomi.csv", "r")) == NULL ){
            puts("Errore nell'apertura del file da leggere\n");
        }else{
            n = caricaDatiDaFile(file, &utenti);
        }
        puts(utenti[1].cognome); //stampa di prova
        fclose(file);
        return 0;
    }
    
    int caricaDatiDaFile(FILE *file, Utente **utenti){
        utenti = calloc(1, sizeof(Utente));
        char *nome, *cognome, *anno_t;
        char buffer[BUFFER_SIZE];
        int anno, i = 0;
        while(fgets(buffer, BUFFER_SIZE, file) != NULL){
            nome = strtok(buffer, ";");
            cognome = strtok(NULL, ";");
            anno_t = strtok(NULL, ";");
            anno = atoi(anno_t);
            strcpy(utenti[i]->nome, nome);
            strcpy(utenti[i]->cognome, cognome);
            utenti[i]->anno = anno;
            i++;
            utenti = realloc(utenti, (i+1) * sizeof(Utente));
        }
        printf("Utenti caricati: %d\n", i);
        return i;
    }
    Ho usato, come hai detto tu, un doppio puntatore e l'operatore -> nella funzione, ma la stampa di prova che vedi non va ugualmente, ci sto perdendo la testa
  • Re: Uso dei file e array dinamici in C

    Nell'altro esercizio vettore diventava (*vettore). Che succede qui ad utenti?
  • Re: Uso dei file e array dinamici in C

    Vabbé ti dò la soluzione e facciamo prima
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define NAME_SIZE 15
    #define SURNAME_SIZE 15
    
    typedef struct{
        char nome[NAME_SIZE];
        char cognome[SURNAME_SIZE];
        int anno;
    }Utente;
    
    int caricaDati(Utente ** output);
    
    int main(void){
        Utente *utenti;
        int n = caricaDati(&utenti);
        puts(utenti[1].cognome); //stampa di prova
        return 0;
    }
    
    int caricaDati(Utente ** output){
        (*output) = (Utente *)calloc(2, sizeof(Utente));
        const char *nome, *cognome;
        int anno;
        nome = "Mario";
        cognome = "Rossi";
        anno = 2000; 
        strcpy((*output)[0].nome, nome);
        strcpy((*output)[0].cognome, cognome);
        (*output)[0].anno = anno;    
        nome = "Guido";
        cognome = "Bianchi";
        anno = 2001; 
        strcpy((*output)[1].nome, nome);
        strcpy((*output)[1].cognome, cognome);
        (*output)[1].anno = anno;        
    
        printf("Utenti caricati: %d\n", 2);
        return 2;
    } 
  • Re: Uso dei file e array dinamici in C

    Grazie mille, quindi hai scritto

    strcpy((*output)[1].nome, nome);

    Perché "nome" è un puntatore al primo carattere della stringa, mentre con *output ti riferisci al valore della prima cella di quella stringa, giusto?
  • Re: Uso dei file e array dinamici in C

    Ascolta, ti stai perdendo veramente in un bicchiere d'acqua.

    Ripartendo dall'inizio:
    void funzione(int a){
        a = 42;
    }
    int main(void){
        int n = 0;
        funzione(n);
        printf("%d", n); //stampa di prova
        return 0;
    }
    Non funziona perché stai passando n ad a per valore. Per funzionare devi passare per riferimento con * e &
    void funzione(int * a){
         (* a) = 42;
    }
    int main(void){
        int n = 0;
        funzione(& n);
        printf("%d", n); //stampa di prova
        return 0;
    }
    Che cosa ti vieta di usare la stessa logica con un puntatore stesso?
    void funzione(int * a){
         a = (int *)calloc(1, sizeof(int));
         (* a) = 42;
    }
    int main(void){
        int *p;
        funzione(p);
        printf("%d", * p); //stampa di prova
        return 0;
    }
    Non funziona perché stai passando p ad a per valore. Per funzionare devi passare per riferimento con * e &
    void funzione(int * (*a)){
         (*a) = (int *)calloc(1, sizeof(int));
         (* (*a)) = 42;
    }
    int main(void){
        int *p;
        funzione(& p);
        printf("%d\n", * p); //stampa di prova
        return 0;
    }
  • Re: Uso dei file e array dinamici in C

    Ho capito e ti ringrazio, posso dirti che sicuramente sui puntatori adesso ho le idee più chiare e anche dal tuo codice ho capito come si fa

    continua a non funzionare quando uso i file csv, non so perché
    strcpy(*(utenti)[i].nome, nome);
    strcpy(*(utenti)[i].cognome, cognome);
    *(utenti)[i].anno = anno;
    penso che a sto punto sia solo un problema di sintassi
  • Re: Uso dei file e array dinamici in C

    Ma perché sposti le parentesi rispetto agli esempi mostrati? E dai
  • Re: Uso dei file e array dinamici in C

    lippolis2000 ha scritto:


    penso che a sto punto sia solo un problema di sintassi
    Errore da principianti

    La sintassi, a cui ti stai riferendo, ha DIRETTA CONSEGUENZA SULLA SEMANTICA: gli errori di sintassi che stai facendo SONO ERRORI DI SEMANTICA!!! Moooooolto peggio!

    Un errore di sintassi e' definire una variabile "pippo" e poi chiamarla "poppi". La SEMANTICA e' sempre la stessa (e' una variabile) MA hai sbagliato il nome (la SINTASSI).

    METTERE le parentesi nel modo sbagliato, usare un puntatore ad intero invece che un puntatore a puntatore ad intero e' SEMANTICA SBAGLIATA, NON SINTASSI

    Vedila cosi': se per te

    1) io do soldi a te
    2) tu dai soldi a me

    e' solo un problema di sintassi, io metto firma per la prima interpretazione

    (con il trucco)
  • Re: Uso dei file e array dinamici in C

    Oltre ai puntatori in generale, forse sarebbe utile anche una ripassatina alla precedenza degli operatori!
Devi accedere o registrarti per scrivere nel forum
14 risposte