在C中复制字符串的一部分

时间:2010-06-08 21:48:58

标签: c string

这看起来应该很简单,但出于某种原因,我没有让它发挥作用。我有一个名为seq的字符串,如下所示:

ala
ile
val

我想获取前3个字符并将它们复制到不同的字符串中。我使用命令:

memcpy(fileName, seq, 3 * sizeof(char));

应该{​​{1}},对吧?但出于某种原因,我得到fileName = "ala"。我正在解决它只是说fileName = "ala9",但我想知道为什么我会得到那个。{/ p>

注意: 将seq更改为

fileName[4] = '\0'

并重新运行相同的代码,fileName变为ala ile val ser 。不再是9,但仍然是一个错误的角色。

10 个答案:

答案 0 :(得分:18)

C使用空终止符来表示字符串的结尾。 memcpy不知道你是在复制字符串(它只是复制字节),所以它不会想要放一个字符串。您的解决方法实际上是正确的答案。

编辑:wolfPack88有一个好点。你真的需要改变文件名[3]。此外,下面的评论提出了一些关于strncpy的好点,这也是值得学习的选择。

答案 1 :(得分:11)

sprintf是你的朋友,用于从一个字符串的中间提取字符并将它们放在一个空终止的字符缓冲区中。

sprintf(fileName, "%.3s", seq);

sprintf(fileName, "%.*s", 3, seq);

甚至

snprintf(fileName, sizeof(fileName), "%.*s", len, seq);

会给你你想要的东西。 *版本允许可变长度,snprintf更安全,以避免缓冲区溢出

答案 2 :(得分:5)

您需要设置

fileName[3] = 0;

确保fileName有足够的空间用于字符串NUL字节的结尾。

答案 3 :(得分:5)

您应该使用filename[3]='\0';。至于为什么有必要:因为没有别的东西为字符串设置了NUL终结符,所以你必须这样做。

编辑:当然,对于实际使用,你不要使用像我上面所示的常量。通常你会使用类似的东西:

char *substring(char *out, char const *in, size_t len) { 
    memcpy(out, in, len);
    out[len] = '\0';
    return out;
}

请注意,尽管如此,您确实使用memcpy提出了正确的想法。 strncpy(对于一个明显的例子) not 真的是用于此(或几乎任何其他)目的的正确选择。在要避免的标准库函数列表中,strncpy位于列表的第二位,仅位于gets之后(但公平地说,我必须指出strtok关闭第三)。

另请注意(与大多数标准库函数一样),这不会尝试验证您传递的参数 - 例如,如果您告诉它从一个只有10个字符长的字符串中复制99个字符到一个只有5个字符的缓冲区中字符长,无论如何都会尝试复制99个字符,产生未定义的行为。)

Edit2:另一种选择是use sprintf

答案 4 :(得分:5)

如果要使用memcpy复制字符串,则必须在字符串的最后一个字符后手动设置字符“\ 0”。如果您不想手动处理'\ 0',请改用strcpy或strncpy。

答案 5 :(得分:4)

C语言的标准库没有用于复制字符串部分的专用函数。正确的方法是使用memcpy(就像你已经做过的那样)并显式地终止结果。你忘了终止结果,这就是你在复制的字符串部分之后看到奇怪的额外字符的原因。

请注意memcpy仅在您事先知道源字符串的长度时才有效,即您知道字符串的复制部分完全位于源字符串内。如果源的复制部分有可能包含终止空字符(即源字符串在复制部分的中间结束),那么您必须编写自己的函数进行复制或使用非标准但可广泛使用strlcpy

有时,您可能会遇到尝试使用strncpy函数的代码示例。虽然在某些情况下它似乎“有效”,但使用strncpy绝对没有意义,同时考虑到它不打算以这种方式使用。

答案 6 :(得分:3)

C中的字符串是nul终止的,这意味着你需要字符串末尾的nul字符。看起来你很幸运能够在下一个角色中拥有一个空角色,这样你只能得到一个额外的垃圾角色,你也可以获得数以千计的垃圾角色......

答案 7 :(得分:2)

原因是您从seq复制了三个字符的字节,但是没有终止的null-char。因此,您的解决方法不是解决方法,而是正确的解决方案。

C-Strings应该以null结尾。如果它们不是,则字符串的“用户”将读取,直到他无法进一步读取,这将导致未定义的行为。

不过,为什么不使用strncpy?

答案 8 :(得分:2)

意外字符是未正确终止fileName的工件。

在这种情况下,fileName必须是char缓冲区,其长度至少为 4 (三个字符ala为三个,终止空字符为一个)。要设置空字符,可以使用:

fileName[3] = '\0';

memcpy之后。

答案 9 :(得分:2)

除了终止你的字符串外,

fileName[3] = '\0';

您可能还想考虑使用strncpy代替memcpy。此外,sizeof(char)应始终评估为1,因此它是多余的。

祝你好运!