Lista Ligada C

Neo4

Banido
Boas,

estou aqui com um problema que me está a moer a mioleira >(
alguém me sabe dizer porque é que esta função so guarda os ultimos 2 elementos da lista ( a ideia é adicionar um elemento ao fim da lista) é que se eu corro por exemplo tres vezes a funcao e vou a imprimi-la so sao mostrados os 2 ultimos elementos e a funcao de imprimir esta bem pois se os adicionar á cabeça ela imprime tudo direitinho...

Código:
Lista addfim(Lista a, int d){

  Lista new, aux=a;
 

 if(a == NULL) {
   new=(Lista) malloc(sizeof(Lista));
   new->valor = d;
   new->seg= a; return(new);
  }

  while(aux->seg != NULL)
     aux= aux->seg;
  new=(Lista) malloc(sizeof(Lista));
  new->valor=d;
  new->seg= NULL;
  aux->seg=new;
 
return aux;
}


e uma soluçao para isto?!


Obrigado
 
Código:
Lista addFim(Lista a, int d) {
	Lista new;
	
	if(a == NULL) {
		new = (Lista) malloc(sizeof(Lista));
		
		new->valor = d;
		new->seg = a;
		
		return new;
	} else {
		a->seg = addFim(a->seg, d);
		
		return a;
	}
}

1) Sugiro um código assim. Está mais limpo, e não repetes código como no teu exemplo. Penso que percebes cada linha e não é preciso explicar...
2) Tenho um feeling que aquele malloc está incorrecto. Tanto o teu como o meu, porque eu usei como base o teu código. No entanto, não consigo ver se está certo ou errado sem que me apresentes a estrutura definida e o código onde declaras a primeira lista e chamas pela primeira vez a função addFim.
3) Sugestão: Acho um bocado inconsistente usares palavras em inglês e português e andares a misturar tudo.
 
What the... o malloc não devolve ponteiros?
Ah ok, provavelmente esse Lista é um typedef de um ponteiro para a estrutura.
Anyway está ai algo de muito errado, o malloc nesse caso está a alocar o tamanho do ponteiro e não da estrutura. Como essa maravilha não te está a dar um segmentation fault é algo que desconheço, mas provavelmente foi sorte.
 
Última edição:
"What the... o malloc não devolve ponteiros?"

sim realmente o malloc retorna um ponteiro em que este aponta para o endereço em memoria que tu pediste para reservar, caso a instrucao malloc tenha sido realizada com sucesso, caso contrario esta funcao ira retornar null.



é assim se nao me engano penso que tens a definicao de malloc mal estruturada na tua cabeça.. entao é assim o malloc (funcao em C) recebe como um inteiro que representa o tamanho em bytes que desejas "reservar" em memória.. um pormenor que eu reparei é que tu no teu código em seguida ao malloc, nao fazes a verificaçao se a instrução foi realizada com sucesso, ou seja:


ptr = malloc(n * sizeof(int));
if( ptr == NULL ) {
printf(``Out of memory\n'');
return NULL;
}


Espero que isto te possa ajudar;)


Cumprimentos.
 
Última edição:
sim a Lista é apontador como podem ver pelo typedef:

Código:
typedef struct slista{
int valor;
struct slista *seg;
}lista, *Lista;

Nazgulled funcionou! muito obrigado ;)

mas alguem me sabe explicar porque é que a minha está mal? eu penso que é porque o apontador da lista ficava a apontar para o penultimo elemento(ou seja era quando adicionava o ultimo elemento) será por isso?



obrigado mais uma vez :arrow:
 
Última edição:
mas alguem me sabe explicar porque é que a minha está mal? eu penso que é porque o apontador da lista ficava a apontar para o penultimo elemento(ou seja era quando adicionava o ultimo elemento) será por isso?

O problema era mesmo esse, o "return aux;". Provavelmente estavas a chamar essa função com algo como "x = addFim(x, 1);" e o x passava a apontar para o penúltimo elemento. Podes resolver o problema no teu código mudando para "return a;".

