在C中复制字符串

时间:2011-08-10 14:34:56

标签: c string

我正在学习c中的字符串。我使用code :: blocks作为编译器,即使它不仅仅用于c。因此,下面代码的问题是string2的输出是存储的5个字符加上string1的输出。我会告诉你:

#include <stdio.h>
#include <string.h>          /* make strncpy() available */

int main()
{
char string1[]= "To be or not to be?";
char string2[6];

/* copy first 5 characters in string1 to string2 */
strncpy (string2, string1, 5);

printf("1st string: %s\n", string1);
printf("2nd string: %s\n", string2);
return 0;
}

输出是:

1st string contains: To be or not to be? 
2nd string contains: To be To be or not to be?

如果你问我,那就超过了5个字符......

6 个答案:

答案 0 :(得分:10)

来自strncpy手册页:

  

没有空字符隐式附加到目标的末尾,因此如果源中的C字符串的长度小于num,则目标将仅以空值终止。

由于原始字符串的长度大于5,因此不会添加NULL。

正如其他人所指出的那样,为它增加一些安全性:

strncpy (string2, string1, sizeof(string2));
string2[sizeof(string2)-1] = '\0';

请注意,如果string2是通过malloc()

获得的
char * string2 = malloc(123); //sizeof(string2) == sizeof(void *) and not 123

上面的代码会失败。

为了完整起见,这里是代码:http://ideone.com/eP4vd

答案 1 :(得分:3)

您没有使用'\ 0'终止string2,因此printf溢出。尝试做:

memset(string2,0,6);

在使用string2之前。 或者,因为你知道你正在复制5个字符,在strncpy之后:

string2[5] ='\0';

所以你正确地正确终止了字符串。

请注意你应该在你复制的字符数之后加上'\ 0',否则你甚至会在字符串的中间看到垃圾。

答案 2 :(得分:1)

基本上两个字符串都在内存中彼此相邻的堆栈上,并且在string2之后没有空终止符,因此当它打印时,它会从string2 +随机的一个字节值打印“待定”({在点击空字节之前{1}})+ string2[5](“成为或不成为”)。

如果随机的一个字节值为0,它将停止。你会得到你期望的印刷品。

答案 3 :(得分:0)

您的string2不包含\0,因此此字符串不会终止。当你打印它时,它超出了它的界限并打印它在那里找到的任何内容,直到它找到\0

在每个strncpy之后,如果您想要正确终止字符串,则必须手动插入\0

答案 4 :(得分:0)

strncpy有局限性,见上文。 看看像sprintf一样的

sprintf( string2, "%.*s", sizeof(string2)-1, string1 );

答案 5 :(得分:0)

strncpy(),尽管名称不同,但它不仅仅是strcpy()更安全的边界指定版本。这是一个模糊的函数,具有模糊的语义,我认为它不应该被包含在C标准库中。

另一方面,

strncat() 更安全的边界指定版strcat()

这是一个解决方案:

char string1[]= "To be or not to be?";
char string2[6];

string2[0] = '\0';
strncat (string2, string1, 5);