Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

Sign in to follow this  
BrunoT

Retornar string de uma função

Recommended Posts

BrunoT

Boas pessoal !

Vou tentar explicar o que se passa, mas antes disso vou copiar as partes do código que interessa

typedef struct sEquipa {
char nome[20];
char pais[20];
int nCc;
struct sEquipa *seg;
} Equipa, *lEquipa;

typedef struct sCiclista {
char nome[20];
int idade;
char nac[20];
int dorsal;
char equipa[20];
int tEtapas;
int pEtapas;
int pMont;
int etaPer;
struct sCiclista *seg;
} Ciclista, *lCiclista;

char* retEquipa (lEquipa l3, int opc) {

int cont =1;

	while ( l3!= NULL ) {

		if ( opc == cont ) return l3->nome;
		else { 
			l3 = l3->seg;
			cont++;
		}
	}

return NULL;

}

b->equipa = retEquipa (l3,equip);

O que queria é que a função retEquipa retornasse o nome da equipa para adicionar a estrutura do ciclista. Alguém me pode ajudar ?

Deixem-me também dizer que o b é do tipo apontador para Ciclista ...

Cumprimentos

Bruno Araújo

Share this post


Link to post
Share on other sites
Localhost

Vou tentar estruturar isto o máximo possível.

Tu sabes que:

- O nome de uma string é na verdade um ponteiro para o seu 1º elemento.

- Quando uma função termina todas as variáveis "pertencentes" à função são destruídas. (stack frame da função)

Seguindo esta teoria tu ao declarares uma string local, quando a função terminar o seu "conteúdo" vai ser destruído, como o nome da string é um ponteiro para o seu primeiro elemento tu ao fazeres return (literalmente) desse ponteiro vais estar a retornar o endereço de algo que já foi destruído (visto que a função já terminou), então vais ter com o velho amigo "segmentation fault".

Agora que já percebeste a teoria, percebes que não podes retornar (literalmente) uma string.

Para solucionares este problema tens duas opções:

- Declaras a string como global (isto não se costuma fazer).

- Declaras um ponteiro do tipo char * e alocas dinamicamente uma string.

Aconselho-te a seguires a 2ª opção, depois basta retornares o endereço e recebê-lo com um ponteiro.

Só para terminar o post, lembra-te que alocando dinamicamente o que alocaste só vai ser destruído quando tu quiseres (tipicamente com função free), ou seja, podes sempre trabalhar com um ponteiro. Para alocares utiliza por exemplo, a função malloc. 


here since 2009

Share this post


Link to post
Share on other sites
BrunoT

Obrigado Localhost.

Já percebi a lógica da coisa, posso até usar o strdup penso eu. Vou ver se soluciono o problema.

:D

Share this post


Link to post
Share on other sites
Localhost

Dei-te duas maneiras de como resolver esse problema, agora é só aplicares. Pelo que vi do código já tens conhecimentos em ponteiros, portanto é só alocares e depois trabalhares com o ponteiro que recebe o endereço.

Já agora deixo aqui um exemplo:

char *heap = (char *)malloc(sizeof(char) * N);
return heap;

Neste caso, heap será o ponteiro que vai receber o endereço. Estamos a alocar uma string com N caracteres.


here since 2009

Share this post


Link to post
Share on other sites
TheDark

- O nome de uma string é na verdade um ponteiro para o seu 1º elemento.

- Quando uma função termina todas as variáveis "pertencentes" à função são destruídas. (stack frame da função)

Seguindo esta teoria tu ao declarares uma string local, quando a função terminar o seu "conteúdo" vai ser destruído, como o nome da string é um ponteiro para o seu primeiro elemento tu ao fazeres return (literalmente) desse ponteiro vais estar a retornar o endereço de algo que já foi destruído (visto que a função já terminou), então vais ter com o velho amigo "segmentation fault".

A teoria está bem. Só que não se aplica a este caso, e acabaste por matar uma mosca com um míssil, e o código continua a não funcionar porque está-se a tentar atribuir o valor de um apontador a um array na última linha de código apresentada.

sCiclista e sEquipa são nós de listas simplesmente ligadas. Ao retornar l3->nome, não é o endereço de uma variável local que vai ser retornado, é o valor de um apontador que existe num desses nós, o qual continua a ser válido após a função terminar.

A única alteração que vejo ser necessária é substituir a tal última linha por um strcpy, copiando o resultado da chamada à função retEquipa para o campo b->equipa.

Já agora, uma sugestão que não sei se podes seguir: em vez de teres o nome da equipa como um array de caracteres em sCiclista, não podes ter antes um apontador para sEquipa? Evitavas andar a copiar strings, e tinhas a informação de equipa toda "agarrada" ao ciclista.


Desaparecido.

Share this post


Link to post
Share on other sites
Localhost

Sinceramente não li o código dele, apenas li o titulo do tópico e vi que a dúvida era retornar uma string por isso ter dito aquilo. De qualquer das formas fica a informção.


here since 2009

Share this post


Link to post
Share on other sites
BrunoT

Obrigado aos dois, desde já.

Realmente o que eu tava a fazer era uma autêntica estupidez, o que tinha feito estava certo, só precisava de fazer

strcpy (retEquipa (l3,equip),b->equipa);

Uma distracção :s

Quanto à ultima sugestão do The Dark ... é realmente uma boa ideia que melhoraria a perfomance, vai já directo para a lista de optimizações.

Mais uma vez, obrigado aos dois.

Share this post


Link to post
Share on other sites
TheDark

Sinceramente não li o código dele, apenas li o titulo do tópico e vi que a dúvida era retornar uma string por isso ter dito aquilo.

Muito má política, responder sem entender o problema ;P


Desaparecido.

Share this post


Link to post
Share on other sites
BrunoT

Tinha tudo para funcionar, mas realmente não funciona ... ao listar o ciclista, o nome da equipa aparece em branco.

Share this post


Link to post
Share on other sites
TheDark

Se usaste a função strcpy como puseste ali, tens os argumentos ao contrário. O 1º parâmetro é o destino, e o 2º é a origem.


Desaparecido.

Share this post


Link to post
Share on other sites
BrunoT

Claro, tinha que a minha distracção entrar ao serviço. :D

Já agora, isto é um trabalho para a universidade ... acham que depois de entregue e avaliado, é útil postar o programa aqui no forum ? Ou não é aconselhável ?

Cumprimentos

Share this post


Link to post
Share on other sites
TheDark

Aconselhável? Claro! :D Posta no Wiki com um título sugestivo :)


Desaparecido.

Share this post


Link to post
Share on other sites
BrunoT

O trabalho é entregue no próximo Domingo, avaliado na Terça e postado no wiki na Quarta :confused:

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
Sign in to follow this  

×

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.