Problema com listas em linguagem c

Saudações programadores.

Por motivos académicos tive de desenvolver algumas funções de listas no GLib. Neste caso eu estou a fazer um código conteúdo de inserção em uma lista duplamente ligada. E para mostrar o conteúdo da lista implementei uma função que imprime o conteúdo no ecrã. Eis aqui o codigo que desenvolvi.

Na main invoco as funções que foram definidas no utilizador.c . Insiro dois utilizadores e imprimo o conteúdo no ecrã.

[code]
#include <stdio.h>
#include <stdlib.h>

#include "Utilizador.h"

//------------------------------------------------------------------------------

//funcao para imprimir so um elemento da lista

//------------------------------------------------------------------------------

void showUtilizador2(gpointer dados_each, gpointer parametros) { //funcao para mostrar o utilizador

Utilizador *u = (Utilizador *) dados_each;

printf("\n---------------------------------\n"); //rever isto melhor
printf("%s |%s |%s |%d | %s | %f\n", u -> nome , u -> codigo , u -> passe , u -> idade , u -> morada , u -> saldo);

}

//------------------------------------------------------------------------------

//------------------------------------------------------------------------------

int main(void) {

GList *lista = NULL;

//--------------------------------------------------------------------------

Utilizador u3 = consUtilizador(&quot;50055&quot; , &quot;ola&quot; , 50.0 , &quot;Sergio&quot; , 21 , &quot;rua&quot;);

lista = InsereUtilizador(lista , u3);

//--------------------------------------------------------------------------

Utilizador u4 = consUtilizador(&quot;50056&quot; , &quot;ola&quot; , 50.0 , &quot;Sergio&quot; , 21 , &quot;rua&quot;);

lista = InsereUtilizador(lista , u4);

printf(&quot;Conteudo\n\n&quot;);

g_list_foreach(lista, (GFunc) showUtilizador2 , NULL);

return (EXIT_SUCCESS);

}[/code]

No utilizador.c estão implementados as funções de inserção na lista.


//funcao para criar um utilizador

//------------------------------------------------------------------------------

GList* InsereUtilizador(GList *lista , Utilizador u) {  //falta inserir condiçoes de segurança

    GList *aux = 0;

    //..........................................................................

    lista = g_list_append(lista,&u);

    return lista;

    //..........................................................................

} //fim de funcao

//------------------------------------------------------------------------------

//funcao para construir uma estrutura di tipo Utilizador

//------------------------------------------------------------------------------

Utilizador consUtilizador(char *codigo , char *passe , float saldo , char *nome , int idade , char *morada) {

	Utilizador aux;

        strcpy(aux.codigo,codigo);
        strcpy(aux.passe,passe);
        aux.saldo = saldo;
        strcpy(aux.nome,nome);
        aux.idade = idade;
        strcpy(aux.morada,morada);

        return aux;                      }

O problema ocorre quando executo este código. Não ocorre nenhume falaha de segmentação no entanto quando em teoria deveria ser imprimido no ecrã, "Sergio 50055 … , Sérgio 50056" , o programa imprime "Sérgio 50055 … , Sérgio 50055". Ou seja o ultimo utilizador inserido substitui todos os outros.

Eu tive a tentar procurar o erro e quando faço as seguintes alterações, no main.c , a lista imprime direitinha.

[code]
#include <stdio.h>
#include <stdlib.h>

#include "Utilizador.h"

//variaveis global

//------------------------------------------------------------------------------

//funcao para imprimir so um elemento da lista

//------------------------------------------------------------------------------

void showUtilizador2(gpointer dados_each, gpointer parametros) { //funcao para mostrar o utilizador

Utilizador *u = (Utilizador *) dados_each;

printf("\n---------------------------------\n"); //rever isto melhor
printf("%s |%s |%s |%d | %s | %f\n", u -> nome , u -> codigo , u -> passe , u -> idade , u -> morada , u -> saldo);

}

//------------------------------------------------------------------------------

//------------------------------------------------------------------------------

int main(void) {

GList *lista = NULL;

//--------------------------------------------------------------------------

Utilizador u3 = consUtilizador(&quot;50055&quot; , &quot;ola&quot; , 50.0 , &quot;Sergio&quot; , 21 , &quot;rua&quot;);

lista = g_list_append(lista,&u3);

//--------------------------------------------------------------------------

Utilizador u4 = consUtilizador(&quot;50056&quot; , &quot;ola&quot; , 50.0 , &quot;Sergio&quot; , 21 , &quot;rua&quot;);

lista = g_list_append(lista,&u4);

printf(&quot;A partir daqui\n\n&quot;);

 g_list_foreach(lista, (GFunc) showUtilizador2 , NULL);

return (EXIT_SUCCESS);

}[/code]

Ao fazer isto o programa retorna a lista direitinha, o que permite concluir que o problema reside na função "GList* InsereUtilizador(GList *lista , Utilizador u)" , mas já executei a mesma linha no main e funciona direitinho.

Já estive algumas horas a volta disto, mas ainda não consegui encontrar o erro, peço ajuda a toda a gente que tenha experiência com listas que me ajude a encontrar o problema neste código.

Desde já agradeço pelo tempo despendido.
Cumprimentos sergiosaturn.

Tente alterar a assinatura para:

Ou então:

Da forma que você está fazendo, você está criando uma cópia da variável utilizador dentro da função InsereUtilizador. E então, armazenando na lista o endereço dessa cópia.

Entretanto, essa cópia tem escopo local e é automaticamente descartada ao final da função.
Aquele endereço torna-se inválido.

Você só não obteve um segmentation fault por azar, devido a alguma característica do seu compilador.

Saudações ViniGodoy.

Desde já agradeço imenso pela sua sugestão.

Apliquei agora e funciona correctamente, e agora posso utilizar a funções que já tinha desenvolvido a varias semanas.

Voçe salvou-me mesmo a minha vida.

Muito obrigado e desejo-lhe imensas felicidades :slight_smile: .

O importante não é tanto a correção, mas… vc entendeu o problema e porque ela funciona?

Compreendi porque funciona assim, e ao compreender isso já consegui resolver outros problemas que tinha no mesmo código. Agora já posso fazer um código mais completo.

Mais uma vez muitíssimo obrigado :slight_smile: .

Legal. Cuidado que problemas de cópias acidentais são responsáveis por grandes perdas de performance no C e no C++. Felizmente no C++ é possível impedir essas cópias, através da sobrecarga do construtor, do construtor de cópia e do operador de =.