Solicitação de algoritmo 4
Solicitação recebida de Caio da Silva Caetano. O problema encontrado no código dele é que a execução do código não gerava a média correta. Segue o enunciado e o código enviado.
Enunciado: fazer um programa para obter o nome e as 2 notas dos 28 alunos de uma turma. As notas serão informadas pelo professor. O programa deve calcular a média das 2 notas de cada aluno e exibir “Aprovado” caso a média seja igual ou superior a 7.0 e reprovado, caso contrário. Armazenar os valores em variável vetorial.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#include <stdio.h> #include <string.h> #include <stdlib.h> char vetor [3][3][28]; int main(void) { float nota1; float nota2; float media; int i,j; char nome[28]; for(i=0;i<3;i++){ printf("\nEntre com o nome do aluno: "); fflush(stdin); gets(vetor[i][0]); for(j=1;j<3;j++){ printf("Informe a %da. nota:",j); fflush(stdin); gets(vetor[i][j]); } } for(i=0;i<3;i++){ nota1=atof(vetor[i][1]);nota2=atof(vetor[i][2]);; media = (nota1 + nota2 ) / 2; printf("\nMedia final = %.2f", media); if (media >= 7.0) printf(" ( aluno %s aprovado ).",vetor[i][0]); else if ((media >= 4.0) && (media < 7.0)) printf(" ( aluno %s em recuperacao ).",vetor[i][0]); else printf(" ( aluno %s reprovado ).",vetor[i][0]); } getch(); } |
O código enviado mostra que foi pensado em utilizar uma matriz tridimensional para armazenar os alunos e suas notas. Como a matriz somente pode ser de um tipo e ela armazena dados numéricos e alfanuméricos, foi decidido corretamente em criar uma matriz de caracteres. Obviamente, ao armazenar os números nela, foi necessário fazer a conversão deles posteriormente para os cálculos.
Aqui vem uma primeira recomendação. A matriz criada é 3x3x28 e fica óbvio que uma dimensão de tamanho 3 é para guardar as 2 notas e o nome do aluno, outra dimensão de tamanho 3 é porque o algoritmo cumpre o enunciado apenas para 3 alunos (e não 28 como é pedido) e a dimensão de tamanho 28 se refere ao tamanho máximo do nome do aluno. Veja que esse tamanho 28 se confunde com o número de alunos do enunciado e por isso eu colocaria outro valor (eu coloquei o tamanho 30 no meu código). Também recomendo especificar o número de alunos como uma constante, para depois alterar somente o valor da constante e ter o meu código funcionando para 3 alunos durante os testes e 28 alunos para a conclusão do algoritmo.
Outra coisa é o uso da função gets(). É comum os compiladores mostrarem um warning ao utilizar essa função. Isso porque, se for informado um nome maior do que o definido (no caso, um nome com mais de 27 letras – isso porque o último caractere de uma string deve ser o ‘\0’), isso gerará um overflow do buffer (estouro de buffer). Uma função alternativa e que previne essa possibilidade de falha é a função fgets(). Muitos usam a função gets() porque aparece em material mais antigo sobre a linguagem C e também porque precisa receber apenas de um parâmetro (no caso, a variável a ser lida), mas a fgets() não é tão mais difícil de utilizar.
Para a função fgets(), informe a variável string a ser lida, o tamanho da string a ser lida e, considerando a entrada padrão (normalmente o teclado), o parâmetro stdin. No código do caso ficará fgets(vetor[i][0], 29, stdin). Lembrando que o tamanho 29 é porque o tamanho da variável para o nome está em é 30, mas é preciso deixar um caractere para receber o ‘\0’.
Veja que eu inicialmente fiz recomendações de melhorias. Agora vamos falar sobre o erro. Veja que no código foi corretamente utilizada a função atof() para converter a string no número.
Alterando o código para funcionar com a constante e a função fgets() teremos pouca diferença do anterior, mas ele segue a seguir. Eu também tirei a variável de nome vetor do escopo global e coloquei no escopo local porque não faz sentido ela no escopo global.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include <stdio.h> #include <string.h> #include <stdlib.h> #define ALUNOS 3 int main(void) { float nota1; float nota2; float media; char vetor [ALUNOS][3][30]; int i,j; //char nome[30]; --remover porque não é utilizada for(i=0;i<ALUNOS;i++){ printf("\nEntre com o nome do aluno: "); fflush(stdin); fgets(vetor[i][0],29,stdin); for(j=1;j<3;j++){ printf("Informe a %da. nota:",j); fflush(stdin); fgets(vetor[i][j],5,stdin); //pensando na entrada 09.55 } } for(i=0;i<ALUNOS;i++){ nota1=atof(vetor[i][1]); nota2=atof(vetor[i][2]);; media = (nota1 + nota2 ) / 2; printf("\nMedia final = %.2f", media); if (media >= 7.0) printf(" ( aluno %s aprovado ).",vetor[i][0]); else printf(" ( aluno %s reprovado ).",vetor[i][0]); } return 0; } |
Teste o código em: https://ideone.com/yFRf93
Particularmente eu não teria utilizado a solução com a matriz tridimensional e sim com uma matriz para notas e outra para os nomes. Isso porque a estrutura tridimensional vai ser subutilizada. Para cada nota serão alocados 30 caracteres, sendo que 6 seria o máximo possível para elas. Além disso é preciso fazer a conversão de string para número o que, embora seja somente usar uma função, possui custo computacional associado. O código abaixo mostra essa opção de codificação.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <stdio.h> #include <string.h> #include <stdlib.h> #define ALUNOS 3 int main(void) { float notas[ALUNOS][2], media; char nomes[ALUNOS][30]; int i,j; for(i=0;i<ALUNOS;i++){ printf("\nEntre com o nome do aluno: "); fgets(nomes[i],29,stdin); for(j=0;j<2;j++){ printf("Informe a %da. nota:", j); scanf("%f ", ¬as[i][j]); } } for(i=0;i<ALUNOS;i++){ media = (notas[i][0] + notas[i][1]) / 2; printf("\nMedia final = %.2f", media); if (media >= 7.0) printf(" ( aluno %s aprovado ).",nomes[i]); else printf(" ( aluno %s reprovado ).",nomes[i]); } return 0; } |
Teste o código em: https://ideone.com/wdsXif
Complementando a solução proposta, segue a solução utilizando funções. Elaborei 3 funções para a solução, sendo uma para ler os dados, outra para calcular a média de cada aluno e uma terceira para mostrar se aluno está aprovado ou reprovado.
A função leituraDados() é um copia e cola de um trecho da função main(). Essa função e a mostraAprovacao() são funções que precisam receber as duas matrizes.
A função calcularMedias() somente precisa receber a matriz com as notas. Veja que para as médias foi necessário aumentar uma coluna na matriz de notas. Isso porque a matriz agora armazena as duas notas do aluno e a média das notas. Poderia ter feito o cálculo das médias na função mostraAprovacao(), dispensando inclusive a coluna adicional na matriz de notas, mas preferi dessa forma para facilitar o entendimento de todo o código (foi uma decisão pessoal e também achei didático mostrar que a função calcularMedias() precisa de menos parâmetros do que as demais).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#include <stdio.h> #include <string.h> #include <stdlib.h> #define ALUNOS 3 void leituraDados(char nomes[ALUNOS][30], float notas[ALUNOS][3]) { int i,j; for(i=0;i<ALUNOS;i++){ printf("\nEntre com o nome do aluno: "); fgets(nomes[i],29,stdin); for(j=0;j<2;j++){ printf("Informe a %da. nota:", j); scanf("%f ", ¬as[i][j]); } } } void calcularMedias(float notas[ALUNOS][3]) { int i; for(i=0;i<ALUNOS;i++){ notas[i][2] = (notas[i][0] + notas[i][1]) / 2; } } void mostraAprovacao(char nomes[ALUNOS][30], float notas[ALUNOS][3]) { int i; for(i=0;i<ALUNOS;i++){ printf("\nMedia final = %.2f", notas[i][2]); if (notas[i][2] >= 7.0) printf(" ( aluno %s aprovado ).",nomes[i]); else printf(" ( aluno %s reprovado ).",nomes[i]); } } int main(void) { float notas[ALUNOS][3], media; char nomes[ALUNOS][30]; leituraDados(nomes, notas); calcularMedias(notas); mostraAprovacao(nomes, notas); return 0; } |
Gosto sempre de destacar a vantagem na legibilidade do código que o uso de funções traz. Olhando para a função main(), fica claro ler o que o algoritmo faz.
Teste o código em: https://ideone.com/e6Se8c