1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

Lista Ligada C

Discussão em 'Programação' iniciada por Neo4, 12 de Setembro de 2007. (Respostas: 25; Visualizações: 2262)

  1. Neo4

    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
     
  2. Nazgulled

    Nazgulled Power Member

    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.
     
  3. napalm

    napalm Power Member

    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: 12 de Setembro de 2007
  4. "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: 12 de Setembro de 2007
  5. Neo4

    Neo4 Banido

    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: 12 de Setembro de 2007
  6. FirewalkR

    FirewalkR Power Member

    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: 12 de Setembro de 2007
  7. Neo4

    Neo4 Banido

    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:
     
  8. 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;
    }
     
  9. Nazgulled

    Nazgulled Power Member

    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.
     
  10. Neo4

    Neo4 Banido

    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
     
  11. 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' ...
     
  12. napalm

    napalm Power Member

    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: 12 de Setembro de 2007
  13. Neo4

    Neo4 Banido

    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!
     
  14. greatbunzinni

    greatbunzinni Power Member

    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
     
  15. napalm

    napalm Power Member

    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.
     
  16. 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
     
  17. Neo4

    Neo4 Banido

    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 ;)
     
  18. 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
     
  19. Nazgulled

    Nazgulled Power Member

    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...
     
  20. Neo4

    Neo4 Banido

    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:
     

Partilhar esta Página