Jump to content

exercicio ponteiro para ponteiro


luismsantana

Recommended Posts

boa tarde ...

eu tenho este exercicio (alignea) para fazer:

d) Efectue a seguinte alteração na função proposta na alínea anterior. Os alunos a eliminar da

lista original devem ser inseridos numa outra lista (a lista vai conter os nós dos alunos com média

inferior à média da turma). Esta nova função deve receber como argumento adicional uma

referência para o ponteiro para o início da nova lista (i.e., recebe um ponteiro para esse ponteiro).

o código da função da aligena c) penso que seja (se tiver feito bem):

al elimina(al p, al pal[])
{
 int alunos=0;
 float media_geral=0;
 al aux,anterior=NULL;
 while(p!=NULL)
 {
   alunos++;
   media_geral+=p->media;
   p=p->prox;
 }
 media_geral=media_geral/alunos;
 aux=p;
 while(aux!=NULL)
 {
   if(aux->media<media_geral){
     anterior->prox=aux->prox;
     free(aux);
   }
   anterior=aux;
   aux=aux->prox;
 }
 return p;
}

e a estrutura declarada:

typedef struct aluno student,*al;
struct aluno{
 char nome[50];
 int notas[5];
 float media;
 al prox;
};

alguma dica de como fazer esta alteração?

abraço

Link to comment
Share on other sites

... se tiver feito bem ...

al elimina(al p, al pal[])
{
   while(p!=NULL)
   {
       /* ... */
       p=p->prox;
   }
   aux=p;
   while(aux!=NULL)
   {
       /* ... */
   }
   /* ... */
}

Nope, nao esta bem feito.

Repara: no fim do primeiro ciclo p tem NULL; depois metes esse NULL no aux e nunca executas o segundo ciclo.

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Link to comment
Share on other sites

uma iteração

- por cada iteração

- uma comparação

- se dentro do parâmetro (inferior à média)

- adicionar à segunda lista

- remover da lista original

sim, essa parte eu percebo e sei como remover ... mas é suposto criar um array de ponteiros, certo? a minha dúvida principal é se crio esse array na main ou na função e depois como manipular para mover da primeira lista para a segunda, utilizando esse array!

Repara: no fim do primeiro ciclo p tem NULL; depois metes esse NULL no aux e nunca executas o segundo ciclo.

ah pois é, tens razão ... thanks ... mas entao como faço para correr a lista novamente no segundo ciclo? ponho o aux=p logo no inicio?

Link to comment
Share on other sites

certo, sorry ja to com a cabeça em água xD mas e em relação à segunda parte da dúvida?

não te posso responder sem saber mais sobre a estrutura "al".

não faço ideia se é um elemento de uma "lista ligada" ou de uma "lista duplamente ligada"

por outras palavras : tens de fazer post da definição do "al"

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

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

typedef struct aluno student,*al;
struct aluno{
   char nome[50];
   int notas[5];
   float media;
   al prox;
};
void grava_ficheiro(int n_al, char *nome)
{
   int i,j;
   student aux;
   FILE *f;
   f=fopen(nome,"wb");
   i=0;
   while(i<n_al)
   {
       printf("nome do aluno:");
       scanf("%s",&aux.nome);
       printf("\n");
       for(j=0;j<5;j++)
       {
           printf("nota%d:",j);
           scanf("%d",&aux.notas[j]);
       }
       printf("\n");
       fwrite(&aux,sizeof(student),1,f);
       i++;
   }

   fclose(f);
}

al busca_ficheiro_lista(char *nome1)
{
   int total=0,i,j,total_notas=0,nota,c[20];
   float media=0;
   al p=NULL,novo;
   student aux,b[20];
   FILE *f;

   f=fopen(nome1,"rb");
   while(fread(&aux,sizeof(student),1,f)==1){
       novo=(al) malloc(sizeof(student));
       strcpy(novo->nome,aux.nome);
       for(i=0;i<5;i++){
           c[i]=aux.notas[i];
           nota=c[i];
           for(j=0;j<5;j++)
               novo->notas[i]=nota;
       }
       novo->prox=NULL;
       for(i=0;i<5;i++){
           total_notas+=c[i];
       }
       media=(float)total_notas/5;
       novo->media=media;
       if(p==NULL)
           p=novo;
       else
           p->prox=novo;
   }
   fclose(f);
   return p;
}

al elimina(al p, al pal[])
{
   int alunos=0;
   float media_geral=0;
   al aux,anterior=NULL;
   while(p!=NULL)
   {
       alunos++;
       media_geral+=p->media;
       p=p->prox;
   }
   media_geral=media_geral/alunos;
   aux=p;
   while(aux!=NULL)
   {
       if(aux->media<media_geral){
           anterior->prox=aux->prox;
           free(aux);
       }
       anterior=aux;
       aux=aux->prox;
   }
   return p;
}

void main()
{
}

está aí o código todo ... ainda nao tenho nada na main porque ainda nao executei, so compilei, e fui fazendo alignea a alignea ...

a indentacção do programa não é assim, quando colei aqui ficou assim ... peço desculpa entao desde já por isso!

Edited by pmg
Indentacao
Link to comment
Share on other sites

ainda nao tenho nada na main porque ainda nao executei, so compilei ...

Vai executando testes enquanto vais contruindo o programa, funcao a funcao. A compilacao isoladamente nao e suficiente para teres uma base solida.

Assim, ao introduzires uma funcao nova, podes usar as funcoes antigas com a certeza que estao bem.

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Link to comment
Share on other sites

isto vai ser complicado ...

achas que chegas lá se te disser só para andares com ponteiros de um lado para o outro ?

gostava de poder dizer que sim, mas nao ainda nao domino esta parte dos arrays de ponteiros :\

Vai executando testes enquanto vais contruindo o programa, funcao a funcao. A compilacao isoladamente nao e suficiente para teres uma base solida.

Assim, ao introduzires uma funcao nova, podes usar as funcoes antigas com a certeza que estao bem.

obrigado pela dica 😉

isto vai ser complicado ...

achas que chegas lá se te disser só para andares com ponteiros de um lado para o outro ?

é tipo isto?

void transfere(plivro *p1, plivro *p2)
{
 plivro aux;
 if(*p1 == NULL)
   return; /*lista L1 vazia*/
 aux = *p1;
 *p1 = aux->prox;
 aux->prox = *p2;
 *p2 = aux;
}
Link to comment
Share on other sites

estas a ir no bom caminho, apesar de teres imensos problemas no código ...

estive a ver o código que apresentaste no primeiro post, acho melhor corrigires esse primeiro.

vais ver que depois disso terás melhor ideia do que tens a fazer

notas a ver :

- porque gravas um registo diretamente no ficheiro, desse modo nunca terás na lista para ser manipulado

- a tua função de leitura do ficheiro tem 50% do código desnecessário que não faz nada

- cria uma lista no main e tenta apresentar os dados da lista no ecrã

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

- a tua função de leitura do ficheiro tem 50% do código desnecessário que não faz nada

boa tarde

a função como está funciona ...

al busca_ficheiro_lista(char *nome1)
{
 int total=0,i,j,total_notas=0,nota,c[20];
 float media=0;
 al p=NULL,novo;
 student aux,b[20];
 FILE *f;
 f=fopen(nome1,"rb");
 while(fread(&aux,sizeof(student),1,f)==1){
   novo=(al) malloc(sizeof(student));
   strcpy(novo->nome,aux.nome);
   for(i=0;i<5;i++){
     c[i]=aux.notas[i];
     nota=c[i];
     for(j=0;j<5;j++)
       novo->notas[i]=nota;
   }
   novo->prox=NULL;
   for(i=0;i<5;i++){
     total_notas+=c[i];
   }
   media=(float)total_notas/5;
   novo->media=media;
   if(p==NULL)
     p=novo;
   else
     p->prox=novo;
 }
 fclose(f);
 return p;
}

como faço para fazer retirar o código desnecessário?

Link to comment
Share on other sites

1º :

 novo=(al) malloc(sizeof(student));
 strcpy(novo->nome,aux.nome);
 for(i=0;i<5;i++){
  c[i]=aux.notas[i];
  nota=c[i];
  for(j=0;j<5;j++)
   novo->notas[i]=nota;
 }
 novo->prox=NULL;

>>

 novo=(al) malloc(sizeof(student));
 memcpy(novo, aux, sizeof(student)); // uma função para copiar tudo de uma estrutura para outra do mesmo tipo
 novo->prox=NULL;

2º :

 for(i=0;i<5;i++){
  total_notas+=c[i];
 }
 media=(float)total_notas/5;
 novo->media=media;

o cálculo da média deveria ser fora desta função pela simples razão que alterares um único valor de uma nota qualquer, terás de recalcular a média.

conclusão, deverias criar uma função que calcule esse valor e chamar-la sempre que necessário (re)calcular a média do aluno

void calcular_media(al aluno)
{
 float total_notas;
 for(i = 0; i < 5; i++)
  total_notas += aluno->notas[i];
 aluno->media = total_notas / 5;
}

al busca_ficheiro_lista(char *nome1)
{
 // código inicial de leitura do registo ...

 // calcular a média
 calcular_media(novo);

 if(p==NULL)
  p=novo;
 else
  p->prox=novo;
}
IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

 memcpy(novo, aux, sizeof(student)); // uma função para copiar tudo de uma estrutura para outra do mesmo tipo

memcpy, nao conhecia ... os profs nao ensinam mesmo nada -.-

obrigado HappyHippy ... agora outra coisa, antes de entrar na parte de mexer com os ponteiros, podes analisar-me a função de eliminar, por favor? nao percebo porque nao está a dar :s

al elimina(al p)
{
 int alunos=0;
 float media_geral=0;
 al aux,anterior=NULL;
 aux=p;
 while(p!=NULL)
 {
   alunos++;
   media_geral+=p->media;
   p=p->prox;
 }
 media_geral=media_geral/alunos;

 printf("%f\n",media_geral);
 while(aux!=NULL)
 {
   if(media_geral>aux->media && anterior==NULL)
   {
     anterior=aux->prox;
     free(aux);
   }
   else{
     if(media_geral>aux->media)
     {
       anterior->prox=aux->prox;
       free(aux);
     }
   }

   printf("chega aqui?\n");
   anterior=aux;
   aux=aux->prox;
 }
 return p;
}
Link to comment
Share on other sites

1º - novamente o cálculo da média geral é um passo que deverá ser separado numa função à parte

double calcular_media_geral(al p)
{
int alunos = 0;
double sum = 0.0;

while(p!=NULL)
{
 alunos++;
 sum += p->media;
 p = p->prox;
}

// verificar sempre o numero de elementos nunca tentes fazer a divisão por zero !!!
if (alunos == 0)
 return 0;
return sum / alunos;
}

agora podes ter um código muito mais limpo

al elimina_abaixo_media(al p)
{
al aux = p, anterior=NULL;

// calcular a media global
double media_global = calcular_media_global(p);

while(aux!=NULL)
{
 // recalcular a media do aluno porque não sei se andaste a mexer nas notas dele
 calcular_media(aux);

 // filtar à partida pela média
 if (media_geral > aux->media)
 {
   // verificar se é o primeiro da lista
   if(anterior==NULL)
   {
     // dizer que o primeiro da lista é o seguinte
     p = p->next;
     // eliminar o registo
     free(aux);
     // vamos verificar o novo primeiro da lista
     aux = p;
   }
   else
   {
     // remover o elemento da lista
     anterior->prox = aux->prox;
     // eliminar o registo
     free(aux);
     // vamos processar o seguinte da lista
     aux = anterior->prox;
   }
 }
 else
 {
   // avançar o ponteiro (deixar estar na lista)
   anterior = aux;
   aux = aux->next;
 }
}

return p;
}
IRC : sim, é algo que ainda existe >> #p@p
Link to comment
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.