2010-01-29 5 views
0

Je suis en train d'écrire ma propre fonction de copie de chaîne. Les travaux suivants:C: manquant une certaine logique avec les pointeurs des choses

char *src, *dest; 
src = (char *) malloc(BUFFSIZE); 
//Do something to fill the src 
dest = (char *) malloc(strlen(src) + 1); 
mystringcpy(src, dest); 

void mystringcopy(char *src, char *dest) { 
    for(; (*dest = *src) != '\0'; ++src, +dest); 
} 

Mais cela ne fonctionne pas:

char *src, *dest; 
src = (char *) malloc(BUFFSIZE); 
//Do something to fill the src 
mystringcpy(src, strlen(src), dest); 

void mystringcopy(char *src, size_t length, char *dest) { 
    dest = (char *)malloc(length + 1); 
    for(; (*dest = *src) != '\0'; ++src, +dest); 
} 

et je ne comprends pas pourquoi ... Est-ce l'allocation de mémoire dans une fonction appelée une erreur?

+3

'* src = (char *) malloc (taille du buffer)' ne devrait pas avoir un chef de file '' *. – spoulson

+0

Quelle est l'erreur? Pour une chose, mystringcopy n'est pas encore défini, sauf si vous avez un prototype quelque part. –

+0

Oh son juste me donner une erreur de segmentation ... Je vais vérifier les autres solutions dans une seconde ... – Legend

Répondre

2

Vous n'avez pas vraiment dit ce que "fonctionne" signifie, mais je suppose que vous êtes confus pourquoi dest n'est pas en train de changer la nouvelle mémoire dans la fonction d'appel.

La raison en est que, dans votre fonction mystringcopy, le paramètre dest est une copie du pointeur dest dans la fonction appelante.

Vous assignez ensuite cette copie à un nouveau tampon, faire la copie, puis la copie va. L'original est inchangé. Vous devez passer dest comme pointeur (à un pointeur).

Aussi, je suppose que vous avez écrit ce que vous avez fait de la mémoire car il ne doit pas compiler tout comme (mauvais déréférencer dans la fonction d'appel). Voici le code fixe:

char *src, *dest; 
src = (char *)malloc(BUFFSIZE); // no dereference on src, it's a pointer 

//Do something to fill the src 
mystringcpy(src, strlen(src), &dest); // pass the address of dest 

// take a pointer to a char* 
void mystringcopy(char *src, size_t length, char **dest) { 
    // now you should dereference dest, to assign to 
    // the char* that was passed in 
    *dest = (char *)malloc(length + 1); 

    // for simplicity, make an auxiliary dest 
    char* destAux = *dest; 

    // and now the code is the same 
    for(; (*destAux = *src) != '\0'; ++src, ++destAux); 
} 

Une autre méthode consiste à renvoyer le pointeur dest:

char *src, *dest; 
src = (char *)malloc(BUFFSIZE); 

//Do something to fill the src 
dest = mystringcpy(src, strlen(src)); // assign dest 

char* mystringcopy(char *src, size_t length) { 
    char* dest = (char *)malloc(length + 1); 

    // for simplicity, make an auxiliary dest 
    char* destAux = dest; 

    for(; (*destAux = *src) != '\0'; ++src, ++destAux); 

    return dest; // give it back 
} 

Gardez à l'esprit si la longueur est plus petite que la longueur réelle du tampon source que vous envahie votre mémoire tampon de destination. Voir les commentaires pour une solution, même si cela vous appartient.

+0

Grande explication .. Merci beaucoup ... Une autre question est que si je ne passe pas la longueur, je suppose que je vais devoir calculer cela à l'intérieur de la fonction appelée. Est-ce correct ou va-t-il encore fonctionner dans la fonction appelée? – Legend

+0

Vous pouvez simplement utiliser 'strlen' dans la fonction. Je laisserais en fait, cependant. Cela vous permet de faire des copies partielles d'une chaîne, par exemple, ou d'extraire des sous-chaînes. – GManNickG

+0

Oh ... compris ... Merci encore ... – Legend

2

Il n'y a pas de problème à allouer à l'intérieur d'une fonction.

Le problème est que dans les arguments de C sont passés par valeur. Ainsi, lorsque vous affectez une valeur à dest, cela ne modifie que le paramètre dest local à la fonction.

Vous avez deux choix. Vous pouvez retourner le pointeur de dest:

char *alloc_and_copy(const char *src, size_t length) 
{ 
    char *dest = malloc(length + 1); 
    ... do your copying 
    return dest; 
} 

ou vous pouvez passer un pointeur sur l'argument et modifier ce qui est pointé:

void alloc_and_copy(const char *src, size_t length, char **dest) 
{ 
    char *local_dest = malloc(length + 1); 
    ... do your copying using local_dest 

    *dest = local_dest; 
} 

La technique d'utiliser une variable locale n'est pas nécessaire, mais je pense que cela rend le code plus lisible.

+0

Affectez * dest avant de modifier local_dest afin de parcourir la chaîne. – jmucchiello

+0

@jmucchiello - l'idée est de tout faire dans la fonction avec local_dest et de ne le copier qu'à la fin (sinon, cela ajoute peu de valeur). J'ai clarifié mon commentaire pour le rendre plus explicite. –

2

Faire la malloc dans la fonction est OK, mais vous n'êtes pas passer le pointeur de retour de la fonction. Soit renvoyer le pointeur:

char * mystringcopy(char *src) 

ou passer un pointeur sur le pointeur:

void mystringcopy(char *src, char **dest) 
1

En général, lors de l'allocation mémoire il y a certaines hypothèses au sujet de ce code est responsable de la libération de la mémoire quand il est fait. Je souscris à la notion qu'une fonction devrait être responsable d'une opération majeure, comme si une boîte noire. Pour les deux raisons, il est préférable d'allouer votre propre mémoire et de remettre le pointeur à la fonction pour remplir son tampon.

Cela mis à part, vous pouvez soit renvoyer le pointeur char * comme une valeur de retour.

Ou, modifiez le paramètre char *dest-char **dest. Ensuite, appelez la fonction comme: mystringcopy(src, strlen(src), *dest). Et dans la fonction, il renvoie le pointeur par: *dest = (char *)malloc(length + 1);. Pas beau.

2

Les paramètres de C sont transmis par valeur, donc votre fonction reçoit une copie du pointeur dest, l'écrase avec malloc puis la supprime. Essayez ceci:

void mystringcopy(char *src, size_t length, char **dest) { 
    *dest = (char *)malloc(length + 1); 
    char *p=*dest; 
    for(; (*p = *src) != '\0'; ++src, ++p); 
} 

Maintenant, vous passez un pointeur vers le pointeur sur votre chaîne, vous pouvez le remplacer dans la procédure principale. Vous souhaitez l'utiliser comme:

char *src, *dest; 
*src = (char *) malloc(BUFFSIZE); 
//Do something to fill the src 
mystringcpy(src, strlen(src), &dest); 
// now in dest you have your copy 
Questions connexes