为什么这种“ strncpy”实现有效?

时间:2019-02-19 16:24:57

标签: c string strcpy strlcpy

在多次尝试和错误,一些外部帮助之后,我必须为赋值重写一个模仿strncpy行为的函数,这是最终代码:

 15 char    *ft_strncpy(char *dest, char *src, unsigned int n)
 16 {
 17     unsigned int i;
 18     unsigned int size;
 19
 20     i = 0;
 21     size = 0;
 22     while (src[i] && i < n)
 23     {
 24         dest[i] = src[i];
 25         i++;
 26     }
 27     while (i < n)
 28     {
 29         dest[i] = '\0';
 30         i++;
 31     }
 32     return (dest);
 33 }

它可以正常工作,但是我没有得到这一部分:

 while (i < n)
 {
     dest[i] = '\0';
     i++;
 }

在这一点上,i的值应该是(n-1)对吗?因此'\0' goes into dest[n-1],循环结束,因为i becomes equal to n,然后函数结束。

我们剩下的字符串看起来像这样:

"string copied\0not copied part"

并像string copiednot copied part一样打印。

我的问题是:

  • 为什么dest[n-1]='\0'dest[n]='\0'而不是while循环,而当他们基本上做同样的事情时,返回string copied而不是'string copyednot copy part'呢?

  • 为什么在{while}循环之后打印出\0时似乎被“忽略”,而当我使用dest [n-1] ='\ 0'来代替它时,为什么它似乎是句号?

这是我用来运行测试并试图了解的主要/替代功能:

int main()
{
     char str[] = "test de chaine";
     char *str2 = "chaine de test";

     ft_strncpy(str, str2, 6);
     printf("%s", str);
     return 0;
}

char    *ft_strncpy(char *dest, char *src, unsigned int n)
 {
     unsigned int i;
     unsigned int size;

     i = 0;
     size = 0;
     while (src[i] && i < n)
     {
         dest[i] = src[i];
         i++;
     }
         dest[n-1] = '\0';
     return (dest);
 }

3 个答案:

答案 0 :(得分:1)

strncpy()被指定为正好写入n个字节,而与源字符串的长度无关。

strncpy(dst, "foo", 5); // writes 'f', 'o', 'o', 0, and 0
strncpy(dst, "foo", 3); // writes 'f', 'o', and 'o': dst is not a string now (*)
strncpy(dst, "foo", 1); // write 'f': dst is not a string now (*)
// (*) unless you make sure there is a '\0' somewhere else in dst

答案 1 :(得分:1)

  

i的值应该是(n-1)对吗?

并不一定要这样,因为第一个while循环在遇到\0字符时会退出(即使i小于n-1)。

while循环用于确保将dest数组的其余部分正确初始化为\0

您看到的“错误”行为(正在打印的字符串超出复制的字符串的末尾)是由于两个循环都以相同的条件退出:第一个循环在i变为{时退出{1}},并且由于第二个循环具有检查n,因此它不会运行。

这与手册中描述的行为相对应:

  

strncpy()函数类似,但最多复制i<n个字节中的n个字节。警告:如果src的前n个字节中没有空字节,则放置在src中的字符串将不会以空值结尾。

如果要复制值为dest的字符串str,它将在以下示例中正确显示它:

abc

答案 2 :(得分:0)

您需要了解,虽然它们看起来很相似,但char数组不是字符串,而字符串是char数组。某些函数(例如string.h的函数)将一个接一个地读取每个字节,并在它们停止时停止遇到'\ 0'。因此,请查看此示例,您将获得不同的视图。

int main()
{
     char str3[] = "This is a test";

     printf("\n %s", str3);
     str3[5] = '\0';
     printf("\n %s \n", str3);
     int i = 0;
     for(i = 0 ; i < strlen(str3) ; i ++)
     {
         printf(" %c -",str3[i] );
     }
     printf("\n");
     for(i = 0 ; i < 12 ; i ++)
     {
         printf(" %c -",str3[i] );
     }
     return 0;
}

我们打印的不是内存中的内容,特别是使用%s将流char数组并在命中'\ 0'时停止。 这个示例中发生的事情对您来说清楚吗?