Jump to content
PsySc0rpi0n

Exercícios de Exames

Recommended Posts

PsySc0rpi0n

Tenho aqui alguns exames e estou a tentar resolvê-los...

Citação

2. Escreva um programa que permite gerir o IMC (índice da massa corporal). Crie uma

estrutura de dados que permita guardar o nome de uma pessoa, o peso (Kg) e a altura (m).

a) Escreva uma função que peça os dados de uma pessoa e os devolva. Os dados inseridos

relativamente ao peso e à altura só devem ser aceites se forem superiores a 30Kg e 1m,

respectivamente.

b) Escreva uma função que recebe o endereço de uma estrutura e o nome do ficheiro e

acrescenta a estrutura lida ao ficheiro.

c) Escreva uma função que consulta os dados armazenados no ficheiro e, para cada registo

guardado no ficheiro, calcula o IMC

IMC =

peso

altura 2

e escreve no monitor uma das frases:

IMC entre 18.6 e 24.9: Nome da pessoa, IMC, “Peso normal.”

IMC menor 15 ou maior 40: Nome da pessoa, IMC, “Por favor consulte o seu

médico!”

d) Escreva um programa que implemente o seguinte menu:

MENU:

1 – Inserir novo registo e guardar em ficheiro

2 - Calcular IMC

3 - Sair

E fiz o seguinte code mas tem alguns problemazitos que queria que me ajudassem a resolvê-los

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
  typedef struct{
  char nome[50];
  float peso;
  float altura;
  } Dados;

#define CLEAR_INPUT while (getchar ()!= '\n')
#define CLEAR_SCREEN puts("\x1b[H\x1b[2J")

//Alínea a) que pede os dados de uma pessoa e os guarda na estrutura Dados pessoa.
//Verifica também se o peso e a altura são superiores a 30 e a 1 respectivamente.
//Se não forem, volta a pedir os dados até que sejamsuperiores a 30 e a 1...
Dados PedeDados(){
  Dados pessoa;
  printf("Introduza o nome:\n");
CLEAR_INPUT;
  fgets(pessoa.nome, 50, stdin);
  if((pessoa.nome[strlen(pessoa.nome) - 1]) == '\n')
  pessoa.nome[strlen(pessoa.nome) - 1] = '\0';
  do{
  printf("Introduza o peso:\n");
  scanf("%f", &pessoa.peso);
  if(pessoa.peso <= 30)
	 printf("O peso tem que ser superior a 30Kg!\n");
  }while(pessoa.peso <= 30);
  do{
  printf("Introduza a altura:\n");
  scanf("%f", &pessoa.altura);
  if(pessoa.altura <= 1)
	 printf("A altura tem que ser superior a 1 metro!\n");
  }while(pessoa.altura <= 1);
return pessoa;
}
//Alínea b) pede uma função que recebe um ponteiro para uma estrutura e o nome
//de um ficheiro para guardar a estrutura nesse ficheiro
int EscreveEstruturaFicheiro(Dados *pessoa, char *nomeficheiro){
  FILE *pficheiro;
  if((pficheiro = fopen(nomeficheiro, "r+b")) == NULL){
  printf("Erro ao aceder ao ficheiro!\n");
  return -1;
  }

  fseek(pficheiro, 0, SEEK_END);
  fwrite(pessoa, sizeof(Dados), 1, pficheiro);
  fclose(pficheiro);
  return 0;
}
//Alínea c) que lê os dados do ficheiro e calcula o IMC para cada dado lido
int ConsultaDadosEscreveMonitor(){
  FILE *pficheiro;
  float imc;
  Dados *pessoatmp = NULL;

  if((pficheiro = fopen("dadospessoa.bin", "r+b")) == NULL){
  printf("Erro ao aceder ao ficheiro!\n");
  return -1;
  }
  while(fread(pessoatmp, sizeof(Dados), 1, pficheiro) != 0){
  imc = (pessoatmp->peso)/(pow(pessoatmp->altura, 2));
  if((imc >= 18.6) && (imc <= 24.9))
	 printf("%s, %.2f, Peso Normal!\n", pessoatmp->nome, imc);
  if((imc < 15) || (imc > 40))
	 printf("%s, %.2f, \"Por favor consulte o seu médico!\"\n", pessoatmp->nome, imc);
  }
  fclose(pficheiro);
  return 0;
}
//Alínea d) que pede o menu para usar as funções criadas anteriormente
int main (void) {
  char op;
  Dados pessoa;
  char nomeficheiro[25] = "dadospessoa.bin";

  CLEAR_SCREEN;
  do{
  printf("\t\tMENU\n");
  printf("\t(I)nserir novo registo e guardar em ficheiro\n");
  printf("\t(C)alcular IMC\n");
  printf("\t(S)air\n");
  scanf(" %c", &op);
  switch(tolower(op)){
	 case 'i': pessoa = PedeDados();
		   EscreveEstruturaFicheiro(&pessoa, nomeficheiro);
		   break;
	 case 'c': ConsultaDadosEscreveMonitor();
		   break;
	 case 's': break;
	 default : printf("Opção inválida!\n");
  }
  }while(op != 's');
  getchar ();
  return 0;
}
 

O primeiro problema é que quando peço os dados da pessoa, ele está a passar o nome em falso... Porquê?


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
thoga31

Eu (ainda) não sou grande um conhecedor de C, pelo que te vou apontar apenas duas incongruências no teu código:

  do{ // whatever
         if(pessoa.peso < 30)
                printf("O peso tem que ser superior a 30Kg!\n");
  }while(pessoa.peso <= 30);
  do{ // whatever
         if(pessoa.altura <= 1)
                printf("A altura tem que ser superior a 1 metro!\n");
  }while(pessoa.altura <= 1);

Na condição de saída do while tens <= e no if tens <. Decide qual deles queres. Se alguém introduzir um peso de 30 Kg, o programa não avisa mas o ciclo também não é interrompido.


Knowledge is free!

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Eu (ainda) não sou grande um conhecedor de C, pelo que te vou apontar apenas duas incongruências no teu código:

  do{ // whatever
	  if(pessoa.peso < 30)
			 printf("O peso tem que ser superior a 30Kg!\n");
  }while(pessoa.peso <= 30);
  do{ // whatever
	  if(pessoa.altura <= 1)
			 printf("A altura tem que ser superior a 1 metro!\n");
  }while(pessoa.altura <= 1);

Na condição de saída do while tens <= e no if tens <. Decide qual deles queres. Se alguém introduzir um peso de 30 Kg, o programa não avisa mas o ciclo também não é interrompido.

Obrigado... Bem visto... Erro meu...

Se conseguires ajudar-me na minha questão inicial, agradecia!


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
thoga31

Como disse, ainda não sou grande conhecedor de C, há aqui quem perceba potes acima de mim :P

Anyway, o que queres dizer com "ele está a passar o nome em falso"?


Knowledge is free!

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Não me deixa inserir o nome. É algum caractere que está a passar para o fgets e depois o programa passa logo para o peso. Mas esse até já resolvi...

Agora está outro problema na função que consulta os dados do ficheiro e os escreve no ecrã. Está-me a dar falha de segmentação.


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
HappyHippyHippo

O primeiro problema é que quando peço os dados da pessoa, ele está a passar o nome em falso... Porquê?

enquanto não elucidares a comunidade o que queres dizer com isto, acho pouco provável que terás muito sucesso na resolução do problema.

no entanto, vejo um problema muito pior ao referido pelo @thoga31 (se fosse pascal ele diria logo qual seria o problema :D , por outro lado, eu não :D )

