Dúvida quanto a Structs

1. Dúvida quanto a Structs

Fernando
bellun

(usa Outra)

Enviado em 10/09/2015 - 09:56h

Estou com um problema com código usando structs, acho que tem algo muito errado na minha função de ler e validar uma nota.

// Aluno : Fernando Henrique Antero de Moraes

/*
Sintese
Objetivo: Auxiliar o usuário no cadastro de um aluno , suas 4 notas e calcular a média.

Entrada :nome do aluno, notas

Saida : nome do aluno, notas, media

*/

#include <stdio.h>
#include <conio.h>
#include <locale.h>
#define MAX_NOME 100
#define QTDE_NOTAS 4
struct Cadastro
{
char nome[MAX_NOME];
float notas[QTDE_NOTAS];
float media;
};
//////////////////////PROTÓTIPOS/////////////////////////////////////
void leValidaNota(struct Cadastro aluno, char *titulo, int contador);
void apresentaCadastro(struct Cadastro aluno, int qtdeNotas);
void calculaMedia(struct Cadastro aluno, int qtdeNotas);
void leValidaTexto (char *texto, char *mensagemTitulo, int tamanho);
///////////////////////////////////////////////////
int main(void){
// Declaracoes
char titulo[MAX_NOME];
int aux;
// Instrucoes
setlocale(LC_ALL,"Portuguese");
struct Cadastro aluno;
leValidaTexto(aluno.nome,"Informe o nome do estudante:",MAX_NOME);
for(aux=0;aux<QTDE_NOTAS;aux++){
leValidaNota(aluno,"Informe as notas do estudante:\n", aux);
}
calculaMedia(aluno, QTDE_NOTAS);
apresentaCadastro(aluno, QTDE_NOTAS);
getch();
return 0;
}
//Objetivo:ler e validar uma nota
//Parametros:
//Retorno:nota valida
void leValidaNota(struct Cadastro aluno, char *titulo, int contador)
{
int ret;
do{
printf("Informe a nota numero %d:\n",contador+1);
fflush(stdin);
ret=scanf("%f",&aluno.notas[contador]);
fflush(stdin);
if(aluno.notas[contador]<0||aluno.notas[contador]>10)
{
printf("Valor informado fora da faixa informe novamente: 0...10\n");
}
else if(ret==0)
{
printf("Campo destinado para numeros, informe novamente\n");
}
}while(aluno.notas[contador]<0||aluno.notas[contador]>10||ret==0);
}
// Objetivo: Ler e validar um texto
// Parâmetros: referencia ao vetor do texto, referencia ao vetor mensagem de titulo, valor maximo da string
// Retorno:
void leValidaTexto (char *texto, char *mensagemTitulo, int tamanho)
{
do{
printf("%s\n", mensagemTitulo);
fflush(stdin);
fgets(texto, tamanho, stdin);
fflush(stdin);
if(texto[strlen(texto)-1] == '\n'){
texto[strlen(texto)-1] = '\0';
}
if(strlen(texto) == 0){
system("cls");
printf("Nada foi informado\n");
getch();
}
}while(strlen(texto) == 0);
}
//Objetivo:calcular a media entre 4 valores
//Parametros:
//Retorno:
void calculaMedia(struct Cadastro aluno, int qtdeNotas)
{
float somaMedias;
int aux;
for(aux=0;aux<qtdeNotas;aux++){
somaMedias=aluno.notas[aux];
}
aluno.media=somaMedias/qtdeNotas;
}
//Objetivo:Apresentar os dados do aluno
//Parametros:
//Retorno:
void apresentaCadastro(struct Cadastro aluno, int qtdeNotas)
{
int aux;
printf("Aluno:%s\n",aluno.nome);
printf("Suas notas foram:\n");
for(aux=0;aux<qtdeNotas;aux++){
printf("%.2f\n",aluno.notas[aux]);
}
printf("A média do aluno foi %.2f:\n", aluno.media);
}





  


2. Re: Dúvida quanto a Structs

Paulo
paulo1205

(usa Ubuntu)

Enviado em 10/09/2015 - 13:35h

Comentários:

1) fflush(stdin) é uma aberração.

Os que vêm depois de fgets() podem ser removidos sem dó nem piedade, nem prejuízo algum para o programa.

Nos casos em que ele seria supostamente necessário para eliminar o '\n' deixado no buffer de leitura após invocar scanf() para ler um número, a solução mais correta seria mudar a string de formatação do scanf() para consumir o '\n'.

