Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Luiz Picolo

[Resolvido] Implementar função strcpy com ponteiros

Recommended Posts

Pessoal bom dia. Na faculdade o professor pediu para implementar esta função utilizando ponteiros e alocando memória. Como sou iniciante no C, eu não sei onde estou errado.

Na verdade eu fiz essa função sem a necessidade de usar o ponteiro duplo **origem, mas, o exercicio teria que sair com todos esses requisitos, ponteiro duplo e memoria alocada.

 

No final, aux contem a string trocada, porém, não estou conseguindo manter (ou retornar nao sei), quando termina a função.

 

outro fato e que eu tenho que trocar o conteudo referenciado pelo ponteiro, e a função nao pode retornar nada, somente void.

 

Desculpe se nao fui claro, iniciante como ja disse.

 

/* 
* File:   main.c
* Author: Picolo
*
* Created on 24 de Outubro de 2012, 10:42
*/

#include <stdio.h>
#include <stdlib.h>

/*
* 
*/
void strcopy(char *destino, char **origem)
{
   int cont = 0;
   char *aux, *aux2 = *&origem;
   while (aux2[cont] != 0)
   {
       cont++;
   }

   aux = malloc((cont + 1) * sizeof (char));

   int i = 0;
   while (aux2[i] != 0)
   {
       aux[i] = aux2[i];
       i++;
   }

   aux[cont] = 0;
}

int main(int argc, char** argv)
{
   char *destino, origem[50] = "teste2";

   strcopy(&destino, &origem);
   printf("\n\n%s", destino);
   return (EXIT_SUCCESS);
}


Compartilhar este post


Link para o post
Compartilhar em outros sites

Falta você apontar a memória alocada com o seu ptr "destino".

 

Da forma que está fazendo, está é criando memory leak.

 

Esqueci de mencionar a variável cont, não está atribuindo nenhum novo valor a ela. Aí quando você faz isto:

 

aux[cont] = 0;

 

Esta perdendo a referência a toda a memória alocada anteriormente.

Imagino que cont deva ser a variável que deve ser utilizada no while, não precisa utilizar aquela variável i.

 

Espero ter ajudado, FLW!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá e obrigado por sua resposta.

Bem, a variável

cont

faz referência a última valor alocado para a string, ou seja, nesta caso ele esta vazio, eu acrescento o \0.

 

Então, mas como eu faria este apontamento?

 

*destino = aux?

 

Sinceramente essa parte que não estou compreendendo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pera, uma coisa não entendi nesse exercício: o professor pediu para implementar a strcpy() com alocação dinâmica?

 

E você vai ficar dando free() toda vez que fizer isso e parar de usar a string copiada? Pois sem isso só está criando memory leaks...

 

Não me faz sentido.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Seguinte: um ponteiro é, simplificadamente, uma variável que armazena endereços de memória. Então, se você acessa o valor que tem no ponteiro, é apenas um endereço.

 

Quando você utiliza *<ponteiro>, você usa um operador unário que retorna o que está armazenado no lugar em que o endereço do ponteiro aponta para. Quando utiliza &<variavel>, você retorna o endereço da memória onde está localizada a variável - o que é um ponteiro.

 

Mas um ponteiro também é um tipo de variável, e, como tudo, é armazenado na memória. Então, se você usa &<ponteiro>, você pega o endereço da memória em que está armazenado o endereço para o qual o ponteiro aponta. Mas onde guardar o endereço de um ponteiro? Você guarda um endereço em um ponteiro não é? Então você precisa de um ponteiro de ponteiro.

 

Exemplos:

 

int x = 42; // Armazenamos 42 no endereço da variável x.
int *x_p = &x; // Armazenamos o endereço da variável x.
int y = *x_p; // Acessamos o que está armazenado no endereço armazenado pelo ponteiro x_p.
int **x_p_p = &x_p; // Armazenamos o endereço do ponteiro x_p.
int *y_p = *x_p_p; // Armazenamos o endereço armazenado no ponteiro x_p.
int z = **x_p_p; // Por meio dessa construção acessamos o próprio x.
// No final, x == y resulta em true, y == z resulta em true.

 

Então, sabendo disso, podemos implementar assim:

OBS: sempre use nomes bons para variáveis, nomes descritivos, assim seu código fica mais auto-explicativo. Ah, e bastantes comentários.

 

#include <stdio.h>
#include <stdlib.h>

// Calculamos o tamanho da string, sem incluir o '\0' final.
size_t strlength(char *string)
{
char *position = NULL;

/*
 * O for abaixo funciona assim:
 * 1º, fazemos o ponteiro "position" apontar para o início da string.
 * 2º, a cada iteração, nós incrementamos o ponteiro "position".
 * 3º, o for continuará seu loop enquanto o valor armazenado no endereço apontado por position for diferente de 0. Assim, quando for igual a '\0' (o fim da string), o loop terminará.
 */
for(position = string; *position; ++position)
	/* Não fazer nada. */;

// Retorna a diferença entre os endereços - o que dá o tamanho da string, sem o '\0' do final.
	return position - string;
}

void strcopy(char **destino, char *origem)
{
char *position_origem = NULL, *position_destino = NULL; // Responsáveis pela posição nas strings.
size_t length = strlength(origem); // O tamanho da string.

// Alocamos o tamanho necessário para a string copiada. Caso falhar (ou seja, malloc() retornar null), terminamos. SEMPRE cheque o retorno de malloc().
       *destino = malloc(length + 1);
if(!*destino) {
	exit(1);
}

// Enquanto não encontrarmos o '\0' da origem, continuamos. Veja bem que isso faz praticamente o mesmo da função strlength(), então a organização do programa não está perfeita - poderíamos melhorar o design para evitar duplicação de código.
for(position_origem = origem, position_destino = *destino; *position_origem; ++position_origem, ++position_destino) {
	*position_destino = *position_origem; // Copiamos o valor.
}
}

