Por que o resultado deste programa é sempre zero? [duplicado]

Oct 02 2020

Estou tentando escrever um programa simples que receba notas, nomes e carteiras de no máximo 30 alunos e imprima a média de suas notas. Fiquei me perguntando por que o resultado do programa é sempre zero.
Agradeço se alguém puder me deixar uma dica.
Aqui está o código:

#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);
}

Respostas

5 AsteroidsWithWings Oct 02 2020 at 19:02

O especificador de formato %sdiz para ler uma string, e está fazendo isso ... incluindo vírgulas e caracteres subsequentes. É "ganancioso".

Então não há mais nada para %dser absorvido pelo, então todos os inteiros permanecem zero.

Eu sugiro que você leia uma linha de cada vez e, em seguida, analise as linhas.

Como alternativa, existem algumas sugestões sobre esta questão semelhante .


Ao se deparar com um problema como este, você deve tentar restringi-lo examinando os valores das variáveis ​​em seu depurador, ou mesmo apenas usando printf, assim:

    printf("%s|%d|%d\n", s[i].name, s[i].mark, s[i].ID);

Quando coloco isso em seu primeiro loop e passo a seguinte entrada para o programa:

2
A,2,3
B,4,5

... a saída é esta :

A,2,3|0|0
B,4,5|0|0
0.00

… O que mostra claramente que a análise é o problema.

1 P__JsupportswomeninPoland Oct 02 2020 at 19:09

o problema está nesta linha:

scanf("%s,%d,%d",s[i].name,&s[i].mark,&s[i].ID);

não vai funcionar como você pensa. Para testá-lo, alterei seu programa.

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

O que você precisa fazer? Você precisa ler a linha da baleia com fgetse escrever o analisador que irá separar esta string

VERIFIQUE SEMPRE O RESULTADO DO SCANF

1 JohnBode Oct 02 2020 at 19:20

Se você está tentando inserir nomes com espaços, como

Joe Smith,90,1234

então o problema é que o %sespecificador de conversão para de ler no primeiro caractere de espaço em branco, então ele lê "Joe"e sai "Smith"no fluxo de entrada, o que atrapalha as próximas duas leituras. Alternativamente, se você não tiver nenhum espaço, %sleia toda a linha de entrada name(se ela se ajusta ou não, potencialmente levando a um estouro de buffer).

Você deve usar o %[especificador de conversão em vez de %sdimensioná-lo explicitamente para evitar o risco de um estouro de buffer. Você também deve verificar o valor de retorno de scanfpara ter certeza de ler todos os 3 itens corretamente:

/**
 * 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

Seu problema está ,noscanf("%s,%d,%d",s[i].name,&s[i].mark,&s[i].ID);

Mudei o código da seguinte maneira:

scanf("%s%d%d",s[i].name,&s[i].mark,&s[i].ID);

então a entrada e a saída eram como: INPUT:

2
moh 1 2
test 2 3

RESULTADO:

1.50