O código do Nazgulled está muito mais legível mas introduz recursividade e no caso de ser uma lista muito grande perdes alguma performance e memória. (na verdade parece-me o código de alguém habituado a pensar em programação em linguagens funcionais :Winkani:, mas posso tar errado :) )
 
Última edição:
O problema era mesmo esse, o "return aux;". Provavelmente estavas a chamar essa função com algo como "x = addFim(x, 1);" e o x passava a apontar para o penúltimo elemento. Podes resolver o problema no teu código mudando para "return a;".

O código do Nazgulled está muito mais legível mas introduz recursividade e no caso de ser uma lista muito grande perdes alguma performance e memória. (na verdade parece-me o código de alguém habituado a pensar em programação em linguagens funcionais :Winkani:, mas posso tar errado :) )

pois era mesmo isso que eu tinha... sim tens razao o meu problema aqui entao foi com o apontador para o inicio da lista...

muito obrigado pela vossa ajuda

:arrow:
 
se fosse eu faria algo do género:

Código:
Lista addFim(Lista a, int d) {
    Lista new, aux;

    new = (Lista) malloc(sizeof(lista));
    new -> valor = d;
    new -> seg = NULL;

    if(new == NULL){
       printf("Erro no malloc");
       return NULL; /* apos invocar addFim deve-se verificar o resultado */
   }
    
    if(a == NULL) {
       return new;
    } 
    else {
       for(aux=a; aux->seg!=NULL; aux=aux->seg){;}
       aux->seg = new;
    }
    return a;
}
 
Vendo agora a tua estrutra e se optares por usar o meu código...

Troca esta linha:
new = (Lista) malloc(sizeof(Lista));

Por esta:
new = (Lista) malloc(sizeof(lista));

Se fosse eu, dava-lhe antes nomes tipo struct {} Nodo, *Lista. Teres struct {} lista, *Lista, pode ser umpouco confuso, só mais uma sugestão...

@FirewalkR
Nem por isso... :P Sempre programei em linguagens imperativas, só desde o ano passado na universidade é que aprendi/usei a minha primeira linguagem funcional, Haskell e apesar de ter ficado a perceber, gostar mais ao menos, não fiquei com vicios, porque continuo a prefeir programar mais em linguagens imperativas. Atenção, não estou a dizer que é melhor ou pior, apenas a minha preferência, talvez por habito ao longo dos anos, não sei, mas prefiro imperativas em especial o C.
 
qual é a diferença de por Lista ou lista? é que comigo sempre funcionou direito pondo o apontador quando vejo codigo d outras pessoas umas x vejo com o o nome outras com o apontador. faz alguma diferença?

thanks
 
quando usas 'lista' estas a alocar espaço para a tua estrutura ( 1 inteiro e 1 apontador para o seguinte ),
quando usas 'Lista' estas a alocar espaço para um apontador para a tua estrutura
um apontador são 4bytes em sistemas de 32bit e 8bytes em sistemas 64
ou seja com lista estas a reservar 8/12 bytes e com Lista estas a reservar 4/8
Nem sei como é que com a versão que usa Lista no malloc isso aidna não deu nenhum 'segmentation fault' ...
 
Código:
malloc(sizeof(struct slista))
Já agora, é uma prática horrivel dar dois significados completamente distintos a lista e Lista. Não sei sequer se isso compila com -ansi -pedantic.
Aconselho a escolher nomes mais explicitos, como Lista e ListaPtr.
 
Última edição:
sinceramente eu nunca tinha percebido a diferença! agora ja estou a ver... isto é mau de se dizer mas desleixei-me na parte das listas na epoca de aulas agora ando a estuda-las sozinho para o exame da epoca especial(ainda bem que houve!)
e tenho mais uma duvida.... desta vez é na remoçao do ultimo elemento da lista,
bem eu começei com isto:
Código:
Lista dellst(Lista a){

Lista new=a;
 
  if(new->seg == NULL){
     free(new); return(a);}
    else{
         new->seg=dellst(new->seg);
              }

}
ao correr o que ele fazia era substituir o ultimo elemento por zero! e se tentava apagar o outro pum core dumped... porque?!

e depois fiz isto:
Código:
Lista dellst(Lista a){

Lista new=a->seg;
 
  if(a->seg == NULL){
     ;free(a); return(new);}
    else{
         a->seg= dellst(a->seg);
              }

}

só a 2º é que funcionou (nem sei porque é que me lembrei de tentar aquilo) mas eu nao percebo como é que funciona aquele "return new" se a lista new aponta para a->seg que neste caso é NULL!!

obrigado pela ajuda que tem prestado!
 
se fosse eu faria algo do género:

Código:
Lista addFim(Lista a, int d) {
    Lista new, aux;

    new = (Lista) malloc(sizeof(lista));
    new -> valor = d;
    new -> seg = NULL;

    if(new == NULL){
       printf("Erro no malloc");
       return NULL; /* apos invocar addFim deve-se verificar o resultado */
   }
    
    if(a == NULL) {
       return new;
    } 
    else {
       for(aux=a; aux->seg!=NULL; aux=aux->seg){;}
       aux->seg = new;
    }
    return a;
}

Eu faria basicamente a mesma coisa mas separava a lista e os elementos da lista em duas estruturas diferentes. Assim trocava-se um pouco mais de código por uma maior clareza da coisa e dava a hipótese de adicionar umas coisinhas boas pelo meio. Por exemplo, um apontador na estrutura da lista com a função de apontar sempre para o último elemento da lista é algo jeitoso de se ter.

Mas isso sou eu que gosto de pilhas e de filas de espera :D
 
sinceramente eu nunca tinha percebido a diferença! agora ja estou a ver... isto é mau de se dizer mas desleixei-me na parte das listas na epoca de aulas agora ando a estuda-las sozinho para o exame da epoca especial(ainda bem que houve!)
e tenho mais uma duvida.... desta vez é na remoçao do ultimo elemento da lista,
bem eu começei com isto:
Código:
Lista dellst(Lista a){

Lista new=a;
 
  if(new->seg == NULL){
     free(new); return(a);}
    else{
         new->seg=dellst(new->seg);
              }

}
ao correr o que ele fazia era substituir o ultimo elemento por zero! e se tentava apagar o outro pum core dumped... porque?!

e depois fiz isto:
Código:
Lista dellst(Lista a){

Lista new=a->seg;
 
  if(a->seg == NULL){
     ;free(a); return(new);}
    else{
         a->seg= dellst(a->seg);
              }

}

só a 2º é que funcionou (nem sei porque é que me lembrei de tentar aquilo) mas eu nao percebo como é que funciona aquele "return new" se a lista new aponta para a->seg que neste caso é NULL!!

obrigado pela ajuda que tem prestado!
Get your shit together. Se queres ajuda faz por tê-la:
1. Onde dá o core dump?
2. Usa um debugger (em linux usa o gdb)
3. Sê mais explicito tanto no código como nos problemas/dúvidas que estás a ter.
 
Neo4, em relação ao teu código deves evitar a recursividade pois é algo penoso para a computação tanto em consumo de memoria para a stack (guardar o contexto a cada invocação da função), como as mudanças de contexto são coisas pesadas para o processador,
Na tua primeira del estas a libertar memoria free(new) e como new = a, depois retornas um apontador pra lá... um 'return NULL' deve resolver...
Na segunda já fazes new = a->seg, o 'return new' dá NULL logo não deve dar problemas ...

em relação à questão de remover eu faria algo como:
Código:
Lista dellst(Lista a){

   Lista aux;

   if(a != NULL){
      if(a->seg==NULL){
         free(a);
         return NULL;
      }
      else{
         for(aux=a;(aux->seg)->seg != NULL; aux=aux->seg){;}
         free(aux->seg);
         aux->seg = NULL;
      }
   }
   return a;
}
greatbunzinni, tens toda a razão se isto fosse uma queue um apontador para o ultimo ficava a matar e evitava o ciclo for que tenho na inserção obrigando a percorrer toda a lista
 
Neo4, em relação ao teu código deves evitar a recursividade pois é algo penoso para a computação tanto em consumo de memoria para a stack (guardar o contexto a cada invocação da função), como as mudanças de contexto são coisas pesadas para o processador,
Na tua primeira del estas a libertar memoria free(new) e como new = a, depois retornas um apontador pra lá... um 'return NULL' deve resolver...
Na segunda já fazes new = a->seg, o 'return new' dá NULL logo não deve dar problemas ...

entao no caso de apagar um elemento tenho que retornar NULL ou seja essa lista é vazia?
eu estava a pensar que tinha k retornar um apontador para a cabeça da lista com se faz nas operaçoes de adicionar...

bem voces estao aqui a dar-me uns avanços bem jeitosos!

muito obrigado ;)
 
o que eu disse é que quando só tens um elemento e o eliminas tens de retornar NULL e tu no primeiro exemplo estavas a dar um endereço de memoria invalido.

outra coisa que tens em falha nas tuas implementações é que se a lista for vazia ( NULL ) isso dá chocapic... :P
 
Acho que já consegui perceber que és de Braga ou pelo menos estudas na Universidade do Minho aqui como eu, btw, em que curso? CC ou LEI? Eu ando é a rasca com AL, adiante...

Vocês estão todos a dar dicas boas de boa programação e depuramento de problemas e tal, mas sinceramente, para o que ele quer, agora não interessa para nada. A ideia dele é passar no exame o que eu não percebo como é possível alguém ainda estar a fazer exame a PI porque o exame de recurso era de caras mesmo, só eu pa me esquecer da inscrição para fazer melhoria, ficava com 20 à cadeira, enfim, exame cagado mesmo, anyway...

Como isto é po exame/cadeira e não é para te preocupares muito com todos os pormenores de tudo e mais alguma coisa porque os profs não vão avaliar o facto de libertares memória ou não (desde que não dê nenhum segmentation fault [ou outro erro qq], tens a cotação toda). Eu faria assim:

Percorria cada elemento da lista até ao element seguinte ser nulo. Durante cada iteração da lista, inseria o elemento numa nova lista, quando o seguinte fosse nulo, não inseria o elemento actual pois é o último da lista. Depois, bastava retornar a nova lista.

Pode não ser a melhor hipotese para um código perfeito e tal, mas funciona sem problemas e se tivesses a pergunta para fazeres uma função que passasse como argumento uma lista e devolvesse essa lista sem o último elemento, a minha maneira resultava e tinhas a cotação toda que é o que te interessa na epoca especial de exames. Para aprender a programares a sério, tens tempo... Agora preocupa-te em passar no exame.

That's what I think...
 
o que eu disse é que quando só tens um elemento e o eliminas tens de retornar NULL e tu no primeiro exemplo estavas a dar um endereço de memoria invalido.

outra coisa que tens em falha nas tuas implementações é que se a lista for vazia ( NULL ) isso dá chocapic... :P

ahh ja percebi... é que eu as ideias ate as tenho mas ainda nao sei bem esses pormenores de sintaxe nas listas...

Nazgulled,

sim sou de braga e estudo LEI, eu achei bem mais faceis os dois primeiros exames do que o de recurso mas nao ha que mentir e tens razao mesmo assim era facil...
quanto ainda estar a fazer isto é simples,,, projecto de LI nao fiz nada so fazia os relatorios, estudei isto 15 dias antes do exame e 10 dias agora acho que aprendi bem para o tempo que foi...


obrigados a todos :009:
 
Back
Topo