int main(void)
{
char *destino = NULL, origem[] = "teste2";

strcopy(&destino, origem); // Antes estava strcopy(&destino, &origem) - mas o correto é strcopy(&destino, origem) por origem já ser um ponteiro.
printf("\n\n%s", destino);

free(destino); // NÃO se esqueça disso.
return 0; // 0 significa EXIT_SUCCESS.
}

 

Espero que tenha entendido.

 

 

Abraços :D

Compartilhar este post


Link para o post
Compartilhar em outros sites

Galera, muito obrigado por todos os comentários e respostas.

Renato Utsch, muito bem explicado, esta era a resposta que eu estava esperando.

Obrigado a todos.

 

Tópico Resolvido.

Compartilhar este post


Link para o post
Compartilhar em outros sites
Galera, muito obrigado por todos os comentários e respostas.

Renato Utsch, muito bem explicado, esta era a resposta que eu estava esperando.

Obrigado a todos.

 

Fico feliz que pude ajudar :thumbsup:

 

Uma observação: a subtração entre ponteiros tem como resultado um valor de tipo ptrdiff_t.

 

Mas então, com a solução que eu fiz acima, eu teria que fazer um cast de valor signed para unsigned em algum lugar, visto que malloc tem como parâmetro size_t. Como eu sei que o resultado será sempre positivo, não acho que tenha problema. Ou não?

 

Então o resultado com cast explícito seria:

 

#include <stdio.h>
#include <stdlib.h>

// Calculamos o tamanho da string, sem incluir o '\0' final.
size_t strlength(char *string)
{
       char *position = NULL;

       /*
        * O for abaixo funciona assim:
        * 1º, fazemos o ponteiro "position" apontar para o início da string.
        * 2º, a cada iteração, nós incrementamos o ponteiro "position".
        * 3º, o for continuará seu loop enquanto o valor armazenado no endereço apontado por position for diferente de 0. Assim, quando for igual a '\0' (o fim da string), o loop terminará.
        */
       for(position = string; *position; ++position)
               /* Não fazer nada. */;

       // Retorna a diferença entre os endereços - o que dá o tamanho da string, sem o '\0' do final.
               return (size_t) position - string; // Sempre será positivo.
}

void strcopy(char **destino, char *origem)
{
       char *position_origem = NULL, *position_destino = NULL; // Responsáveis pela posição nas strings.
       size_t length = strlength(origem); // O tamanho da string.

       // Alocamos o tamanho necessário para a string copiada. Caso falhar (ou seja, malloc() retornar null), terminamos. SEMPRE cheque o retorno de malloc().
       *destino = malloc(length + 1);
       if(!*destino) {
               exit(1);
       }

       // Enquanto não encontrarmos o '\0' da origem, continuamos. Veja bem que isso faz praticamente o mesmo da função strlength(), então a organização do programa não está perfeita - poderíamos melhorar o design para evitar duplicação de código.
       for(position_origem = origem, position_destino = *destino; *position_origem; ++position_origem, ++position_destino) {
               *position_destino = *position_origem; // Copiamos o valor.
       }
}

int main(void)
{
       char *destino = NULL, origem[] = "teste2";

       strcopy(&destino, origem); // Antes estava strcopy(&destino, &origem) - mas o correto é strcopy(&destino, origem) por origem já ser um ponteiro.
       printf("\n\n%s", destino);

       free(destino); // NÃO se esqueça disso.
       return 0; // 0 significa EXIT_SUCCESS.
}

 

Ou:

 

#include <stdio.h>
#include <stdlib.h>

// Calculamos o tamanho da string, sem incluir o '\0' final.
ptrdiff_t strlength(char *string)
{
       char *position = NULL;

       /*
        * O for abaixo funciona assim:
        * 1º, fazemos o ponteiro "position" apontar para o início da string.
        * 2º, a cada iteração, nós incrementamos o ponteiro "position".
        * 3º, o for continuará seu loop enquanto o valor armazenado no endereço apontado por position for diferente de 0. Assim, quando for igual a '\0' (o fim da string), o loop terminará.
        */
       for(position = string; *position; ++position)
               /* Não fazer nada. */;

       // Retorna a diferença entre os endereços - o que dá o tamanho da string, sem o '\0' do final.
               return position - string; // Sempre será positivo.
}

void strcopy(char **destino, char *origem)
{
       char *position_origem = NULL, *position_destino = NULL; // Responsáveis pela posição nas strings.
       size_t length = (size_t) strlength(origem); // O tamanho da string.

       // Alocamos o tamanho necessário para a string copiada. Caso falhar (ou seja, malloc() retornar null), terminamos. SEMPRE cheque o retorno de malloc().
       *destino = malloc(length + 1);
       if(!*destino) {
               exit(1);
       }

       // Enquanto não encontrarmos o '\0' da origem, continuamos. Veja bem que isso faz praticamente o mesmo da função strlength(), então a organização do programa não está perfeita - poderíamos melhorar o design para evitar duplicação de código.
       for(position_origem = origem, position_destino = *destino; *position_origem; ++position_origem, ++position_destino) {
               *position_destino = *position_origem; // Copiamos o valor.
       }
}

int main(void)
{
       char *destino = NULL, origem[] = "teste2";

       strcopy(&destino, origem); // Antes estava strcopy(&destino, &origem) - mas o correto é strcopy(&destino, origem) por origem já ser um ponteiro.
       printf("\n\n%s", destino);

       free(destino); // NÃO se esqueça disso.
       return 0; // 0 significa EXIT_SUCCESS.
}

 

Alguma sugestão, guidjos?

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.