int ConsultaDadosEscreveMonitor(){
  FILE *pficheiro;
  float imc;
  Dados *pessoatmp = NULL; // <--- isto é um ponteiro, não existe um espaço de memória para guardar os dados da estrutura Dados
  Dados pessoa;            // <--- uma instância da estrutura Dados

  if((pficheiro = fopen("dadospessoa.bin", "r+b")) == NULL){
         printf("Erro ao aceder ao ficheiro!\n");
         return -1;
  }
  while(fread(pessoatmp, sizeof(Dados), 1, pficheiro) == 1){ // <---- estás a usar um ponteiro para nada que na realidade aponta para NULL
                                                             //       que deverá lançar um segmentation fault !!
  while(fread(&pessoa, sizeof(Dados), 1, pficheiro) == 1){    // leitura correcta
         imc = (pessoatmp->peso)/(pow(pessoatmp->altura, 2));
         if((imc >= 18.6) && (imc <= 24.9))
                printf("%s, %.2f, Peso Nomral!\n", pessoatmp->nome, imc);
         if((imc < 15) || (imc > 40))
                printf("%s, %.2f, \"Por favor consulte o seu médico!\"\n", pessoatmp->nome, imc);
  }
  fclose(pficheiro);
  return 0;
}

Edited by HappyHippyHippo

IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Ok, já corrigi e coloquei assim:

//Alínea c) que lê os dados do ficheiro e calcula o IMC para cada dado lido
int ConsultaDadosEscreveMonitor(){
 FILE *pficheiro;
 float imc;
 Dados pessoatmp;
 if((pficheiro = fopen("dadospessoa.bin", "rb")) == NULL){
printf("Erro ao aceder ao ficheiro para consulta!\n");
return -1;
 }
 while(fread(&pessoatmp, sizeof(Dados), 1, pficheiro) != 0){
imc = (pessoatmp.peso)/(pow(pessoatmp.altura, 2));
if((imc >= 18.6) && (imc <= 24.9))
  printf("%s, %.2f, Peso Nomral!\n", pessoatmp.nome, imc);
if((imc < 15) || (imc > 40))
  printf("%s, %.2f, \"Por favor consulte o seu médico!\"\n", pessoatmp.nome, imc);
 }
 fclose(pficheiro);
 return 0;
}

Não percebi porque dizes que a leitura dos dados está a ser mal feita e por isso alterei a comparação do while de == 1 para !=0... Não sei se era a isto a que te referias, happyhippy... Mas não me mostra nada do que tenho no ficheiro... Ainda não fiz contas mas só se as contas não estiverem incluídas em nenhuma das condições dos dois if's...

Bem, pelos vistos, o code estava bem mesmo com o == 1 no fread... Acontece que o enunciado não contempla valores maiores que 24.9 e menores que 40... Não sei qual é a lógica mas ok... Como os meus valores de IMC davam 27.7, os dois if's falhavam as condições e por isso não mostravam nada...

Vou passar ao exercício das listas ligadas...

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
HappyHippyHippo

Não percebi porque dizes que a leitura dos dados está a ser mal feita e por isso alterei a comparação do while de == 1 para !=0... Não sei se era a isto a que te referias, happyhippy...

eu disse que estava a ser mal feita pela razão que alteras-te e corrigiste o código ...


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
PsySc0rpi0n

eu disse que estava a ser mal feita pela razão que alteras-te e corrigiste o código ...

Mas com o == 1 não funcionava? Devia funcionar já que o fread retorna o número de elementos lidos com sucesso... Por isso, pelo menos, pensei que devia funcionar!


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
thoga31

O problema não estava no ==1, não reparaste que alteraste todo o fread?...


Knowledge is free!

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Ok... Então o fread não estava mal... O que estava mal era a variável estar a apontar para null... E como consequência, o fread já dava problemas...

Agora o exercício das listas ligadas diz:

3. Considere que os dados dos jogadores de todas equipas de Futebol da 1a divisão

Portuguesa se encontram guardadas numa lista ligada cujos nós são do seguinte tipo

struct jogadoresPrimeiraDivisao{

char Pais [50];

char Nome [50];

unsigned short int idade;

struct jogadoresMundial *prox;

};

Escreva uma função que recebe como parâmetro o endereço do primeiro elemento da lista e

retorne a idade do jogador mais novo, a idade média dos jogadores e o número de jogadores

de nacionalidade Portuguesa.

Seria ilegítimo criar, não uma, mas sim 4 funções? Uma para o jogador mais novo da lista, outra para a idade média dos jogadores e outra para o número de jogadores de nacionalidade portuguesa. No final, haveria uma outra que iria chamar cada uma das 3 anteriores...


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
HappyHippyHippo

depende do professor.

visto que estás a praticar, faz as duas soluções


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Rui Carlos

O exercício não obriga a usar apenas uma função, pelo que acho que faz todo o sentido ter as 3 funções em separado.

(Por outro lado, ao usares 3 funções, vais percorrer a lista 3 vezes, o que ainda assim não me parece muito problemático.)

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Este já foi feito... Se quiserem coloco aqui o code par comentarem...

E já resolvi mais uns quantos... Mas como digo, os enunciados criam sempre ambiguidade... Deixam sempre dúvidas...

Quando se fala numa função que retorna um valor, não pressupõe o uso da palavra reservada "return"? Eu entendo que sim. Ora, se um enunciado pede para uma função RETORNAR 3 valores, das duas uma:

Ou não se respeita o enunciado e não se usa a palavra reservada "return" recorrendo-se a ponteiros ou então o exercício é impossível de se fazer seguindo à risca o enunciado. Isto é a minha opinião!

Estou a fazer este agora:

Construa uma função que permite comparar o tamanho de caracteres de dois ficheiros de texto. A função

recebe o nome dos dois ficheiros a comparar e devolve: 0 (zero) se os ficheiros tiverem exatamente o

mesmo número de caracteres; -1 (menos um) se o primeiro ficheiro for maior que o segundo; 1 (um) se o

segundo ficheiro for maior que o primeiro.

Para já, acho que "comparar o tamanho de caracteres de dois ficheiros" não faz sentido. O tamanho de caracteres é sempre 1 byte, certo? Devia estar escrito "comparar o número de caracteres de dois ficheiros".

Depois, espaços e mudanças de linha, devem contar como caracteres ou não?

Bem, eu nem sei como vou fazer isto mas vou pensar um pouco...

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
Rui Carlos

Este já foi feito... Se quiserem coloco aqui o code par comentarem...

E já resolvi mais uns quantos... Mas como digo, os enunciados criam sempre ambiguidade... Deixam sempre dúvidas...

Quando se fala numa função que retorna um valor, não pressupõe o uso da palavra reservada "return"? Eu entendo que sim. Ora, se um enunciado pede para uma função RETORNAR 3 valores, das duas uma:

Ou não se respeita o enunciado e não se usa a palavra reservada "return" recorrendo-se a ponteiros ou então o exercício é impossível de se fazer seguindo à risca o enunciado. Isto é a minha opinião!

Nada te impede de retornar um apontador para um array para 3 valores, ou para uma struct com 3 valores, por exemplo.

Para já, acho que "comparar o tamanho de caracteres de dois ficheiros" não faz sentido. O tamanho de caracteres é sempre 1 byte, certo? Devia estar escrito "comparar o número de caracteres de dois ficheiros".

Depois, espaços e mudanças de linha, devem contar como caracteres ou não?

Bem, eu nem sei como vou fazer isto mas vou pensar um pouco...

O meu conselho é contares o número de bytes (é que se queres complicar, então também ias ter que saber o encoding do ficheiro).

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Pois, já são pormenores que requerem alguma experiência...

Bem o exame está feito...

O exame era isto:

w25t.jpg

Vou deixar o code que escrevi para cada pergunta:

1)

