RISOLTO Errori su scrittura e lettura di una struct su file

Stato
Discussione chiusa ad ulteriori risposte.

Vito-

Utente Attivo
184
14
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
Post unito automaticamente:

@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:

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
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).
 

Vito-

Utente Attivo
184
14
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
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
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.
 

Vito-

Utente Attivo
184
14
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.

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili