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.
#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.
#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.
#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).
#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