scanf() é uma das funções mais complexas -- talvez até _A_ mais complexa -- da biblioteca padrão do C. O jeito como ela é ensinada normalmente nos cursos introdutórios é uma coisa que está entre a piada de mau gosto e a ofensa por descaso. Ela não é uma função para ler valores de variáveis, mas sim uma função para verificar se os dados de entrada estão de acordo com certo padrão, podendo opcionalmente atribuir partes dos dados verificados a variáveis. E, por ser uma função de validação, é importante checar o valor de retorno da função e eventuais outros marcadores que você mesmo introduza para verificar a quantidade de caracteres consumidos.

O jeito “certo” (e trabalhoso!) de usar leituras com scanf() seria trocar todas as ocorrências de algo como

int var;
scanf("%d", &var);
fflush(stdin); /* Não funciona em todas as máquinas!!! */


pelo seguinte código.

int var;
int a, b, result;
a=b=0;
result=scanf("%d%n%*1[\n]%n", &var, &a, &b);
if(result==1){
/* Consegiu ler o valor inteiro. Agora vamos refinar o tratamento. */
if(b>a){
/* Achou (e consumiu) quebra de linha. O buffer está limpo. */
}
else if(b==0){
/*
Erro de leitura ao tentar encontrar quebra de linha. Seria sensato
não tentar ler mais nada ou, a depender do caso, implementar
algum método mais avançado de recuperação de erro.
*/
}
else{ /* Necessariamente b==a. */
/*
Encontrou um caráter que não é dígito nem quebra de linha.

Como tratar uma entrada como “123x” ou “5 ” (note o espaço depois do 5)
depende se você. Entre os tratamentos possíveis está abortar o programa,
mas você pode optar por algo menos drástico, especialmente se quiser
retentar a leitura do dado desejado. Nesse último caso, terá de tirar do
buffer de leitura os caracteres indesejados, e isso normalmente é feito
com uma leitura e descarte de todos os caracteres até encontrar a próxima
marca de fim de linha. Para tanto, há duas formas portáteis de o fazer, que
são equivalentes.

/* Opção 1 */
void limpabuffer(void){
int ch;
while((ch=getchar())!=EOF && ch!='\n')
;
if(ch==EOF){
/* Erro de leitura. Aborta o programa (ou dá outro tratamento). */
fprintf(stderr, "Erro de leitura.\n");
exit(1);
}
}

--

/* Opção 2 */
void limpabuffer(void){
int n=0;
if(scanf("%*[^\n]%*1[\n]%n", &n)==EOF || n==0){
/* Erro de leitura. Aborta o programa (ou dá outro tratamento). */
fprintf(stderr, "Erro de leitura.\n");
exit(1);
}
}

Note que nenhuma das versões de lmpabuffer(), acima, deve ser usada
se o buffer já estiver limpo.
*/
}
}
else if(result==EOF){
/* Erro de leitura antes de começar a ler. */
}
else{
/*
Não deu erro, mas não converteu o valor (result==0), o que indica que foi
achado um caráter que não é espaço nem dígito. De novo, o tratamento
depende de você.
*/
}



2) Suas funções de leitura estão muito estranhas. Particularmente estranha é leValidaNota().

A primeira coisa estranha é você passar uma cópia de estrutura à função. Não sei se você está acostumado com Java, em que todos os objetos são ponteiros, mas em C, se você passa uma estrutura por valor à função, a função recebe uma cópia do valor original. Se ela eventualmente modificar o valor recebido, vai modificar a cópia, e o original vai parecer intacto.

Se você quer modificar o valor da estrutura dentro declarada em main(), deve transformar o parâmetro da função em ponteiro, modificar o corpo da função de modo a usar acesso a membro a partir de ponteiro (p_somestruct->member em vez de somestruct.member) e, na hora de invocar a função, passar o endereço do objeto, em lugar de (uma cópia de) seu valor.


3) A mesma observação vale para calculaMedia() e apresentaCadastro().


4) Em calculaMedia(), você não está somando os valores e depois dividindo pela quantidade valores. No seu laço de repetição, você simplesmente substitui o valor anterior de somaMedias (que, aliás é um nome ruim, pois não é uma soma de médias, mas sim uma soma de notas) com o valor da próxima nota, e depois divide o valor final (igual à última nota) pela quantidade de notas. Duvido que seja isso que você gostaria de ter feito.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts