Ir ao conteúdo
  • Cadastre-se

C Cadastro e cálculo de notas


Jorge Tadeu

Posts recomendados

Pessoal,

Tô começando em C++ e tentei fazer um pequeno programa para cadastro de alunos numa turma, cadastro de notas, substituição da menor nota pela nota de recuperação, e impressão 2 relatórios: um geral, e outro com relação de aprovados, para aqueles com média superior a 5,0. Após compilação no dev c++, o programa executa apenas a primeira linha e pára. Podem analisar e sugerir correções, por favor?

 

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

struct turma{          /* definição de registro  */
	char nome[80];
	char matricula[5];
	float p1;
	float p2;
	float p3;
	float p4;
	float r;
	float media;
};
typedef struct turma Aluno;

#define MAX 30
Aluno* turma[MAX];

void inicializa (int n, Aluno** turma){
	int i;
	for (i=0; i<n; i++)
	turma[i]=NULL;
}

void preenche (int n, Aluno** turma, int i){         /* cadastro de alunos, matrículas e notas */
	float p1,p2,p3,p4,r;
	char rec;
	
	if (i<0 || i>=n){
		printf("\nIndice fora do limite do vetor\n");
		exit(1);
	}

if (turma[i==NULL])
turma[i]=(Aluno*)malloc(sizeof(Aluno));

printf("\nEntre com o nome:\n");
scanf("%c", &turma[i]->nome);
printf("\nEntre com a matrícula:\n");
scanf("%c", &turma[i]->matricula);
printf("\nEntre com a primeira nota:\n");
scanf("%f", &turma[i]->p1);
printf("\nEntre com a segunda nota:\n");
scanf("%f",  &turma[i]->p2);
printf("\nEntre com a terceira nota:\n");
scanf("%f", &turma[i]->p3);
printf("\nEntre com a quarta nota:\n");
scanf("%f", &turma[i]->p4);

printf("\nExiste prova de recuperação? Digite S ou N\n");
scanf("%c", &rec);

switch (rec){       
	case 'S':
		printf("\nEntre com a nota de recuperação:\n");
		scanf("%f", &turma[i]->r);
	break;
	case 'N':
		printf("\nOk\n");
	break;
	default:
		printf("\nDigite apenas S ou N\n");
	break;
}
if (r!=NULL)           /* substituição de nota de recuperação pela menor nota */
	if (p1<p2)
		if (p1<p3)
			if (p1<p4)
				p1=r;
			else
				p4=r;
		else
			if (p3<p4)
				p3=r;
			else
				p4=r;
	else
		if (p2<p3)
			if (p2<p4)
				p2=r;
			else
				p4=r;
		else
			if (p3<p4)
				p3=r;
			else
				p4=r;
else
	exit (1);
}

void imprime (int n, Aluno** turma, int i){         /* impressão de relatório geral */
	if (i<0 || i>=n){
	printf("Indice fora do limite do vetor\n");
	//exit(1);
	return;
	}
	
	float media;
	float p1,p2,p3,p4;
	media=(p1*1+p2*2+p3*3+p4*4)/10;
	
	if (turma[i]!=NULL){
		printf("\nMatrícula: %c\n", turma[i]->matricula);
		printf("\nNome:%c\n", turma[i]->nome);
		printf("\nNota 1:%f", turma[i]->p1);
		printf("\nNota 2:%f", turma[i]->p2);
		printf("\nNota 3:%f", turma[i]->p3);
		printf("\nNota 4:%f", turma[i]->p4);
		printf("\nMédia:%f", turma[i]->media);
		printf("\n\n");
	}
}

void imprime_aprovados (int n, Aluno** turma, int i){    /* impressão de relatório de aprovados   */
	if (i<0 || i>=n){
	printf("Indice fora do limite do vetor\n");
	//exit(1);
	return;
}
	float soma;
	float media;
	float p1,p2,p3,p4;
	float mediasala;
	
	media=(p1*1+p2*2+p3*3+p4*4)/10;
	
	soma=0;
	for (i=0; i<n; i++){
	soma=soma+turma[i]->media;
	}
	mediasala=(soma/n);
	
	for (i=0; i<n; i++){
		if (media>5,0){
			imprime (30, turma, 0);
			printf("\nMatrícula:%c", turma[i]->matricula);
			printf("\nNome:%c", turma[i]->nome);
			printf("\nMédia:%f", turma[i]->media, "Aprovado");
		}
		else
		return;
	}
}

int main() {
	float mediasala;
	
	system ("cls");
	printf ("\n%c\n", "SISTEMA DE GERENCIAMENTO DE NOTAS");
	preenche(30, turma,0);
	imprime (30, turma,0);
	imprime_aprovados(30, turma,0);
	printf("\nMédia da classe:%f", mediasala);
	
	system("PAUSE");
	return 0;
}

 

 

Link para o comentário
Compartilhar em outros sites

para ler vetor de caracteres você deve usar scanf("%s", turma->nome);  O mesmo vale para matrícula. Veja que nome e matricula se comportam como Ponteiros de modo que voce não deve usar o endereço &. Não use %c nesses casos e sim %s para a cadeia de caracteres. Finalmente, faça o mesmo na impressão de seu programa C printf("%s", turma->nome); 

 

 

Link para o comentário
Compartilhar em outros sites

Obrigado. Fiz as correções, mas após inserir o primeiro nome, o programa não avança para a matrícula. Será que tem algum problema na definição dos ponteiros? 

adicionado 26 minutos depois

Substituí scanf por gets:

void preenche (int n, Aluno** turma, int i){         /* cadastro de alunos, matrículas e notas */
	float p1,p2,p3,p4,r;
	char rec;
	
	if (i<0 || i>=n){
		printf("\nIndice fora do limite do vetor\n");
		exit(1);
	}

if (turma[i==NULL])
turma[i]=(Aluno*)malloc(sizeof(Aluno));

printf("\nEntre com o nome:\n");
gets(turma[i]->nome);
printf("\nEntre com a matrícula:\n");
gets(turma[i]->matricula);

Na execução:

image.png.b853a87cce11f2a42e7b75dab6d235ee.png

Link para o comentário
Compartilhar em outros sites

@Jorge Tadeu Olá, amigo. Esse problema é comum em C mesmo, não é erro no seu código. 

Isso se deve a 'sujeira' no stdin. Entenda isso como 'sujeira' no buffer.

Tem duas funções q conheço para resolver esse problema.

A primeira e q mais uso é a seguinte:

 

void limpa_linha() {
    scanf("%*[^\n]");
    scanf("%*c");
}

A outra, q conheci aqui, é a seguinte:

 

void fflush_stdin() {
    int ch;
    while ((ch = getchar()) != '\n' && ch != EOF);
}

Exemplo de uso de uma dessas funções:

 

printf("\nEntre com o nome:\n");
scanf("%[^\n]s", turma[i]->nome); // aqui o formato '%[^\n]s' é para ler um nome onde no mesmo tenha espaços. Ex: Jonas Barbosa
limpa_linha(); // essa linha é 'ignorada' pelo compilador. O q a função faz é limpar o stdin, ou buffer

printf("\nEntre com a matrícula:\n");
scanf("%[^\n]s", turma[i]->matricula);
limpa_linha();

Só fazendo uso de uma dessas funções depois de cada scanf já vai resolver esse problema, bastante comum no C

adicionado 20 minutos depois

Com respeito a esse problema, devo dizer q até há poucos dias eu usava o comando fflush(stdin); após cada scanf,  mas descobri aqui mesmo nesse fórum q esse comando não é muito recomendável para essa finalidade. Devido a isso passei a fazer uso dessas funções com 'alternativa' ao comando fflush(stdin);

Logo, recomendo o uso de uma dessas funções para contornar o problema de sujeira no stdin

Link para o comentário
Compartilhar em outros sites

@Jorge Tadeu

9 horas atrás, Jorge Tadeu disse:

Novamente pára a execução na linha seguinte. Não solicita a primeira nota!!!

 

Olá. A função limpa_linha ou a função fflush_stdin recomendo usar após cada scanf, com isso resolve esse problema de pular p linha seguinte.

Quanto ao uso do gets eu não recomendo de forma alguma e até posso dizer q ele está caindo em desuso. Isso é porque esse comando é considerado 'perigoso'. No Visual Studio, por exemplo, esse comando nem é mais aceito em códigos feitos em C

Quanto a colocar o nome completo não é o problema, desde q o scanf seja definido dessa forma, por exemplo:

 

scanf("%[^\n]s", x.nome); // esse exemplo pequei d outro código

Logo, na parte q o Sr. mencionou referente a primeira nota, ficaria assim:

 

printf("\nEntre com o nome:\n");
scanf("%[^\n]s", turma[i]->nome); // para ler uma string não é preciso o uso do operador &
limpa_linha();

printf("\nEntre com a matrícula:\n");
scanf("%[^\n]s", turma[i]->matricula);
limpa_linha();

printf("\nEntre com a primeira nota:\n");
scanf("%f", &turma[i]->p1);
limpa_linha();

printf("\nEntre com a segunda nota:\n");
scanf("%f",  &turma[i]->p2);
limpa_linha();

printf("\nEntre com a terceira nota:\n");
scanf("%f", &turma[i]->p3);
limpa_linha();

printf("\nEntre com a quarta nota:\n");
scanf("%f", &turma[i]->p4);
limpa_linha();

Se continuar dando problemas avise, ok?

Perceba q uso a função limpa_linha após cada scanf

Link para o comentário
Compartilhar em outros sites

Pessoal

Após as alterações indicadas, o problema continua:

void preenche (int n, Aluno** turma, int i){         /* cadastro de alunos, matrículas e notas */
	float p1,p2,p3,p4,r;
	char rec;
	
	if (i<0 || i>=n){
		printf("\nIndice fora do limite do vetor\n");
		exit(1);
	}

if (turma[i==NULL])
turma[i]=(Aluno*)malloc(sizeof(Aluno));

printf("\nEntre com o nome:\n");
scanf("%[^\n]s", turma[i]->nome);                       // aqui o formato '%[^\n]s' é para ler um nome onde no mesmo tenha espaços. Ex: Jonas Borba
limpa_linha();                                          // essa linha é 'ignorada' pelo compilador. O q a função faz é limpar o stdin, ou buffer
printf("\nEntre com a matrícula:\n");
scanf("%[^\n]s", turma[i]->matricula);
limpa_linha();
printf("\nEntre com a primeira nota:\n");
scanf("%f", &turma[i]->p1);
limpa_linha();
printf("\nEntre com a segunda nota:\n");
scanf("%f",  &turma[i]->p2);
limpa_linha();
printf("\nEntre com a terceira nota:\n");
scanf("%f", &turma[i]->p3);
limpa_linha();
printf("\nEntre com a quarta nota:\n");
scanf("%f", &turma[i]->p4);
limpa_linha();

printf("\nExiste prova de recuperação? Digite S ou N\n");
scanf("%c", &rec);

 

adicionado 1 minuto depois

image.png.753da47c5a99fbc9fba0ec7ac0303a5f.png

Link para o comentário
Compartilhar em outros sites

@Jorge Tadeu Olá. Estive mexendo em seu código e tem alguns pontos para corrigir.

Bem, vou passar o código todo com os ajustes q fiz e daí dá uma olhada para ver se está de acordo com o esperado.

A questão da média da turma não está ajustada.

Segue o código:

 

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

struct turma {          /* definição de registro  */
    char nome[80];
    char matricula[5];
    float p1;
    float p2;
    float p3;
    float p4;
    float r;
    float media;
};
typedef struct turma Aluno;

#define MAX 30
Aluno* turma[MAX];

void inicializa (int n, Aluno** turma){
    int i;
    for (i=0; i<n; i++)
        turma[i] = NULL;
}

void limpa_linha() {
    scanf("%*[^\n]");
    scanf("%*c");
}

void preenche (int n, Aluno** turma, int i){         /* cadastro de alunos, matrículas e notas */
	
    float p1,p2,p3,p4,r;
    char rec;

    if (i<0 || i>=n) {
        printf("\nIndice fora do limite do vetor\n");
        exit(1);
	}

    if (turma[i] == NULL)
        turma[i]=(Aluno*)malloc(sizeof(Aluno));

    printf("\nEntre com o nome: ");
    scanf("%s", turma[i]->nome);
    limpa_linha();

    printf("\nEntre com a matrícula: ");
    scanf("%s", turma[i]->matricula);
    limpa_linha();

    printf("\nEntre com a primeira nota: ");
    scanf("%f", &turma[i]->p1);
    limpa_linha();

    printf("\nEntre com a segunda nota: ");
    scanf("%f",  &turma[i]->p2);
    limpa_linha();

    printf("\nEntre com a terceira nota: ");
    scanf("%f", &turma[i]->p3);
    limpa_linha();

    printf("\nEntre com a quarta nota: ");
    scanf("%f", &turma[i]->p4);
    limpa_linha();

    printf("\nExiste prova de recuperação? [s/n]: ");
    scanf("%c", &rec);
    limpa_linha();

    switch (rec){
        case 's':
            printf("\nEntre com a nota de recuperação: ");
            scanf("%f", &turma[i]->r);
            limpa_linha();
        break;
        case 'n':
            printf("\nOk\n");
        break;
        default:
            printf("\nDigite apenas 's' ou 'n'!\n");
        break;
    }
    if (r != 0)           /* substituição de nota de recuperação pela menor nota */
        if (p1<p2)
            if (p1<p3)
                if (p1<p4)
                    p1=r;
                else
                    p4=r;
            else
                if (p3<p4)
                    p3=r;
                else
                    p4=r;
        else
            if (p2<p3)
                if (p2<p4)
                    p2=r;
                else
                    p4=r;
            else
                if (p3<p4)
                    p3=r;
                else
                    p4=r;
    else
        exit (1);
}

void imprime (int n, Aluno** turma, int i){         /* impressão de relatório geral */
	if (i<0 || i>=n){
        printf("Indice fora do limite do vetor\n");
        //exit(1);
        return;
	}

    float media = 0;
    float p1, p2, p3, p4;
    media = (p1 * 1 + p2 * 2 + p3 * 3 + p4 * 4) / 10;

    if (turma[i] != NULL){
        printf("\nMatrícula: %s\n", turma[i]->matricula);
        printf("\nNome: %s\n", turma[i]->nome);
        printf("\nNota 1: %.2f", turma[i]->p1);
        printf("\nNota 2: %.2f", turma[i]->p2);
        printf("\nNota 3: %.2f", turma[i]->p3);
        printf("\nNota 4: %.2f", turma[i]->p4);
        printf("\nMédia: %.2f", media);
        printf("\n\n");
    }
}

void imprime_aprovados (int n, Aluno** turma, int i){    /* impressão de relatório de aprovados   */
	if (i<0 || i>=n){
        printf("Indice fora do limite do vetor\n");
        //exit(1);
        return;
    }
    float soma = 0;
    float media = 0;
    float p1 , p2, p3, p4;
    float mediasala = 0;

    media=(p1*1+p2*2+p3*3+p4*4)/10;

    soma=0;
    for (i=0; i<n; i++) {
        soma=soma+turma[i]->media;
    }
    mediasala = (soma / n);

    for (i = 0; i < n; i++){
       if (media > 5.0){
            imprime (30, turma, 0);
            printf("\nMatrícula: %s", turma[i]->matricula);
            printf("\nNome: %s", turma[i]->nome);
            printf("\nMédia: %.2f", turma[i]->media);
            printf("\nAprovado!\n\n");
      }
      else
          return;
	}
}

int main() {

    setlocale(LC_CTYPE, "Portuguese");

    system ("cls");
    printf ("\n\nSISTEMA DE GERENCIAMENTO DE NOTAS\n\n");
    preenche(30, turma, 0);
    imprime (30, turma, 0);
    imprime_aprovados(30, turma,0);

    system("PAUSE");
	
    return 0;
}

Experimenta rodar esse código e se continuar dando problemas avise, ok?

Só q o Sr. está fazendo alocação dinâmica de memória e não está liberando a memória que foi alocada

adicionado 1 minuto depois

OBS: A questão da média da turma precisa ser ajustada

Link para o comentário
Compartilhar em outros sites

@Jorge Tadeu Olá. Como o Sr. mesmo disse q está começando a estudar C/C++, recomendo fortemente trabalhar em programas mais simples, a princípio. Depois q começar a entender bem a respeito dos assuntos referentes ao C/C++, aí sim passe a trabalhar com programas mais complexos. 

O processo de aprendizagem é passo a passo, degrau por degrau.

Se for ver esse código q o Sr. postou, nele estão sendo usados recursos avançados do C, como alocação dinâmica de memória, ponteiros, matrizes, etc.. Devido a isso vai ficar difícil entender exatamente o q está sendo feito no código

Fica a dica! :thumbsup:

 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Olá a todos.

 

@Jorge Tadeu, costumo passar uma dica aqui no fórum: Não tente fazer todo programa de uma vez. Vá fazendo aos poucos.

 

Basicamente é o seguinte: antes de implementar uma nova funcionalidade no código, as funcionalidades anteriores devem está "funcionando perfeitamente"*, ou seja, caso o código apresente alguma falha, terá uma noção que essa falha está no algo novo que você implementou.

 

Para tentar ajudar, "desabilitei" parte do código que está com problemas... ai você dá uma revisada e vai tentando corrigir parte por parte...

 

Código:

Spoiler

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

struct turma {          /* definição de registro  */
    char nome[80];
    char matricula[5];
    float p1;
    float p2;
    float p3;
    float p4;
    float r;
    float media;
};

typedef struct turma Aluno;

#define MAX 30
Aluno* turma[MAX];

void inicializa (int n, Aluno** turma){
    int i;
    for (i=0; i<n; i++)
        turma[i] = NULL;
}

void limpa_linha() {
    scanf("%*[^\n]");
    scanf("%*c");
}

void preenche (int n, Aluno** turma, int i){         /* cadastro de alunos, matrículas e notas */
	
    float p1,p2,p3,p4,r;
    char rec;

    if (i<0 || i>=n) {
        printf("\nIndice fora do limite do vetor\n");
        exit(1);
	}

    if (turma[i] == NULL)
        turma[i]=(Aluno*)malloc(sizeof(Aluno));

    printf("\nEntre com o nome: ");
    scanf("%s", turma[i]->nome);
    limpa_linha();

    printf("\nEntre com a matrícula: ");
    scanf("%s", turma[i]->matricula);
    limpa_linha();

    printf("\nEntre com a primeira nota: ");
    scanf("%f", &turma[i]->p1);
    limpa_linha();

    printf("\nEntre com a segunda nota: ");
    scanf("%f",  &turma[i]->p2);
    limpa_linha();

    printf("\nEntre com a terceira nota: ");
    scanf("%f", &turma[i]->p3);
    limpa_linha();

    printf("\nEntre com a quarta nota: ");
    scanf("%f", &turma[i]->p4);
    limpa_linha();

    printf("\nExiste prova de recuperação? [s/n]: ");
    scanf("%c", &rec);
    limpa_linha();

    switch (rec){
        case 's':
            printf("\nEntre com a nota de recuperação: ");
            scanf("%f", &turma[i]->r);
            limpa_linha();
        break;
        case 'n':
            printf("\nOk\n");
        break;
        default:
            printf("\nDigite apenas 's' ou 'n'!\n");
        break;
    }
    if (r != 0)           /* substituição de nota de recuperação pela menor nota */
        if (p1<p2)
            if (p1<p3)
                if (p1<p4)
                    p1=r;
                else
                    p4=r;
            else
                if (p3<p4)
                    p3=r;
                else
                    p4=r;
        else
            if (p2<p3)
                if (p2<p4)
                    p2=r;
                else
                    p4=r;
            else
                if (p3<p4)
                    p3=r;
                else
                    p4=r;
    else
        exit (1);
}

void imprime (int n, Aluno** turma, int i){         /* impressão de relatório geral */
	if (i<0 || i>=n){
        printf("Indice fora do limite do vetor\n");
        //exit(1);
        return;
	}

    float media = 0;
    float p1, p2, p3, p4;
    media = (p1 * 1 + p2 * 2 + p3 * 3 + p4 * 4) / 10;

    if (turma[i] != NULL){
        printf("\nMatrícula: %s\n", turma[i]->matricula);
        printf("\nNome: %s\n", turma[i]->nome);
        printf("\nNota 1: %.2f", turma[i]->p1);
        printf("\nNota 2: %.2f", turma[i]->p2);
        printf("\nNota 3: %.2f", turma[i]->p3);
        printf("\nNota 4: %.2f", turma[i]->p4);
        printf("\nMédia: %.2f", media);
        printf("\n\n");
    }
}

void imprime_aprovados (int n, Aluno** turma, int i){    /* impressão de relatório de aprovados   */
	if (i<0 || i>=n){
        printf("Indice fora do limite do vetor\n");
        //exit(1);
        return;
    }
    float soma = 0;
    float media = 0;
    float p1 , p2, p3, p4;
    float mediasala = 0;

    //media=(p1*1+p2*2+p3*3+p4*4)/10;

    soma=0;
    
    
    //AQUI ESTÁ ACESSANDO DE 0 A N, MAS NEM SEMPRE OS N CADASTROS JÁ EXISTEM!!! DEVERIA IR DE "1 ATÉ A QUANTIDADE DE ALUNOS CADASTRADOS"
    /*
    for (i=0; i<n; i++) {
        soma=soma+turma[i]->media; //<-- VAI CONSEGUIR ACESSAR A POSIÇÃO 0, MAS VAI DÁ PAU NA POSIÇÃO 1 (QUE ESTÁ NULL!!!)
    }    
    */
    
    mediasala = (soma / n);

    /*
    for (i = 0; i < n; i++){  //MESMA COISA. SÓ EXISTE UAM NOTA CADASTRADA, MAS ESTÁ TENTANDO ACESSAR TODAS 
       if (media > 5.0){
            imprime (30, turma, 0);
            printf("\nMatrícula: %s", turma[i]->matricula); //AQUI VAI DAR PAU QUANDO I FOR IGUAL A 1
            printf("\nNome: %s", turma[i]->nome);
            printf("\nMédia: %.2f", turma[i]->media);
            printf("\nAprovado!\n\n");
      }
      else
          return;
	}
	*/
}

int main() {
    setlocale(LC_CTYPE, "Portuguese");

    system ("cls");
    printf ("\n\nSISTEMA DE GERENCIAMENTO DE NOTAS\n\n");
    preenche(30, turma, 0);
    imprime (30, turma, 0);
    imprime_aprovados(30, turma,0);

    system("PAUSE");
	
    return 0;
}

 

Obs.: Meus comentários eu deixei em CAIXA ALTA.

 

Pronto. Está compilando e rodando (pelo menos aqui no meu Dec-C++). Como está rodando, concluímos que não tem erro de sintaxe, logo, o que não está funcionando está no âmbito da lógica!!! Entende?

 

Ai, coloque para rodar e veja o que está acontecendo. Deverá ver que a média está dando errada (como citado por @giu_d).. ai vai atuar somente nessa questão!!! Tente analisar e ver o que está acontecendo para a média está saindo errada... não tente fazer outras!!! Apenas faça a média dar certo!!!

 

Aí posta o código aqui para analisarmos... caso tenha dúvidas, informar onde.

 

Para ajudar, adiante já um errinho:

Spoiler

void imprime (int n, Aluno** turma, int i){         /* impressão de relatório geral */
	if (i<0 || i>=n){
        printf("Indice fora do limite do vetor\n");
        //exit(1);
        return;
	}

    float media = 0;
    float p1, p2, p3, p4;  //<--- NÃO É PARA DECLARAR ESSAS VARIÁVEIS!!! AS NOTAS ESTÃO NO VETOR

 

 

No aguardo.

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...