File sequenziale
Salve ragazzi, avevo già postato questo esercizio tempo fa e credevo seriamente di aver risolto tutti i problemi ma purtroppo non è stato così, vi scrivo traccia e svolgimento e anche l'errore che mi da cygwin durante l'esecuzione.
Volevo fare anche un altra domanda riguardante i sottoprogrammi : i parametri effettivi e i parametri formali sono definiti come variabili in ingresso, in uscita o di algoritmo?
foto errore
Volevo fare anche un altra domanda riguardante i sottoprogrammi : i parametri effettivi e i parametri formali sono definiti come variabili in ingresso, in uscita o di algoritmo?
foto errore
Risposte
L'errore di segmentazione indica un accesso errato alla memoria, ed è causato dalla linea 31:
mentre invece dovrebbe essere
Devi scrivere nelle variabili matricola, giorni, voto, quindi a fscanf() devi passare il loro indirizzo.
Invece alle linee 14 e 16 non devi passare l'indirizzo di nome e cognome, poiché sono array e decadono automaticamente in puntatori.
L'altro problema invece, quello che salta alcune domande, riguarda il fatto che scanf() non legge correttamente il carattere di newline \n. Non sono sicuro di come funzioni esattamente perché non uso mai il runtime C, però potresti semplicemente leggere un campo e poi scartare tutto l'input fino a leggere un \n:
Quel while devi metterlo dopo ogni chiamata a scanf(). In alternativa ho visto molte volte consigliare di leggere un'intera linea con getline() e poi passarla a sscanf().
Il programma corretto è:
fscanf(Fmio,"%s %s %d %d %d\n",nome,cognome,matricola,giorni,voto);
mentre invece dovrebbe essere
fscanf(Fmio,"%s %s %d %d %d\n",nome,cognome,& matricola,& giorni,& voto);
Devi scrivere nelle variabili matricola, giorni, voto, quindi a fscanf() devi passare il loro indirizzo.
Invece alle linee 14 e 16 non devi passare l'indirizzo di nome e cognome, poiché sono array e decadono automaticamente in puntatori.
// No scanf("%s\n",&nome); scanf("%s\n",&cognome); // Sì scanf("%s\n",nome); scanf("%s\n",cognome);
L'altro problema invece, quello che salta alcune domande, riguarda il fatto che scanf() non legge correttamente il carattere di newline \n. Non sono sicuro di come funzioni esattamente perché non uso mai il runtime C, però potresti semplicemente leggere un campo e poi scartare tutto l'input fino a leggere un \n:
scanf("%s",nome); while(getchar()!= '\n'); // Nota il punto e virgola!
Quel while devi metterlo dopo ogni chiamata a scanf(). In alternativa ho visto molte volte consigliare di leggere un'intera linea con getline() e poi passarla a sscanf().
Il programma corretto è:
#include<stdio.h> int main ( ) { FILE*Fmio; char nome[20],cognome[20]; int matricola,giorni,voto,n,i; Fmio=fopen("file1.txt","w"); //apre file in scrittura printf("Quanti allievi vuoi inserire?\n"); scanf("%d",&n); for (i=0;i<n;i++) { printf("nome:"); scanf("%s",nome); while(getchar()!= '\n'); printf("cognome:"); scanf("%s",cognome); while(getchar()!= '\n'); printf("matricola:"); scanf("%d",&matricola); while(getchar()!= '\n'); printf("giorni:"); scanf("%d",&giorni); while(getchar()!= '\n'); printf("voto:"); scanf("%d",&voto); while(getchar()!= '\n'); fprintf(Fmio,"%s %s %d %d %d\n",nome,cognome,matricola,giorni,voto); } printf("FINE SALVATAGGIO\n"); fclose(Fmio); Fmio=fopen("file1.txt","r"); do { fscanf(Fmio,"%s %s %d %d %d\n",nome,cognome,&matricola,&giorni,&voto); printf("nome=%s \n", nome); printf("cognome=%s \n", cognome); printf("matricola=%d \n", matricola); printf("giorni=%d \n", giorni); printf("voto=%d \n", voto); } while(!feof(Fmio)); fclose(Fmio); }
ti ringrazio per la risposta non esiste un altro metodo oltre "while(getchar()!='\n');" ? perchè non l'abbiamo mai utilizzato a lezione, per il resto ti ringrazio di tutto ora mi è chiarissimo

L'unico altro modo che conosco è usare getline() + sscanf(), qua un esempio. Però non sono molto ferrato con il runtime C, magari qualcuno ha un'altra soluzione.
Ti ringrazio , sei stato super gentile . Per quanto riguarda la domanda sui sottoprogrammi
"Volevo fare anche un altra domanda riguardante i sottoprogrammi : i parametri effettivi e i parametri formali sono definiti come variabili in ingresso, in uscita o di algoritmo?"
non riesci a darmi una mano ?
grazie ancora
"Volevo fare anche un altra domanda riguardante i sottoprogrammi : i parametri effettivi e i parametri formali sono definiti come variabili in ingresso, in uscita o di algoritmo?"
non riesci a darmi una mano ?

grazie ancora
Non sono sicuro di come interpretare la domanda. Parametri formali sono i parametri che una funzione dichiara di accettare, i parametri effettivi sono quelli che le vengono effettivamente passati. Nell'esempio i parametri formali sono a e b, quelli effettivi sono una volta c e d, un'altra 767 e f.
Probabilmente la risposta è che i parametri effettivi sono quelli in ingresso all'algoritmo, mentre quelli formali sono interni all'algoritmo.
Se invece la domanda riguarda parametri di ingresso e uscita nelle funzioni: parametri in ingresso contengono dati che verranno usati dalla funzione, parametri in uscita conterranno dati prodotti dalla funzione (dopo la chiamata), parametri in ingresso e uscita entrambi.
Spesso i parametri sono in ingresso, oppure sia in ingresso che in uscita, però alcuni linguaggi supportano anche parametri di sola uscita. Esempio nel linguaggio D:
In C++ si possono usare i riferimenti, che sono di ingresso e uscita:
Il linguaggio C invece supporta solamente parametri in ingresso. Però usando i puntatori si può ottenere lo stesso risultato.
int gcd(int a, int b) { // Calcola il massimo comun divisore. while (b != 0) { int t = b; b = a % b; a = t; } return a; } int main() { int c = 1974, d = 45769; int r = gcd(c, d); // Il risultato è nella variabile r. } void altrafunzione() { ... int f = 7684; int r = gcd(767, f); // Il risultato è nella variabile r. }
Probabilmente la risposta è che i parametri effettivi sono quelli in ingresso all'algoritmo, mentre quelli formali sono interni all'algoritmo.
Se invece la domanda riguarda parametri di ingresso e uscita nelle funzioni: parametri in ingresso contengono dati che verranno usati dalla funzione, parametri in uscita conterranno dati prodotti dalla funzione (dopo la chiamata), parametri in ingresso e uscita entrambi.
Spesso i parametri sono in ingresso, oppure sia in ingresso che in uscita, però alcuni linguaggi supportano anche parametri di sola uscita. Esempio nel linguaggio D:
void gcd(int a, int b, out int result) { while (b != 0) { int t = b; b = a % b; a = t; } result = a; } void main() { int c = 1974, d = 45769; int r; gcd(c, d, r); // Il risultato è nella variabile r. }
In C++ si possono usare i riferimenti, che sono di ingresso e uscita:
void gcd(int a, int b, int & result) { while (b != 0) { int t = b; b = a % b; a = t; } result = a; } int main() { int c = 1974, d = 45769; int r; // Warning. r non è stato inizializzato, se la funzione gcd() legge il suo valore // il comportamento è indefinito. gcd() non lo fa, però sarebbe meglio inizializzare // r a qualcosa. gcd(c, d, r); // Il risultato è nella variabile r. }
Il linguaggio C invece supporta solamente parametri in ingresso. Però usando i puntatori si può ottenere lo stesso risultato.
void gcd(int a, int b, int * result) { while (b != 0) { int t = b; b = a % b; a = t; } *result = a; } int main() { int c = 1974, d = 45769; int r; // Stesso problema del C++. gcd(c, d, & r); // Il risultato è nella variabile r. }
Sei stato chiarissimo e hai risposto a pieno alla mia domanda, ti ringrazio
Volevo porti un ulteriore domdanda, nel caso dell'esericizio con i file sequenziale (che ho risolto) le variabili in uscita coincidono con quelle in entrata ?
Per i parametri del sottoprogramma invece nel tuo esempio la variabile "gdc" come la definisci in ingresso, in uscita o di algoritmo ?
Per i parametri del sottoprogramma invece nel tuo esempio la variabile "gdc" come la definisci in ingresso, in uscita o di algoritmo ?
"frenky46":
Volevo porti un ulteriore domdanda, nel caso dell'esericizio con i file sequenziale (che ho risolto) le variabili in uscita coincidono con quelle in entrata ?
Per l'intero esercizio non ha molto senso. Per la fase di scrittura dell'elenco sui file le variabili sono l'elenco e il nome del file, entrambe in ingresso. Per la lettura le variabili sono ancora l'elenco e il nome del file, ma l'elenco è in uscita. Per la fase di stampa l'elenco è variabile di ingresso.
In sostanza, vedi un algoritmo come una funzione a cui passi delle variabili:
- Le variabili il cui valore viene usato dall'algoritmo sono di ingresso.
- Le variabili il cui valore viene modificato dall'algoritmo (e la modifica è visibile al chiamante) sono di uscita.
- Le variabili il cui valore viene sia usato sia modificato sono di ingresso e uscita.
- Le variabili il cui valore non viene né usato né modificato sono inutili.
"frenky46":
Per i parametri del sottoprogramma invece nel tuo esempio la variabile "gdc" come la definisci in ingresso, in uscita o di algoritmo ?
Nel mio esempio "gcd" non è una variabile. È un nome di funzione, quindi è un valore, come 4, 9.4 o "abcd". Le variabili "a" e "b" sono di ingresso e la variabile "result" è di uscita (in linea di principio, poi come detto non tutti i linguaggi supportano variabili solo di uscita).