【问题标题】:questions regarding string functions like strcat(), strncpy(),strncat()?关于 strcat()、strncpy()、strncat() 等字符串函数的问题?
【发布时间】:2014-01-22 17:41:55
【问题描述】:

代码 1

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

输出-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;
}

输出-@#^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;
}

输出-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;
}

输出-abchello

问题

Q-1) 为什么abchello computer 显示在code 1@#^hello computercode 2 中?垃圾@#^从哪里来?

Q-2) 为什么strncpy() 需要外部添加NULL '\0'strncat() 不需要,如code 3code 4 所示?

注意 - 如果在 code 4 我做 char str[100]; 然后 @#^hello 显示,但字符串仍然结束而不添加 NULL

【问题讨论】:

  • '\0'NUL 并且不同于 NULL
  • C 标准也要求编译器生成初始化 auto 变量的代码,而不是 0 或其他任何东西。

标签: c string output strcat strncpy


【解决方案1】:

代码 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" 的前五个字符,并且不会以 NUL 终止它。你应该自己做(就像你做的那样)。如需进一步参考,请参阅strcpy 的手册页:

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

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 结尾。

【讨论】:

  • @DavidHeffernan,确实如此。 strncpy"hello computer" 复制 5 个字符 (hello),由于尚未满足 NUL,它放弃并退出。结果字符串不是以 NUL 结尾的。
  • 但我在外面做
  • @Shahbaz 我指的是目标字符串。您评论说它没有初始化。但这对 strncpy 来说很好。
  • 对不起大家,我匆忙中没有注意到我写错了。
  • @DavidHeffernan,谢谢你告诉我!你看,这就是我不再在 C++ 标签下做任何事情的原因。如果这是在 C++ 标签下,我会得到 5 次反对票和 10 次愤怒的 cmets 骂我愚蠢之类的。
【解决方案2】:

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

第二个示例使用 strcat,它需要两个以空字符结尾的字符串作为参数。您的其中一个参数不符合该要求,因为您未能对其进行初始化。

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

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

我确实建议您仔细参考这些函数的文档。

【讨论】:

  • 你的第一个例子被彻底破坏了。 str 是一个长度为 4 的数组。您超出了缓冲区。
  • 如果strncat不写null终止符那么为什么字符串正确结束
  • 变量未初始化。它可以有任何值,甚至是 null。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    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'; 之前添加以下行 程序现在应该运行而不显示垃圾字符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-03
      • 2019-08-30
      • 1970-01-01
      • 2011-07-05
      相关资源
      最近更新 更多