Escreva um programa em C onde, se possa representar os nomes e as notas de alunos de um curso da universidade. O programa deverá imprimir os nomes dos cinco alunos que obtiverem as maiores notas acima da média da turma. Considerar que a turma tenha 50 alunos. Usar a estrutura multivalorada vista em sala de aula.
Passo 1
O enunciado pede que eu escreva um programa em C que represente nomes e notas de uma turma com
50
alunos usando uma “estrutura multivalorada” (ou seja, uma struct que guarda nome e nota). O objetivo final é: imprimir os nomes dos cinco alunos que obtiverem as maiores notas entre aqueles cuja nota é estritamente maior que a média da turma.
Informações dadas e o que é pedido:
- Número de alunos:
50 . - Quantos nomes imprimir:
5 (os cinco maiores). - Só considerar alunos com nota maior que a média da turma (ou seja, filtrar por “nota > média”).
- Usar uma estrutura multivalorada (struct em C) para guardar nome e nota.
- O programa deve ler os dados (nome e nota) dos
50 alunos, calcular a média, e então mostrar os cinco nomes com maiores notas entre os acima da média.
Observação importante sobre comportamento em casos limites (vou implementar de forma segura):
- Se houver menos de
5 alunos com nota acima da média, o programa vai imprimir somente os que existirem (e avisar quantos foram impressos). - Se houver empates em notas, o critério será a ordenação por nota: o programa escolhe os cinco primeiros no ordenamento descendente (não quebra o empate por nome).
Passo 2
Decidindo a estrutura de dados — a “estrutura multivalorada” pedida:
- Vou usar uma struct chamada
Student com dois campos: -
char name[100] : para guardar o nome como string (até 99 caracteres mais o terminador). -
float grade : para guardar a nota do aluno.
-
- Também uso duas constantes simbólicas:
-
N = 50 : número total de alunos. -
TOP = 5 : quantos nomes devemos imprimir.
-
Por que isso funciona?
- A struct permite agrupar os dois valores (nome e nota) para cada aluno — isso é exatamente “multivalorada”.
- Um vetor
Student students[N] guarda os dados de todos os alunos.
Passo 3
Como ler os dados de forma robusta (entrada de nome e nota, evitando problemas com quebras de linha):
- Para o nome: uso
fgets() para ler a linha inteira (inclui espaços). Depois removo o ‘\n’ final se existir. - Para a nota: uso
fgets() para ler a linha e sscanf() para converter para float . Isso evita misturar scanf e fgets (que costuma causar confusão com o buffer). - Exemplo de remoção do ‘\n’ do final da string lida:
- Se
s for a string lida, faço: - verificar o comprimento com
strlen(s) , - se o último caractere for ‘\n’, substituir por ‘\0’.
- verificar o comprimento com
- Se
- Vou validar a leitura da nota: enquanto
sscanf(buffer, “%f”, &grade) != 1 peço a nota novamente.
Isso garante que nomes com espaços funcionem e que não haja problemas de leitura entre entradas.
Passo 4
Como calcular a média da turma (a teoria e a fórmula):
- Se as notas dos
N alunos são g_1, g_2, \dots, g_N , a média é dada por:
- No programa: soma todas as notas em uma variável
sum e depois faz average = sum / N . - Explicando variáveis:
-
sum é a soma acumulada das notas. -
average é a média resultante. -
N é 50 .
-
Passo 5
Como selecionar os cinco maiores acima da média — estratégia:
- Primeiro, ordeno o vetor de estudantes por nota em ordem decrescente (maior nota primeiro).
- Após a ordenação, percorro o vetor do início e escolho os alunos cuja nota é estritamente maior que a média, até formar uma lista de no máximo
TOP alunos. - Ordenação: uso a função padrão
qsort() da biblioteca C para ordenar o vetor. É simples e eficiente para esse tamanho. - Sobre o comparador de
qsort : - O comparador recebe dois ponteiros para elementos e deve retornar:
- valor negativo se o primeiro elemento deve vir antes do segundo,
- zero se são equivalentes,
- valor positivo se o primeiro deve vir depois do segundo.
- Como quero ordem decrescente por nota, o comparador compara
b->grade com a->grade (ou inverte o sinal).
- O comparador recebe dois ponteiros para elementos e deve retornar:
Por que ordenar? Porque facilita pegar os “maiores” — após ordenar, os maiores aparecem no começo. Para
N=50
isso é trivial de executar em tempo de prova.
Passo 6
Detalhes de implementação e cuidados (passo a passo pro código):
- Declarar includes:
#include <stdio.h> , #include <stdlib.h> , #include <string.h> . - Definir
N e TOP com #define . - Declarar
struct Student com name e grade . - No
main() : - Criar vetor
Student students[N] e buffer de leitura. - Loop de
i = 0 até N-1 : - Ler nome via
fgets() , remover ‘\n’, copiar para students[i].name . - Ler linha para nota via
fgets() , usar sscanf() para obter students[i].grade . Repetir leitura se falhar.
- Ler nome via
- Calcular soma e média conforme Passo 4.
- Ordenar com
qsort(students, N, sizeof(Student), cmp) onde cmp é o comparador. - Percorrer do início e imprimir os nomes dos alunos com
grade > average até imprimir TOP ou acabar os alunos. - Se imprimir menos que
TOP , mostrar mensagem dizendo quantos foram impressos.
- Criar vetor
- Outras atenções:
- Truncar nomes que excedam
99 caracteres. - Mostrar a nota ao lado do nome (opcional, mas útil para conferir).
- Indicar ao usuário o formato de entrada (por exemplo, “Digite o nome” e “Digite a nota”).
- Truncar nomes que excedam
Passo 7
Resumo do método escolhido e por que:
- Usei
struct porque o enunciado pediu estrutura multivalorada. - Usei leitura por linha (
fgets + sscanf ) para robustez com nomes com espaços. - Usei
qsort por ser rápido e simples de usar; para N=50 qualquer método funciona, mas qsort reduz código e é padrão da linguagem. - Depois de ordenar em ordem decrescente, selecionar os primeiros com nota
média é direto e minimiza chance de erro durante a prova.
Passo 8
Segue abaixo o programa completo em C (pronto para compilar). Ele implementa tudo que expliquei: leitura robusta, cálculo de média, ordenação decrescente e impressão dos nomes dos até
5
maiores alunos acima da média.
Resposta
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 50
#define TOP 5
typedef struct {
char name[100];
float grade;
} Student;
int cmp_desc(const void *a, const void *b) {
const Student *sa = (const Student*)a;
const Student *sb = (const Student*)b;
if (sa->grade < sb->grade) return 1;
if (sa->grade > sb->grade) return -1;
return 0;
}
int main(void) {
Student students[N];
char buffer[256];
float sum = 0.0f;
printf("Entrada de dados da turma (total de %d alunos).\n", N);
for (int i = 0; i < N; ++i) {
/* Ler nome */
while (1) {
printf("Aluno %d - Digite o nome: ", i + 1);
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
printf("Erro de leitura. Tente novamente.\n");
continue;
}
/* remover newline final, se houver */
size_t len = strlen(buffer);
if (len > 0 && buffer[len - 1] == '\n') buffer[len - 1] = '\0';
/* Se string vazia, pedir novamente */
if (buffer[0] == '\0') {
printf("Nome vazio. Digite um nome valido.\n");
continue;
}
/* copiar para a struct */
strncpy(students[i].name, buffer, sizeof(students[i].name) - 1);
students[i].name[sizeof(students[i].name) - 1] = '\0';
break;
}
/* Ler nota com validação */
while (1) {
printf("Aluno %d - Digite a nota (por exemplo 7.5): ", i + 1);
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
printf("Erro de leitura. Tente novamente.\n");
continue;
}
float g;
if (sscanf(buffer, "%f", &g) == 1) {
if (g < 0.0f) {
printf("Nota negativa nao permitida. Digite novamente.\n");
continue;
}
students[i].grade = g;
sum += g;
break;
} else {
printf("Entrada invalida para nota. Use apenas numeros (ex: 8.25).\n");
}
}
}
/* Calcular a media */
float average = sum / (float)N;
printf("\nMedia da turma: %.2f\n", average);
/* Ordenar em ordem decrescente por nota */
qsort(students, N, sizeof(Student), cmp_desc);
/* Imprimir os TOP alunos com nota > media */
printf("\nAlunos com maiores notas acima da media (ate %d):\n", TOP);
int printed = 0;
for (int i = 0; i < N && printed < TOP; ++i) {
if (students[i].grade > average) {
printf("%d) %s - %.2f\n", printed + 1, students[i].name, students[i].grade);
printed++;
} else {
/* Como o vetor esta ordenado decrescentemente, ao encontrar a primeira nota <= media
nao ha mais alunos acima da media nos indices seguintes */
break;
}
}
if (printed == 0) {
printf("Nenhum aluno ficou acima da media.\n");
} else if (printed < TOP) {
printf("\nForam impressos apenas %d aluno(s) porque so havia %d acima da media.\n", printed, printed);
}
return 0;
}