int contaNPrimos (int *vector, int N){
  int i, ok = 0, contaprimos = 0;
  for(i = 0; i < N; i++){
  ok = primo(*(vector + i));
  if(ok == 1)
	 contaprimos++;
  }
  return contaprimos;
}

2.a)

typedef strcut{
  int cod;
  char cat;
  char *nome[50];//O * está errado. Já não sei se o corrigi a passar para a folha de ponto ou não...
}UTENTE;

2.b)

void MostraDados(UTENTE paciente){
  printf("O código do utente é %d\n", paciente.cod);
  printf("A categoria do utente é %d\n", paciente.cat);//aqui devo-me ter enganado e coloquei %d em vez de %c mas já não me recordo
  printf("O nome do utente é %s\n", paciente.nome);
}

2.c)

int ValorPagaCat(char cat){
  switch(tolower(cat)){
  case 'a': return 1;
  case 'b': return 2;
  case 'c': return 3;
  default: printf("Categoria inválida!\n");
  }
}

2.d)

void imprimeTicket(char *nomeficheiro, int codutente){
  FILE *fp;
  UTENTE paciente;
  int ok = 0;
  if((fp = fopen(nomeficheiro, "rb")) == NULL){
  printf("Erro ao aceder ao ficheiro para leitura!\n");
  return -1;
  }

  while((fread(&paciente, sizeof(UTENTE), 1, fp)) != 0){
  if(codutente == paciente.cod){
	 MostraDados(paciente);
	 printf("O valor a pagaré %d €!\n", ValorPagarCat(paciente.cat));
	 ok = 1;
  }
  }
  if(!ok)
  printf("Não foi encontrado nenhum utente com o código fornecido!\n");
}

3)

int contaCaracteres(char *nomeficheiro){
  int i, contaLetra = 0;
  char letra;
  FILE *fp;

  if((fp = fopen(nomeficheiro, "r")) == NULL){
  printf("Erro ao aceder ao ficheiro para leitura!\n");
  return -1;
  }
  while((fread(&letra, sizeof(char), 1, fp)) == NULL){
  if((strcmp(letra, "#") == 0) || (strcmp(letra, "@")==0))
	 contaletra++;
  }
  return contaLetra;
}

