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’.
  • 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:
\bar{g} = \dfrac{1}{N} \sum_{i=1}^{N} g_i
  • 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).
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):
  1. Declarar includes: #include <stdio.h> , #include <stdlib.h> , #include <string.h> .
  2. Definir N e TOP com #define .
  3. Declarar struct Student com name e grade .
  4. 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.
    • 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.
  5. 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”).

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;
}

Exercícios relacionados