RISOLTO Errori su scrittura e lettura di una struct su file

Pubblicità
Stato
Discussione chiusa ad ulteriori risposte.
E' sempre dovuto a quanto detto nell'altro topic; è causato dal new line. Cambia lo scanf in scanf(" %c"); e vedrai che funziona.



Questo dovrebbe essere corretto (a me compila e funziona):
C:
#include <stdio.h>

    typedef struct  {char nome[20];
                     char cognome[20];
                     char codFiscale[20];
                     int anni;
                     char sesso;
                    }studenti;
 

void putStruct(studenti*, FILE *pf);
void printStruct(studenti*, FILE *pf);

int main()
{
  studenti stud1;
    FILE *pf;

    printf("Inserire il nome: ");
    scanf("%s",stud1.nome);
    printf("Inserire il cognome: ");
    scanf("%s", stud1.cognome);
    printf("Inserire il codice fiscale: ");
    scanf("%s", stud1.codFiscale);
    printf("Inserire l'eta: ");
    scanf("%d", &stud1.anni);
    printf("Inserire il sesso: ");
    scanf(" %c", &stud1.sesso);

    pf=fopen("Archivio.txt", "w");
    if(pf)
    {
        putStruct(&stud1, pf);
        fclose(pf);
    }
    else
    {
        printf("Errore.");
    }

    pf=fopen("Archivio.txt", "r");
    if(pf)
    {
        printStruct(&stud1, pf);
        printf("%s\n", stud1.nome);
        printf("%s\n", stud1.cognome);
        printf("%s\n", stud1.codFiscale);
        printf("%d\n", stud1.anni);
        printf("%c\n", stud1.sesso);
        fclose(pf);
    }
    else
    {
        printf("Errore.");
    }

    return(0);
}

void putStruct(studenti *stud1, FILE *pf)
{
    fwrite(stud1,sizeof(stud1),1, pf);
}

void printStruct(studenti *stud1, FILE *pf)
{
    fread(stud1,sizeof(stud1),1, pf);
}



Che compilatore utilizzi? E quale versione?

Comunque non ti aspettare di aprire Archivio.txt con un editor di testo e vedere il contenuto "in chiaro".
Ok perfetto ora va.
Comunque utilizzo CodeBlocks 20.03
--- i due messaggi sono stati uniti ---
@DispatchCode Ora potrei chiederti una cosa?
C:
void putStruct(studenti *stud1, FILE *pf);
Questa é il prototipo della procedura (se non sbaglio). Vorrei capire il perche abbiamo messo quelle cose tra le parentesi. So che sono uno il puntatore a stud1 e l'altro il puntatore a pf, ma perche é cosi?

C:
putStruct(&stud1, pf);
Questo é invece il richiamo della procedura dentro il main. Ma anche qui ti chiedo il perche di quelle cose tra le tonde...
 
Ultima modifica:
Ok perfetto ora va.
Comunque utilizzo CodeBlocks 20.03
Quello però è l'IDE, non è il compilatore.

@DispatchCode Ora potrei chiederti una cosa?
C:
void putStruct(studenti *stud1, FILE *pf);
Questa é il prototipo della procedura (se non sbaglio). Vorrei capire il perche abbiamo messo quelle cose tra le parentesi. So che sono uno il puntatore a stud1 e l'altro il puntatore a pf, ma perche é cosi?

Si, il prototipo della funzione è la dichiarazione della funzione. Quando invece vai a scrivere il codice al suo interno, dove usi le parentesi graffe, allora la stai definendo.

In merito alla seconda domanda:

C:
void putStruct(studenti *stud1, FILE *pf)

Questo è il prototipo della funzione: vale a dire che stai dicendo che la funzione accetta due parametri, uno è un puntatore a una struct di tipo studenti (o meglio, il cui alias è studenti) e l'altro è un puntatore a FILE.
Puoi anche non specificare il nome (mi riferisco a stud1 e pf), è irrilevante. Quello che conta è il tipo.

C:
void putStruct(studenti *stud1, FILE *pf)
{

}

Quindi la funzione segue quanto indicato dal prototipo. Qui stud1 e pf sono variabili locali alla funzione (esistono solo qui dentro, al termine della funzione, non puoi più utilizzarle, perchè non esistono).

C:
putStruct(&stud1, pf);
Questo é invece il richiamo della procedura dentro il main. Ma anche qui ti chiedo il perche di quelle cose tra le tonde...
Considerando che la funzione accetta due parametri del tipo visto in precedenza, quando la chiami, dovrai passare un indirizzo di memoria di tipo "studenti" e un puntatore a FILE.

Ora, penso che il tuo dubbio sia "perchè usare una & quando come parametro c'è *?".
La risposta è semplice: la funzione ha come parametro un puntatore a studenti e un secondo parametro, che è un puntatore a FILE.
Queste due variabili sono dichiarate in questo modo:

C:
studenti stud1;
FILE *pf;

quindi una è una variabile chiamata stud1 di tipo studenti (che è una struct), e l'altra è un puntatore a FILE. Quindi, passandoli alla funzione vista prima, dovrai passare l'indirizzo di stud1 (che viene memorizzato in un puntatore) e "pf", che è già un puntatore.

Faccio notare che la "stud1" vista nel main non è la "stud1" presente nelle funzioni. Si tratta di variabili diverse, in quanto hanno scope differenti: si tratta di due variabili che hanno il nome uguale nel tuo codice sorgente, ma sono in realtà due indirizzi (locazioni) diverse di memoria.

Ora posso spiegarati perchè ti ho detto di usare un puntatore qui:

C:
void printStruct(studenti *stud1, FILE *pf)
{
    fread(stud1,sizeof(stud1),1, pf);
}

Considera sempre il codice di prima, rivisto, togliendo i puntatori a studenti:

C:
#include <stdio.h>

    typedef struct  {char nome[20];
                     char cognome[20];
                     char codFiscale[20];
                     int anni;
                     char sesso;
                    }studenti;
  

void putStruct(studenti, FILE *pf);
void printStruct(studenti, FILE *pf);

int main()
{
  studenti stud1;
    FILE *pf;

    printf("Inserire il nome: ");
    scanf("%s",stud1.nome);
    printf("Inserire il cognome: ");
    scanf("%s", stud1.cognome);
    printf("Inserire il codice fiscale: ");
    scanf("%s", stud1.codFiscale);
    printf("Inserire l'eta: ");
    scanf("%d", &stud1.anni);
    printf("Inserire il sesso: ");
    scanf(" %c", &stud1.sesso);

    pf=fopen("Archivio.txt", "w");
    if(pf)
    {
        putStruct(stud1, pf);
        fclose(pf);
    }
    else
    {
        printf("Errore.");
    }

    pf=fopen("Archivio.txt", "r");
    if(pf)
    {
        printStruct(stud1, pf);
        printf("%s\n", stud1.nome);
        printf("%s\n", stud1.cognome);
        printf("%s\n", stud1.codFiscale);
        printf("%d\n", stud1.anni);
        printf("%c\n", stud1.sesso);
        fclose(pf);
    }
    else
    {
        printf("Errore.");
    }

    return(0);
}


void putStruct(studenti stud1, FILE *pf)
{
    fwrite(&stud1,sizeof(stud1),1, pf);
}

void printStruct(studenti stud1, FILE *pf)
{
    fread(&stud1,sizeof(stud1),1, pf);
    stud1.anni = 123;
}

Come noti ho forzato l'età a 123 nella funzione printStruct.
Eseguendolo ottengo questo:
Codice:
Inserire il nome: nome
Inserire il cognome: cognome
Inserire il codice fiscale: sdfg
Inserire l'eta: 98
Inserire il sesso: n
nome
cognome
sdfg
98
n

Perchè l'età non è 123?

Eseguendo l'altra versione, ma mantenendo la modifica sugli anni in questo modo:
C:
void printStruct(studenti *stud1, FILE *pf)
{
    fread(stud1,sizeof(stud1),1, pf);
    stud1->anni = 123;
}

si ottiene:

Codice:
Inserire il nome: nome
Inserire il cognome: cognome
Inserire il codice fiscale: asdf
Inserire l'eta: 987 
Inserire il sesso: m
nome
cognome
asdf
123
m

Perchè questo? Proprio perchè stiamo usando un puntatore. Grazie al puntatore la "stud1" della funzione accede al medesimo indirizzo di memoria della "stud1" presente nel main, e in questo modo puoi alterare il valore di un membro e mantenere la modifica anche fuori (ovvero nel main).

Ci sarebbe altro da precisare, ma preferisco non aggiungere altro, per non farti fare confusione (a meno di tue domande specifiche, ovviamente).
 
Quello però è l'IDE, non è il compilatore.
Qual é la differenza? E come faccio a vedere il compilatore?
Perchè questo? Proprio perchè stiamo usando un puntatore. Grazie al puntatore la "stud1" della funzione accede al medesimo indirizzo di memoria della "stud1" presente nel main, e in questo modo puoi alterare il valore di un membro e mantenere la modifica anche fuori (ovvero nel main).
Quindi stiamo parlando di passaggio per indirizzo che si contrappone al passaggio per valore
 
Qual é la differenza? E come faccio a vedere il compilatore?
IDE sta per Integrated Development Environment. E' appunto un ambiente di sviluppo. Ti aiuta con il build del progetto oltre che analizzando problemi sintattici e tanto altro ancora.

Il compilatore è quello che al termine del processo, dopo al linker anche, trasforma il tuo codice sorgente in un codice eseguibile dalla CPU, che è il tuo file EXE se ti trovi su Windows.

Non conosco l'IDE che hai indicato, dovresti guardare nelle impostazioni e verificare che compilatore viene utilizzato. Non so se hai scaricato qualcosa prima di installare l'ambiente o se c'era qualcosa già incluso.

Quindi stiamo parlando di passaggio per indirizzo che si contrappone al passaggio per valore

Si, puoi vederlo così.

Io avrei usato
C:
fwrite(stud1,sizeof(studenti),1, pf);
specificando la sizeof della struttura, e non quella di stud1 (che e' un puntatore)
Giusto, svista mia.
 
IDE sta per Integrated Development Environment. E' appunto un ambiente di sviluppo. Ti aiuta con il build del progetto oltre che analizzando problemi sintattici e tanto altro ancora.

Il compilatore è quello che al termine del processo, dopo al linker anche, trasforma il tuo codice sorgente in un codice eseguibile dalla CPU, che è il tuo file EXE se ti trovi su Windows.

Non conosco l'IDE che hai indicato, dovresti guardare nelle impostazioni e verificare che compilatore viene utilizzato. Non so se hai scaricato qualcosa prima di installare l'ambiente o se c'era qualcosa già incluso.
Se ho visto bene il compiler dovrebbe essere "GNU GCC Compiler".
E omunque si, quando ho installato codeblocks ho installato pure altro, sicuramente c'era il compiler dentro...
 
Stato
Discussione chiusa ad ulteriori risposte.
Pubblicità
Pubblicità
Indietro
Top