4)

char *Partido(ELEICOES *partido){//aqui era para ter devolvido os resultados mas acabei por mostrar os resultados na própria função. Portanto ficou mal aqui
  int maior = partido->votos,
   menor = partido->votos;
  char partidomais[50] = partido->nome,
 partidomenos[50] = partido->nome;//tanto nesta inicialização como na anterior, não sei se deixei ficar, sem querer, um asterisco antes do nome das variáveis. Se deixei, não devia...
  while((partido->prox) != NULL){
  if(partido->votos > maior) //aqui se calhar devia ter colocado os parêntesis à volta do partido->votos e não coloquei!
	 maior = partido->votos;
	 strcpy(partidomenos, partido->nome);
  }
  if(partido->votos < menor){
	 menor = partido->votos;
	 strcpy(partidomenos, partido->nome);
  }
  partido = partido->prox;
  }//acho que me esqueci de fechar este parêntesis do while
  printf("O partido mais votado foi %s e o menos votado foi %s!\n", partidomais, partidomenos);
}

E foi isto. O exame era fácil e fora algumas distracções, espero que esteja tudo minimamente aceitável...

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
HappyHippyHippo

de quanto tempo era isso ?

1)

int conta_primos (int *vector, int N)
{
 int i, total = 0;
 for (i = 0; i < N; i++)
   total += primo(vector[i]);
 return total;
}

2.a)

enum Categoria
{
 A = 'A',
 B = 'B',
 C = 'C'
};

struct Utente
{
 int codigo;
 enum Categoria categoria;
 char nome[64];
};

2.b)

void apresenta_utente (struct Utente utente)
{
 printf("Utente\n");
 printf("\tCodigo : %d\n", utente.codigo);
 printf("\tCategoria : %c\n", utente.categoria);
 printf("\tNome : %s\n", utente.nome);
}

2.c)

// double para poder usar centimos
double valor_a_pagar (enum Categoria categoria)
{
 return (double)categoria - 'A' + 1;
}

2.d)

int imprimeTicket (const char * filename, int codigo)
{
 struct Utente utente;
 FILE * file = NULL;

 if (filename == NULL || (file = fopen(filename, "rb")) == NULL)
 {
   // deixar tratamento de erro para a função que chamou
   return -1;
 }

 while (fread(&utente, sizeof(struct Utente), 1, file))
 {
   if (utente.codigo == codigo)
   {
     apresenta_utente(utente);
     printf("\nValor a pagar : %d\n", valor_a_pagar(utente.categoria));

     fclose(file);
     return 0;
   }
 }

 fclose(file); // <------ nunca esquecer !!!!!
 return -2;
}

3)

int conta_caracteres (const char * filename)
{
 int total = 0;
 FILE * file = NULL;
 int c;

 if (filename == NULL || (file = fopen(filename, "r")) == NULL)
 {
   // deixar tratamento de erro para a função que chamou
   return -1;
 }

 while ((c = fgetc(file)) != EOF)
 {
   total += c == '#' || c == '@';
 }

 fclose(file); // <------ nunca esquecer !!!!!
 return total;
}

4)

int menor_e_maior(struct Eleicoes * lista, char * menor, char * maior)
{
 struct Eleicoes * pt_menor = lista, * pt_maior = lista;

 if (lista == NULL || menor == NULL || maior == NULL)
 {
   return -1;
 }

 lista = lista->prox;
 while (lista != NULL)
 {
   if (lista->votos < pt_menor->votos)
   {
     pt_menor = lista;
   }

  if (lista->votos > pt_maior->votos)
  {
     pt_maior = lista;
  }

   lista = lista->prox;
 }

 strpcy(menor, pt_menor->partido);
 strpcy(maior, pt_maior->partido);

 return 0;
}

------

edit : no exercício 3, a variável "c" foi alterada para int (EOF requirmenet)

Edited by HappyHippyHippo

IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Eram 2 horas... Não demos o tipo de dados "enum"...


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Eu tentei seguir o mais à risca possível os enunciado. No exercício 4, se calhar devia ter enviado os resultados como tu fizeste em vez de os ter apresentado na própria função...

Mas do que fiz, está muito mal ou devo-me safar? O exame estava cotado para 14. Os outros 6 valores eram para o projecto. E esses 6, já estão garantidos...


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.