2017-08-08 125 views
1

我试图实现一个函数,用于从memmove字符串中删除一个子字符串。 打印结果时,看起来好像我没有正确移动子字符串,即使它看起来像我在源字符串中使用了正确的位置。 我的功能是:从一个字符串中删除一个子字符串,使用memmove在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; 
} 

我的输出,例如是: 如果发送字符串 “请删除REM删除rem999”, 我得到回: “请奥雅纳RM ovmove重999”

谢谢!

+1

(无关您的问题,但你通过'substr'到'strlen'之前,应先试'SUBSTR == NULL'否则,你可能最终调用。 'strlen'在空指针上。) –

回答

0

sizeof(temp_p)char *的大小,一般为4

你可能想写strlen(temp_p)

+0

strlen返回没有'\ n'的长度,sizeof包含'\ n'里面。不是吗? – ILG

+0

不,它返回指针的大小:-) –

4

以下:

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

让人很没有意义。

你需要的东西是这样的:

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

注:在我的答案,我只是用strlen()的第一个版本,但批评家指出,这将是因为标准的不妥当的。 (它仍然最有可能的工作,因为我们复制下来,不起来,但最好不要试图违反标准来诱惑你的命运。)所以,这就是为什么我们需要memmove()

请注意,使用更多的代码行,可以对其进行优化,以便您不必在循环的每次迭代中计算length = strlen(temp_p);。这个优化作为练习留给学生。

同时请注意:

  • 您做的更好int subStrSize = strlen(substr);你检查substr == NULL;

  • 有作为styrlen()

  • sizeof(temp_p)没有这样的事情确实的东西从你认为它完全不同。

+0

所以memmove不是一个好主意吗? – ILG

+0

'strcpy(temp_p,temp_p + subStrSize);'是未定义的行为。每** 7.24.2.3 [C标准]的'strcpy'函数**(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf):“如果复制发生在 重叠的对象之间,行为是不确定的。“ –

+0

@AndrewHenle哦,我不知道。我会解决这个问题。谢谢。 –

1

在这个循环中

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

} 

有两个错误。

第一个问题是,在循环的每次迭代之后,指针temp_p应该等于指针scan_p的值,因为字符串的尾部会移动到此位置。

第二个是,这种表达

sizeof(temp_p) 

产生类型char *的对象的大小,而不是提供该字符串的长度由指针temp_p指向。

你的功能也经常调用功能strlen

至于整个函数的设计,那么函数不应该检查其中一个参数是否等于NULL。这是该功能的客户端的任务。标准C字符串函数不做这样的检查。

功能实现可以按照演示程序中显示的以下方式进行查看。

#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; 
} 

程序输出是

12A12B12C12D 
ABCD 
+0

谢谢。我从你的帖子中学到了很多东西 – ILG

+0

@ILG没有。不用谢。:) –

相关问题