Perché il risultato di questo programma è sempre zero? [duplicare]
Sto cercando di scrivere un semplice programma che riceva voti, nomi e ID di massimo 30 studenti e stampi la media dei loro voti. Mi chiedevo perché il risultato del programma è sempre zero.
Apprezzo se qualcuno potesse lasciarmi un suggerimento.
Ecco il codice:
#include <stdio.h>
struct student{
char name[30];
int mark;
int ID;
} s[30];
int main() {
int n, i=0, sum=0;
float average;
/* printf("enter the number of students: "); */
scanf("%d", &n);
/* printf("enter their information: "); */
for(i=0; i<n; i++)
scanf("%s,%d,%d",s[i].name,&s[i].mark,&s[i].ID);
for(i=0; i<n; i++)
sum+=s[i].mark;
average=sum/(float)n ;
printf("%.2f", average);
}
Risposte
L'identificatore di formato %sdice di leggere una stringa, e lo sta facendo ... comprese le virgole e i caratteri successivi. È "goloso".
Quindi non c'è più nulla %dda assorbire, quindi tutti gli interi rimangono zero.
Ti suggerisco di leggere una riga alla volta, quindi analizzare le righe.
In alternativa, ci sono alcuni suggerimenti su questa domanda simile .
Di fronte a un problema come questo, dovresti tentare di restringerlo esaminando i valori delle variabili nel tuo debugger, o anche semplicemente usando printf, in questo modo:
printf("%s|%d|%d\n", s[i].name, s[i].mark, s[i].ID);
Quando lo metto nel primo ciclo e passo il seguente input al programma:
2
A,2,3
B,4,5
... l'output è questo :
A,2,3|0|0
B,4,5|0|0
0.00
... il che mostra chiaramente che il problema è l'analisi.
il problema è in questa linea:
scanf("%s,%d,%d",s[i].name,&s[i].mark,&s[i].ID);
non funzionerà come pensi. Per provarlo ho modificato il tuo programma.
int main() {
int n = 10, i=0, sum=0;
int scanfResult;
float average;
/* printf("enter the number of students: "); */
//scanf("%d", &n);
/* printf("enter their information: "); */
for(i=0; i<n; i++)
{
scanfResult = scanf("%s,%d,%d",s[i].name,&s[i].mark,&s[i].ID);
printf("scanf has scanned %d items\n", scanfResult);
if(scanfResult != 3)
{
printf("you need to find another way of entering the data\n");
exit(1);
}
}
for(i=0; i<n; i++)
sum+=s[i].mark;
average=sum/(float)n ;
printf("%.2f", average);
}
https://godbolt.org/z/PredEd
Cosa devi fare? Devi leggere la linea della balena con fgetse scrivere il parser che dividerà questa stringa
CONTROLLARE SEMPRE IL RISULTATO DELLO SCANF
Se stai cercando di inserire nomi con spazi, ad esempio
Joe Smith,90,1234
quindi il problema è che lo %sspecificatore di conversione smette di leggere al primo carattere di spazio bianco, quindi legge "Joe"e lascia "Smith"il flusso di input, che annulla le due letture successive. In alternativa, se non si dispone di spazi, %slegge l'intera riga di input name(indipendentemente dal fatto che si adatti o meno, potenzialmente portando a un overflow del buffer).
Dovresti usare lo %[specificatore di conversione invece di %sridimensionarlo esplicitamente per evitare di rischiare un overflow del buffer. Dovresti anche controllare il valore di ritorno di scanfper assicurarti di leggere correttamente tutti e 3 gli elementi:
/**
* loop until we have three good inputs;
* %29[^,] reads up to 29 characters or to the next comma;
* An array of size 30 can store a string of up to
* 29 characters plus the string terminator;
* Added leading blank in the format string to consume
* any leading whitespace.
*/
while ( scanf( " 29%[^,],%d,%d", s[i].name, &s[i].mark, &s[i].ID) != 3 )
{
fprintf(stderr, "Bad input, try again\n" );
/**
* clear out the input stream before trying again
*/
while ( getchar() != '\n' )
; // empty loop body
}
Il tuo problema è ,nel filescanf("%s,%d,%d",s[i].name,&s[i].mark,&s[i].ID);
Ho cambiato il codice come segue:
scanf("%s%d%d",s[i].name,&s[i].mark,&s[i].ID);
quindi input e output erano come: INPUT:
2
moh 1 2
test 2 3
PRODUZIONE:
1.50