Perché il risultato di questo programma è sempre zero? [duplicare]

Oct 02 2020

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

5 AsteroidsWithWings Oct 02 2020 at 19:02

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.

1 P__JsupportswomeninPoland Oct 02 2020 at 19:09

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

1 JohnBode Oct 02 2020 at 19:20

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
}
MohitSharma Oct 02 2020 at 19:12

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