有关字符串函数的问题,如strcat(),strncpy(),strncat()?

时间:2014-01-22 17:41:55

标签: c string output strcat strncpy

代码1

int main()
{
    char str[]="abc";
    char str1[]="hello computer";
    strcat(str,str1);
    printf("the concatenated string is : %s\n",str);
    return 0;
}

output- abchello computer

代码2

int main()
{
    char str[100];  //notice the change from code 1
    char str1[]="hello computer";
    strcat(str,str1);
    printf("the concatenated string is : %s\n",str);
    return 0;
}

output- @#^hello computer

代码3

int main()
{
    char str[100];
    char str1[]="hello computer";
    strncpy(str,str1,5);
    str[5]='\0';   //external addition of NULL
    printf("the copied string is : %s\n",str);
    return 0;
}

output- hello

代码4

int main()
{
    char str[100]="abc";
    char str1[]="hello computer";
    strncat(str,str1,5);
    printf("the concatenated string is : %s\n",str);
    return 0;
}

output- abchello

问题

问题1)为什么abchello computercode 1 @#^hello computer中显示code 2?垃圾@#^来自哪里?

问题2)为什么在NULL '\0'中需要strncpy()而在strncat()中不需要外部添加code 3,分别在code 4code 4中显示?

注意 - 如果在char str[100];中我@#^hello,则会显示{{1}},但字符串结束时不添加NULL

4 个答案:

答案 0 :(得分:3)

第一个示例写入超出str的结尾,因此具有未定义的行为。

第二个例子使用strcat,它要求两个以null结尾的字符串作为参数。你的一个论点不符合这个要求,因为你没有初始化它。

第三个示例不复制空终止符,因为这是strncpy的设计方式。从文档中可以看出,如果目标缓冲区小于源字符串,strncpy不会写入空终止符。

至于第四个例子,strncat与strncpy的不同之处在于它总是复制一个空终止符。

我建议您仔细参考这些功能的文档。

答案 1 :(得分:3)

代码1

char str[]="abc";
char str1[]="hello computer";
strcat(str,str1);

这会溢出str。行为是未定义的,可以假设任何输出(实际上,可能str1被自己覆盖,这就是你将abshello computer视为输出的原因。

代码2

char str[100];  //notice the change from code 1
char str1[]="hello computer";
strcat(str,str1);

您在hello computer之前看到垃圾,因为str未初始化。它恰好在你的第一个NUL之前的测试时包含了"@#^"

代码3

char str[100];
char str1[]="hello computer";
strncpy(str,str1,5);
str[5]='\0';   //external addition of NULL

这是对的。 strncpy复制"hello computer"中的前五个字符,但不会终止它。你应该自己做(就像你做的那样)。有关进一步参考,请参阅strcpy的手册页:

  

strcpy()函数将src指向的字符串(包括终止空字节('\ 0'))复制到dest指向的缓冲区。字符串可能不重叠,目标字符串dest必须足够大才能接收副本。小心缓冲区溢出! (见BUGS。)

     

strncpy()函数类似,只是复制了最多n个字节的src。 警告:如果src的前n个字节中没有空字节,则放在dest中的字符串将不会以空值终止。

代码4

char str[100]="abc";
char str1[]="hello computer";
strncat(str,str1,5);

strncpystrncat之间的一个区别是strncat NUL - 终止生成的字符串。来自strncat的手册页:

  

与strcat()一样,dest中的结果字符串始终以null结尾。

答案 2 :(得分:0)

正如大卫所说,对于strcat,它期望以null结尾的字符串,以便可能是垃圾值的原因。

对于你的代码3,字符串最后的'\ 0'字符表示一个char数组作为字符串,out'\ 0'终止它只是一个char数组而不是一个有效的字符串。由于您使用%s进行打印,因此编译器需要将其作为字符串。

答案 3 :(得分:0)

  

Q-1)为什么abchello计算机显示在代码1和@#^ hello中   电脑在代码2?从哪里垃圾@#^来了?

在Code2中:“char str [100]包含未初始化的垃圾字符”。

尝试多次运行Code2程序。您可能会看到每次运行时字符串开头的乱码都会发生变化。 char str[100]在内存中保留一个位置,您可以连续存储100个字符,但不会为您清除它。从以前的程序留在内存中的任何东西通常被称为“垃圾”。该内存几乎肯定包含上次使用内存时的随机数据。有时您甚至可以在未初始化的内存中找到可读字符串。

当你运行strcat时,程序需要找出'str'中字符串结尾的位置。问题是,从来没有一个正确的字符串放入str - 它只是充满了垃圾。程序从char str [100]缓冲区的开头开始,查找表示字符串结尾的'\ 0'字符。它最终会找到一个(随机的'\ 0 \最终会出现在内存中的某个地方)并声明它是第一个字符串的结尾。它现在认为第一个'\ 0'之前的所有内容都是官方字符串的一部分。

试试这个:在strcat: str[0]='\0';之前添加以下行。程序现在应该运行而不显示乱码。