0
votes

Comment copier une chaîne qui a été allouée de manière dynamique à une autre chaîne allouée de manière dynamique?

J'ai du mal à essayer d'implémenter une fonction Strcpy personnalisée qui est censée gérer les cas où la chaîne SRC est supérieure à la chaîne de destination. Ici, j'ai fourni du code afin que vous puissiez voir toute la fonction. Mon problème est que chaque fois que j'y incrément * devt, il va dans une adresse nulle malgré le fait que j'ai également attribué une mémoire pour correspondre à tout SRC. Cela provoque la défaillance de la segmentation dans (double pointeur) DEST = * SRC. Dest est stocké comme un char * ** parce que, en réalité, l'argument qui doit être passé est une autre chaîne qui est éventuellement de taille plus petite que SRC, et je souhaite écraser * Dest aussi en toute sécurité que possible.

int customStrCpy(char** dest, char* src){
    int strlen1 = strlen(*dest), strlen2 = strlen(src);
    if(strlen1 < strlen2){
        //Creates a dynamically allocated array that is big enough to    store the contents of line2.
        *dest = calloc(strlen2, sizeof(char));
        char* backup_str = *dest;

        int copy_arrs;
        for(copy_arrs = 0; copy_arrs < strlen2; copy_arrs++){
            **dest = *src;
            *dest++; src++;
        }
        *dest = backup_str;
    }
    else strcpy(*dest, src);
}


9 commentaires

Strlen renvoie le numéro un de moins que vous ne le souhaitez. Mind the Terminant \ 0 . Aussi - est DEST toujours pointant vers une chaîne valide lorsqu'elle est transmise à cette fonction?


Strlen (* Dest) ne vous indiquera que le nombre actuel de caractères de * Dest. S'il a été alloué avant l'appel de votre méthode, vous n'avez aucun moyen de savoir combien d'espace a été alloué sans passer aussi de cette longueur dans votre méthode.


Vous vous rendez compte que cette fonction, même après votre réparation, est essentiellement une fuite de mémoire?


Si vous remplacez la chaîne de destination avec une chaîne nouvellement allouée, vous devez également libérer l'allocation d'origine.


Pourquoi ne pas utiliser strcpy () après calloc () ? En outre, pourquoi utiliser calloc () au lieu de masloc () , si vous allez le remplacer immédiatement?


Vous venez de réimplémenter La fonction Standard de POSIX STRUP () < / a>.


@Andrewhenle non il n'a pas fait. STRUP () ne réutilisera pas une chaîne existante si elle est assez grande.


@Barmar OK, il a créé un dangereux STRDUP () qui pourrait ou non pas de la mémoire. Comme impliqué précédemment ...


@Andrewhenle vrai. Ma réponse montre comment prévenir la fuite.


3 Réponses :


-1
votes
(*dest)++;

5 commentaires

Si vous incrémentez le pointeur que Dest pointe vers, alors l'appelant n'obtiendra pas un pointeur au début de la chaîne retournée, ils auront un pointeur à la fin de celui-ci.


La bonne solution consiste à utiliser une variable locale pour cela, pas le pointeur de l'appelant. Ou juste appeler strcpy () .


Il semblait vouloir qu'il pointit à la fin de la chaîne; Mais oui dans le commentaire, il dit quelque chose de différent.


En fait, non, vous vous trompez. C'est ce que Backup_str.


Oups, n'a pas remarqué cela. Si vous modifiez votre réponse, je peux désvoyer.



0
votes

Vous devez ajouter 1 à la longueur de la chaîne, pour autoriser le terminateur NULL, et vous devez libérer l'ancien contenu de DEST si vous allociez une nouvelle chaîne. Après cela, vous pouvez faire le même strcpy () comme vous n'avez pas besoin de réaffecter.

Il n'y a pas non plus besoin de la int retour Type (sauf si vous souhaitez ajouter une erreur d'erreur à MALLOC () et renvoyer un résultat d'état). Cette fonction modifie un argument, il devrait être void . xxx


10 commentaires

Maintenant, nous devons juste retourner quelque chose d'utile ... aussi, Strcpy () quand vous savoir la longueur?


Il y a peu de choses gagnées d'utiliser strncpy () , puisque vous savez que cela va correspondre. Pourrait utiliser memcpy () . Je ne vais pas m'inquiéter à ce sujet.


void ou int est illogique. En utilisant SHLEN pour déterminer s'il y a suffisamment d'espace également - la chaîne de destination pourrait être modifiée à plusieurs reprises avant l'appel.


@P__JJ__ Je ne remets pas en question la prémisse de base de la question.


@Barmar J'ai essayé d'utiliser Memcpy, Strcpy, Strncpy, etc. Tous ont tous complètement foutu les cordes lorsque vous essayez de copier des chaînes plus grandes en plus petites, à la fois la destination et les chaînes de source.


@Noobprogrammer bien sûr. Vous devez toujours allouer une nouvelle chaîne d'abord si la destination n'est pas assez grande.


@NOOBPROGREMMER Le problème de base avec votre question est que vous supposez que SHLEN (* Dest) est la quantité de mémoire allouée à la destination. Cela pourrait être plus grand, mais il n'y a aucun moyen de savoir avec SHLEN () , afin que vous puissiez réaffecter quand ce n'est pas vraiment nécessaire. Il serait préférable de transmettre la taille de la mémoire tampon de destination en tant que paramètre séparé.


Il n'y a jamais rien à gagner à partir d'utiliser Strncpy () , sauf si vous ne voulez pas réellement écrire une chaîne.


@DEduplicator Je viens de supposer que c'est ce que vous faisiez allusion à quand vous avez mentionné connaître la longueur.


Je faisais allusion à memcpy () , que vous avez mentionné à la fin de cette note. Je n'ai pas considéré strncpy () comme une alternative viable du tout, car je ne le vois pas comme une fonction de chaîne, bien que strictement parlant, avec une longueur connue, il arrive que l'on puisse bien le mouillir là-bas.



0
votes

Généralement Strcpy code> renvoie Char * code> pour "Direct" Utilisez dans d'autres opérations.

char *mysStrCpy(char **dest, const char *src)
{
    size_t len = strlen(src);
    char *tmpptr;

    *dest = malloc(len + 1);
    // or *dest = realloc(*dest, len + 1);
    if(*dest)
    {
        tmpptr = *dest;
        while(*tmpptr++ = *src++);
    }
    return *dest;
}


0 commentaires