Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá
Preciso de ajuda em um programa em C.
O código já está quase pronto, mas ainda quero fazer algumas modificações.
Quero acrescentar no menu a opção de imprimir em ordem alfabética a lista de alunos aprovados. O aluno é considerado aprovado se a media for igual ou superior a 6. Preciso também de ter no menu a opção de imprimir em ordem alfabética o nome de todos os alunos.
Estou em dúvida de como posso fazer isso, se alguém puder ajudar, agradeço muito.
Segue o código que estou utilizando:
#include <stdio.h>#include <stdlib.h>
#include <string.h>
#ifndef __MSDOS__
#include <search.h>
#endif
#ifdef __linux__
#include <termios.h>
#include <unistd.h>
#define CLEAR_SCREEN "clear"
#define aacute "\xC3\xA1"
#define oacute "\xC3\xB3"
#define uacute "\xC3\xBA"
#define Uacute "\xC3\x9A"
int _getch ();
#else#endif
#endif
typedef struct TDAAluno {
char* matricula;
char* nome;
int idade;
char* serie;
float nota_de_trabalho;
float nota_de_prova;
float media;
} Aluno;
void* arranjo_inserir (void *arranjo, size_t *tamanho, size_t size, const void *dado);
void* arranjo_remover (void *arranjo, size_t *tamanho, size_t size, const void *dado);
void arranjo_recorrer (void *arranjo, size_t tamanho, size_t size, void *parametros, void (*funcion)(void*,void*));
void pausar (const char *mensagem);
char* ler_on_line (const char *mensagem);
char* ler_cadeia (const char *mensagem, char *cadeia);
int ler_inteiro (const char *mensagem);
float ler_decimal (const char *mensagem);
int ler_campo (FILE *arquivo, char *campo);
int comparar_aluno (const Aluno *aluno1, const Aluno *aluno2);
void imprimir_aluno (Aluno *dado, int *contador);
void imprimir_en_arquivo (Aluno *dado, FILE *arquivo);
const char *rota = "alunos.dat";
int main ()
{
Aluno *alunos = NULL;
size_t tamanho=0;
Aluno *dado, aluno;
int contador=0, opcao, subopcao;
char campo[255];
FILE *arquivo = fopen (rota, "r");
if (arquivo!=NULL)aluno.matricula = strdup (campo);
ler_campo (arquivo, campo);
aluno.nome = strdup (campo);
ler_campo (arquivo, campo);
aluno.idade = atoi (campo);
ler_campo (arquivo, campo);
aluno.serie = strdup (campo);
ler_campo (arquivo, campo);
aluno.nota_de_trabalho = atof (campo);
ler_campo (arquivo, campo);
aluno.nota_de_prova = atof (campo);
ler_campo (arquivo, campo);
aluno.media = atof (campo);
alunos = (Aluno*) arranjo_inserir (alunos, &tamanho, sizeof (Aluno), &aluno);
}
fclose (arquivo);
}system (CLEAR_SCREEN);
printf ("MENU" "\n");
printf ("1.- Inserir novo cadastro\n");
printf ("2.- Consultas\n");
printf ("3.- Atualizacao\n");
printf ("4.- Excluir registros\n");
printf ("5.- Ordenar registros\n");
printf ("6.- Listar registros\n");
printf ("7.- Sair\n");
printf ("Selecione uma opcao\n");
fflush (stdout);opcao = _getch ();
while (opcao<'1' || opcao>'7');
printf ("%c\n\n", opcao);
if (tamanho==0 && opcao!='1' && opcao!='7')pausar ("Nao ha registros.\n");
continue;
}
if (opcao<'5')aluno.matricula = ler_cadeia ("Insira a matricula do aluno", campo);
dado = (Aluno*) lfind (&aluno, alunos, &tamanho, sizeof (Aluno), (int(*)(const void*,const void*))comparar_aluno);
if (dado!=NULL)putchar ('\n');
imprimir_aluno (dado, &contador);
}
}
if (opcao=='1' && dado!=NULL)
printf ("O registro ja existe.\n");
else if (opcao>='2' && opcao<='4' && dado==NULL)
printf ("\nRegistro nao encontrado.\n");aluno.matricula = strdup (campo);
aluno.nome = ler_on_line ("Digite o nome do aluno");
aluno.idade = ler_inteiro ("Digite a idade");
aluno.serie = ler_on_line ("Digite a serie");
aluno.nota_de_trabalho = ler_decimal ("Digite a nota de trabalho");
aluno.nota_de_prova = ler_decimal ("Digite a nota de prova");
aluno.media = ler_decimal ("Digite a media");
alunos = (Aluno*) arranjo_inserir (alunos, &tamanho, sizeof (Aluno), &aluno);
printf ("\nRegistro adicionado com sucesso!\n");
break;printf ("Menu de modificacao de campos\n");
printf ("1.- nome\n");
printf ("2.- idade\n");
printf ("3.- serie\n");
printf ("4.- nota de trabalho\n");
printf ("5.- nota de prova\n");
printf ("6.- media\n");subopcao = ler_inteiro ("Selecione um numero de campo pra modificar");
if (subopcao<1 || subopcao>6)
printf ("Opcao invalida.\n");
} while (subopcao<1 || subopcao>6);free (dado->nome);
dado->nome = ler_on_line ("Digite o novo nome");
break;dado->idade = ler_inteiro ("Digite a nova idade");
break;free (dado->serie);
dado->serie = ler_on_line ("Digite a nova serie");
break;dado->nota_de_trabalho = ler_decimal ("Digite a nova nota de trabalho");
break;dado->nota_de_prova = ler_decimal ("Digite a nova nota de prova");
break;dado->media = ler_decimal ("Digite a nova media");
break;
}
printf ("\nRegistro atualizado com sucesso!\n");
break;memcpy (&aluno, dado, sizeof (Aluno));
alunos = (Aluno*) arranjo_remover ((void**)alunos, &tamanho, sizeof (Aluno), dado);
free (aluno.matricula);
free (aluno.nome);
free (aluno.serie);
printf ("Registro excluido com sucesso!\n");
break;qsort (alunos, tamanho, sizeof (Aluno), (int(*)(const void*,const void*))comparar_aluno);
printf ("Registros ordenados com sucesso!.\n");
break;contador = 0;
arranjo_recorrer (alunos, tamanho, sizeof (Aluno), &contador, (void(*)(void*,void*))imprimir_aluno);
printf ("Total de registros: %d.\n", contador);
break;
}
if (opcao!='7')
pausar ("");
} while (opcao!='7');
arquivo = fopen (rota, "w");
if (arquivo!=NULL)arranjo_recorrer (alunos, tamanho, sizeof (Aluno), arquivo, (void(*)(void*,void*))imprimir_en_arquivo);
fclose (arquivo);
}
return EXIT_SUCCESS;
}
void arranjo_inserir (void arranjo, size_t tamanho, size_t size, const void dado)
{
char *registro;
arranjo = realloc (arranjo, size * (*tamanho+1));
registro = (char*)arranjo + *tamanho * size;
memcpy (registro, dado, size);
(*tamanho)++;
return arranjo;
}
void arranjo_remover (void arranjo, size_t tamanho, size_t size, const void dado)
{
size_t i;
char *registro = (char*)arranjo;
for (i=0; i<*tamanho && dado!=registro; i++, registro+=size);
if (i<*tamanho)registro+=size;
memcpy (registro-size, registro, size);
}
(*tamanho)--;
arranjo = realloc (arranjo, size * (*tamanho));
}
return arranjo;
}
void arranjo_recorrer (void arranjo, size_t tamanho, size_t size, void parametros, void (funcion)(void,void*))
{
char *registro = (char*)arranjo;
if (tamanho>0)funcion (registro, parametros);
arranjo_recorrer (registro+size, tamanho-1, size, parametros, funcion);
}
}
int comparar_aluno (const Aluno aluno1, const Aluno aluno2)
{
return aluno1==aluno2 ? 0 : strcmp (aluno1->matricula, aluno2->matricula);
}
void imprimir_aluno (Aluno dado, int contador)
{
printf ("matricula : %s\n", dado->matricula);
printf ("nome : %s\n", dado->nome);
printf ("idade : %d\n", dado->idade);
printf ("serie : %s\n", dado->serie);
printf ("nota de trabalho: %g\n", dado->nota_de_trabalho);
printf ("nota de prova : %g\n", dado->nota_de_prova);
printf ("media : %g\n", dado->media);
putchar ('\n');
(*contador)++;
}
void imprimir_en_arquivo (Aluno dado, FILE arquivo)
{
fprintf (arquivo, "%s\t", dado->matricula);
fprintf (arquivo, "%s\t", dado->nome);
fprintf (arquivo, "%d\t", dado->idade);
fprintf (arquivo, "%s\t", dado->serie);
fprintf (arquivo, "%g\t", dado->nota_de_trabalho);
fprintf (arquivo, "%g\t", dado->nota_de_prova);
fprintf (arquivo, "%g\n", dado->media);
}
char ler_on_line (const char mensagem)
{
char on_line[255];
ler_cadeia (mensagem, on_line);
return strdup (on_line);
}
char ler_cadeia (const char mensagem, char *cadeia)
{
printf ("%s: ", mensagem);
scanf ("%[^\r\n]", cadeia);
getchar ();
return cadeia;
}
int ler_inteiro (const char *mensagem)
{
int inteiro;
printf ("%s: ", mensagem);
scanf ("%d", &inteiro);
getchar();
return inteiro;
}
float ler_decimal (const char *mensagem)
{
float decimal;
printf ("%s: ", mensagem);
scanf ("%f", &decimal);
getchar();
return decimal;
}
int ler_campo (FILE arquivo, char campo)
{
fscanf (arquivo, "%[^\t\n\r]", campo);
fgetc (arquivo);
return feof (arquivo) == 0;
}
void pausar (const char *mensagem)
{
printf ("%s\nPressione uma tecla para continuar . . . ", mensagem);
fflush (stdout);
_getch ();
}
#ifdef __linux__
int _getch ()
{
int ch;
struct termios oldt, newt;
tcgetattr (STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr (STDIN_FILENO, TCSANOW, &newt);
ch = getchar();
tcsetattr (STDIN_FILENO, TCSANOW, &oldt);
return ch;
}
#endif
Cara, eu dei uma limpada no seu programa, porque não deu pra entender muita coisa. Não implementei tudo, mas acho que você consegue entender e seguir.
Optei por deixar o nome e a matrícula em tamanho fixo p/ facilitar, mas caso seja realmente necessário ter tamanho dinâmico, você pode criar um utils.c com uma implementação de leitura bufferizada usando fgets e realloc (a princípio tomando cuidado de não estourar o heap).
main_aluno.c
#include <stdio.h>
#include "aluno.h"
int main(void) {
aluno.h
#define INVALIDO -1
#define _LEN_MATRICULA 5
#define _LEN_NOME 30
struct TDAAluno {
// Internal
// Insert-related
// Search-related
// We use a function pointer to pass custom comparison functions.
// Sort-related
// Option comparison Sort-related
// Listing
void imprimir();
aluno.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "aluno.h"
void _init_structures() {
void menu_operacoes() {
int compare_main_options(int opcao) {
int compare_sort_options(int opcao) {
int processar_opcao(int (*func)(int option)) {
void menu_inserir(struct TDAAluno * _tmp) {
int compare_by_nome(struct TDAAluno src, struct TDAAluno current) {
int compare_by_matricula(struct TDAAluno src, struct TDAAluno current) {
int existe_aluno(struct TDAAluno _tmp, int (func)(struct TDAAluno a, struct TDAAluno b)) {
size_t inserir(struct TDAAluno * _tmp) {
if (!existe_aluno(_tmp, &compare_by_nome) &&
!existe_aluno(_tmp, &compare_by_matricula)) {
void menu_ordenar() {
void ordenar(int sort_option) {
void imprimir() {
Utilizei ponteiros p/ funções porque 2 delas, as de comparação de nome e matrícula, por serem utilizadas tanto na busca de um elemento existente na lista quanto na ordenação (como critério) não precisam ser reimplementadas toda hora. No fonte tem um link explicativo. (No começo assusta, mas depois que você entende o que é e o que dá pra ser feito com isso é uma mão na roda).
A compilação foi feita com gcc -Wall -Wextra -std=c99 main_aluno.c aluno.c. O GCC emite 2 warnings sobre o último argumento passado pro qsort,mas não captei como se arruma isso.
PS: Coloque os frees antes de terminar o programa. Acabei esquecendo disso.