2017-08-08 5 views
1

J'essaie d'implémenter une fonction pour supprimer une sous-chaîne d'une chaîne avec memmove. Lors de l'impression des résultats, il semble que je n'ai pas correctement déplacé les sous-chaînes, même s'il semble que j'ai utilisé la bonne position dans la chaîne source. Ma fonction est:Supprimer une sous-chaîne d'une chaîne avec memmove dans C

char * removeSubStr(char * str, const char * substr){ 
    char *scan_p, *temp_p; 
    int subStrSize = strlen(substr); 
    if (str == NULL){ 
     return 0; 
    } 
    else if (substr == NULL){ 
     return str; 
    } 
    else if (strlen(substr)> strlen(str)){ 
     return str; 
    } 
    temp_p = str; 
    while(scan_p = strstr(temp_p,substr)){ 
     temp_p = scan_p + subStrSize; 
     memmove(scan_p, temp_p, sizeof(temp_p)+1); 

    } 
    return str; 
} 

Ma sortie, par exemple: si l'envoi de la chaîne "s'il vous plaît supprimer rem supprimer rem999", Je reviens: "s'il vous plaît Ove rm ovmove re 999"

Merci!

+1

(Rien à voir avec votre problème, mais vous devez tester '== substr null' avant de passer' 'substr' à strlen' Sinon, vous pourriez finir par appeler. 'strlen' sur un pointeur nul.) –

Répondre

0

sizeof(temp_p) est la taille de la char *, généralement 4

Vous vouliez probablement écrire strlen(temp_p)

+0

strlen renvoie la longueur sans le '\ n', et sizeof inclut le '\ n' à l'intérieur. n'est-ce pas? – ILG

+0

Non, il renvoie la taille du pointeur :-) –

4

qui suit:

while(scan_p = strstr(temp_p,substr)){ 
    temp_p = scan_p + subStrSize; 
    memmove(scan_p, temp_p, sizeof(temp_p)+1); 
} 

fait très peu de sens.

Vous avez besoin quelque chose comme ceci:

while(temp_p = strstr(temp_p, substr)) 
{ 
    length = strlen(temp_p); 
    memmove(temp_p, temp_p + subStrSize, length - subStrSize + 1); 
} 

Note: dans la première version de ma réponse que je juste en utilisant strlen(), mais comme commentateurs ont fait remarquer, ce serait à cause de la déconseiller standard. (Cela fonctionnerait probablement très probablement, puisque nous copions, pas en haut, mais il est préférable de ne pas tenter votre destin en violant la norme.) Donc, c'est pourquoi nous avons besoin de memmove().

Notez qu'avec quelques lignes de code supplémentaires, ceci peut être optimisé pour que vous n'ayez pas à calculer length = strlen(temp_p); dans chaque itération de la boucle. Cette optimisation est laissée comme un exercice à l'étudiant.

s'il vous plaît noter également:

  • Tu ferais mieux de faire int subStrSize = strlen(substr);après vous vérifiez substr == NULL;

  • Il n'y a pas une telle chose comme styrlen()

  • sizeof(temp_p) fait quelque chose de complètement différent de ce que vous pensez.

+0

Donc memmove n'est pas une bonne idée? – ILG

+0

'strcpy (temp_p, temp_p + subStrSize);' est un comportement indéfini. Par ** 7.24.2.3 La fonction 'strcpy' ** de [la norme C] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf):" Si copie a lieu entre les objets que se chevauchent, le comportement est indéfini. " –

+0

@AndrewHenle oh, je ne le savais pas. Je vais réparer ça. Merci. –

1

Dans cette boucle

temp_p = str; 
while(scan_p = strstr(temp_p,substr)){ 
    temp_p = scan_p + subStrSize; 
    memmove(scan_p, temp_p, `sizeof(temp_p)`+1); 

} 

il y a deux bugs.

La première est qu'après chaque itération de la boucle, le pointeur temp_p doit être égal à la valeur du pointeur scan_p car la queue de la chaîne est déplacée dans cette position.

Le second est que cette expression

sizeof(temp_p) 

donne la taille d'un objet du type char * au lieu de fournir la longueur de la chaîne pointée par le pointeur temp_p.

Aussi votre fonction appelle trop souvent la fonction strlen. En ce qui concerne la conception de la fonction dans son ensemble, la fonction ne doit pas vérifier si l'un des paramètres est égal à NULL. C'est la tâche du client de la fonction. Les fonctions de chaîne standard C ne font pas une telle vérification.

La mise en œuvre de la fonction peut ressembler à ceci, comme cela est montré dans le programme démonstratif.

#include <stdio.h> 
#include <string.h> 

char * removeSubStr(char *str, const char *substr) 
{ 
    size_t m1 = strlen(str); 
    size_t m2 = strlen(substr); 

    if (!(m1 < m2)) 
    { 
     for (char *p = str; (p = strstr(p, substr)) != NULL;) 
     { 
      size_t n = m1 - (p + m2 - str); 
      memmove(p, p + m2, n + 1); 
     } 
    } 

    return str; 
} 

int main(void) 
{ 
    char s[] = "12A12B12C12D"; 

    puts(s); 

    puts(removeSubStr(s, "12")); 

    return 0; 
} 

La sortie du programme est

12A12B12C12D 
ABCD 
+0

Merci. J'ai beaucoup appris de votre publication – ILG

+0

@ILG Non du tout. Je vous en prie.:) –