【问题标题】:strcpy() of a small string into a bigger string leaves the rest of the bigger string unchanged.How to deal with it?一个小字符串的strcpy()变成一个大字符串,大字符串的其余部分保持不变。如何处理?
【发布时间】:2013-05-05 19:09:37
【问题描述】:

在这个示例程序中,为了说明strcpy() 的这种行为,我将一个字符串"S" 写入了一个更大的字符串previous,而原来的字符串"Delaware"。但是这种覆盖只影响了原来的前两个字符字符串。原始字符串的其余部分继续具有相同的值。如何处理? (即使memcpy() 似乎也可能具有相同的行为)。我的意思是,如何将剩余的字符转换为0?或者字符串中保留其原始值的其余字符没有副作用?

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

int main()
{
    char previous[10]="Delaware";
    printf("The character at position 4 is %c\n",previous[4]);
    strcpy(previous,"S");
    printf("The character at position 4 later is %c",previous[4]);
}

【问题讨论】:

  • 为什么要将字符串的其余部分改为0?
  • 为什么默认会这样做?它是一个字符串函数,字符串不关心空终止符之后的内容,所以大多数时候它只是浪费循环。
  • strcpy 也会复制空终止符,因此如果您执行printf( "%s\n", previous) ;,它只会打印S,这假设目标足够大,也可以容纳空终止符。
  • 字符串函数保证如果您的源是有效字符串,则结果是有效字符串。然而,memcpy 不是字符串函数,没有这样的保证

标签: c string memcpy strcpy null-character


【解决方案1】:

strcpy 函数这样做:

previous                 "S"
     |                    |
     v                    v
 -- -- -- -- -- -- -- -- -- --   -- -
| D| e| l| a| w| a| r| e|\0| |  | S|\0|
 -- -- -- -- -- -- -- -- -- --   -- --
  ^  ^                            |  |
  |  |                            |  |
  |   - - - - - - - - - - - - - - - -
  |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|

让你的记忆看起来像这样:

 -- -- -- -- -- -- -- -- -- --   -- -
| S|\0| l| a| w| a| r| e|\0| |  | S|\0|
 -- -- -- -- -- -- -- -- -- --   -- --

当在 printf 中引用前面的时,0 之后的额外字符将无关紧要。就像特拉华州 0 之后的额外内存位置不会影响您在引用它时使用上一个。

【讨论】:

  • @HAIR @HAIR strcpy() 在将|S|\0| 复制到De 的一部分Delaware 之后,是否不能骑在右边?像strcpy() 这样受人尊敬的库函数不应该在使用结束后清空|S|0| 的内存吗?
  • 不,它没有。它对那个记忆没有任何作用。它是 strcpy,而不是 strcpyandfree 或 strcpyandclear(据我所知,这些都不存在)
【解决方案2】:

strcpy 也会复制空终止符,所以如果你这样做:

printf( "%s\n", previous) ;

在您的情况下,您只会看到S,这在大多数情况下就足够了。如果您真的想在执行strcpy 之前将内存清零,您可以随时在复制之前使用memset

memset(previous, 0, sizeof(previous)) ;

【讨论】:

    【解决方案3】:

    1) 这是 strcpy() 的正确行为。如果您使用 str* 值来访问字符串,您将永远不会看到任何未更改的字节,因为字符串终止符 ('\0') 被放置在第二个位置(索引 0)并且 str* 函数不会通过字符串的结尾。

    2) 这不是 memcpy() 的行为。如果您memcpy(str2, str1, 10),将复制 10 个字符。 memcpy(previous, "S", 10) 不是一个好主意,但是 ;-)

    3) 如果您想在 strcpy() 之前将 previous[] 归零,请尝试 memset(previous, '\0', sizeof(previous))

    【讨论】:

    • memset,而不是 bzero。后者在 C 标准化之前很久就已经过时了。
    【解决方案4】:

    您是否正在实现自己的strcpy() 函数?如果是这样,不要忘记将空终止符从源字符串复制到目标。空终止符告诉 C 字符串在哪里结束。字符串库中的默认实现会执行此操作,当您使用printf() 将其打印出来时,它将显示您期望的内容。

    如果内存分配是一个问题,那么你可以free()previous 字符串占用的空间,然后malloc() 足够你复制的字符串,但在大多数情况下这是多余的,除非你真的担心内存限制,在这种情况下你可能不会使用字符串库。

    【讨论】:

      【解决方案5】:

      字符串中的其余字符实际上应该没有影响,因为 previous 字符串将 S 作为第一个字符(即previous[0])和一个 NULL 值作为第二个。除非您的代码检查字符串中的特定字符,否则这无关紧要。但是,如果您真的希望字符串具有您复制的值,然后是所有 NULL,您可以在执行 strcpy 之前清除字符串。

      memset(previous, 0, sizeof(previous));
      strcpy(previous, "S");
      

      【讨论】:

        猜你喜欢
        • 2020-12-10
        • 1970-01-01
        • 2021-01-01
        • 2017-01-04
        • 2021-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-18
        相关资源
        最近更新 更多