Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

BrunoT

Retornar string de uma função

Mensagens Recomendadas

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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.