简体   繁体   English

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

[英]questions regarding string functions like strcat(), strncpy(),strncat()?

code 1 代码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 输出abchello computer

code 2 代码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 输出- @#^hello computer

code 3 代码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 输出- hello

code 4 代码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 输出abchello

QUESTIONS 问题

Q-1) Why abchello computer is displayed in code 1 and @#^hello computer in code 2 ? Q-1)为什么abchello computer显示在code 1@#^hello computercode 2 From where the garbage @#^ is coming? 垃圾@#^从哪里来?

Q-2) Why external addition of NULL '\\0' is required in strncpy() but not in strncat() as shown in code 3 and code 4 respectively? Q-2)为什么在strncpy()需要在外部添加NULL '\\0' ,而在strncat()却不需要,如code 3code 4所示?

NOTE- If in code 4 I do char str[100]; 注-如果在code 4我执行char str[100]; then @#^hello is displayed,but still the string is ended without addition of NULL 然后显示@#^hello ,但仍然在不添加NULL的情况下结束字符串

The first example writes beyond the end of str and so has undefined behaviour. 第一个示例在str的末尾进行写入,因此具有未定义的行为。

The second example uses strcat which demands two null-terminated strings as arguments. 第二个示例使用strcat,它需要两个以null终止的字符串作为参数。 One of your arguments does not meet that requirement because you failed to initialise it. 您的参数之一不满足该要求,因为您未能对其进行初始化。

The third example does not copy a null terminator because that is how strncpy is designed. 第三个示例不复制空终止符,因为这是strncpy的设计方式。 As you can discern from the documentation, strncpy does not write a null terminator if the destination buffer is smaller than the source string. 从文档中可以看出,如果目标缓冲区小于源字符串,strncpy不会写空终止符。

As for the fourth example, strncat differs from strncpy in that it always copies a null-terminator. 对于第四个示例,strncat与strncpy的不同之处在于,它始终复制一个空终止符。

I do recommend that you refer closely to the documentation of these functions. 我确实建议您仔细参考这些功能的文档。

Code 1 代码1

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

This overflows str . 这溢出str The behavior is undefined and any output can be assumed (in reality, probably str1 is being overwritten by itself, that's why you see abshello computer as output). 该行为是未定义的,可以假定任何输出(实际上, str1可能会被其自身覆盖,这就是为什么您将abshello computer视为输出)。

Code 2 代码2

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

You see garbage before hello computer because str is uninitialized. 您会在hello computer之前看到垃圾,因为str未初始化。 It so happens that it had contained "@#^" at the time of your test before its first NUL. 碰巧的是,在测试时,它在第一个NUL之前包含"@#^"

Code 3 代码3

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

This is correct. 这是对的。 strncpy copies the first five characters from "hello computer" and doesn't NUL-terminate it. strncpy复制"hello computer"的前五个字符,并且不对它进行NUL终止。 You should do that yourself (as you have done). 您应该自己做(如您所愿)。 For further reference, from man page of strcpy : 有关更多参考,请参见strcpy手册页:

The strcpy() function copies the string pointed to by src, including the terminating null byte ('\\0'), to the buffer pointed to by dest. strcpy()函数将src指向的字符串(包括终止的空字节(\\ 0) 复制到dest指向的缓冲区。 The strings may not overlap, and the destination string dest must be large enough to receive the copy. 字符串不能重叠,并且目标字符串dest必须足够大才能接收副本。 Beware of buffer overruns! 当心缓冲区溢出! (See BUGS.) (请参阅错误。)

The strncpy() function is similar, except that at most n bytes of src are copied. 除了最多复制n个src字节外, strncpy()函数与之类似。 Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated. 警告:如果src的前n个字节中没有空字节,则放置在dest中的字符串将不会以空值结尾。

Code 4 代码4

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

One difference between strncpy and strncat is that strncat NUL-terminates the resulting string. strncpystrncat之间的区别是strncat NUL终止结果字符串。 From man page of strncat : strncat手册页:

As with strcat(), the resulting string in dest is always null-terminated. 与strcat()一样,dest中的结果字符串始终以空值结尾。

As David said, for strcat it expects null terminated string so thatmay be he possible reason for the garbage value. 正如David所说,对于strcat,它期望以null结尾的字符串,因此这可能是造成垃圾值的原因。

For your code 3, the '\\0' character at the last of the string represents a char array as string, with out '\\0' terminating it is just a char array not a valid string. 对于您的代码3,字符串的最后一个字符'\\ 0'将一个char数组表示为字符串,而没有'\\ 0'终止它只是一个char数组,不是有效的字符串。 Since you are printing by using %s , compiler requires to be it as string. 由于使用%s进行打印,因此编译器要求将其作为字符串。

Q-1) Why abchello computer is displayed in code 1 and @#^hello computer in code 2? Q-1)为什么在代码1中显示abchello计算机,而在代码2中显示@#^ hello计算机? From where the garbage @#^ is coming? 垃圾@#^从哪里来?

In Code2: "char str[100] contains uninitialized garbage characters". 在代码2中:“ char str [100]包含未初始化的垃圾字符”。

Try running the Code2 program multiple times. 尝试多次运行Code2程序。 You may see that the garbage characters at the beginning of the string change every time you run it. 您可能会看到,每次运行字符串时,字符串开头的垃圾字符都会更改。 char str[100] reserves a place in memory where you can store 100 characters in a row, but it does not clean it out for you. char str[100]在内存中保留了一个位置,您可以在其中连续存储100个字符,但不会为您清除它。 Anything left in memory from a previous program is often referred to as 'garbage'. 先前程序在内存中留下的任何内容通常称为“垃圾”。 That memory almost certainly contains random data from the last time the memory was used. 该内存几乎可以肯定包含上次使用该内存以来的随机数据。 Sometimes you can even find readable strings in uninitialized memory like this. 有时,您甚至可以像这样在未初始化的内存中找到可读的字符串。

When you run strcat, the program needs to figure out where the end of the string in 'str' is. 当您运行strcat时,程序需要弄清楚'str'中字符串结尾的位置。 The problem is, there was never a proper string put into str - it is just full of garbage. 问题是,从来没有在str中放入适当的字符串-它只是充满了垃圾。 The program starts at the beginning of the char str[100] buffer and looks for a '\\0' character that indicates the end of the string. 该程序从char str [100]缓冲区的开头开始,并查找指示字符串结尾的'\\ 0'字符。 It will find one eventually (a random '\\0\\ will eventually shown up somewhere in memory) and declare that to the be the end of the first string. 它将最终找到一个(一个随机的'\\ 0 \\最终将出现在内存中的某个地方),并声明为第一个字符串的结尾。 It now considers everything before the first '\\0' to be part of the official string. 现在,它将第一个“ \\ 0”之前的所有内容视为正式字符串的一部分。

Try this: add the following line right before the strcat: str[0]='\\0'; 尝试以下操作:在strcat: str[0]='\\0';之前添加以下行strcat: str[0]='\\0'; The program should now run without showing the garbage characters. 该程序现在应该运行而不显示垃圾字符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM