为什么 'strncpy' 的这个实现有效?

Why does this implementation of 'strncpy' work?

我必须重写一个模仿 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] = '[=11=]';
 30         i++;
 31     }
 32     return (dest);
 33 }

它完美地工作,但我不明白这部分:

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

此时,i的值应该是(n - 1)吧?所以 '[=15=]' goes into dest[n-1] 循环结束,因为 i becomes equal to n 然后函数结束。

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

"string copied[=13=]not copied part"

并打印成:string copiednot copied part.

我的问题是:

这是我用来 运行 测试并尝试理解的 main/alternative 函数:

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] = '[=14=]';
     return (dest);
 }

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 '[=10=]' somewhere else in dst

the value of i should be (n - 1) right ?

不一定是这样,因为第一个while循环在遇到[=12=]字符时退出(即使i小于n-1)。

while 循环用于确保 dest 数组的其余部分正确初始化为 [=12=].

您看到的 "wrong" 行为(打印的字符串超出复制字符串的末尾)是由于两个循环以相同条件退出:第一个循环在 [=13 时退出=] 变成 n 并且由于第二个循环有检查 i<n,它没有 运行.

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

The strncpy() function is similar, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.

如果您要复制一个字符串 str,其值为 abc,它将在下面的示例中正确显示:

#include <stdio.h>

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++;
    }
    while (i < n)
    {
        dest[i] = '[=10=]';
        i++;
    }
    return (dest);
}

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

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

你需要明白,虽然它们看起来很相似,但一个 char 数组不是一个字符串,而一个字符串是一个 char array.Some 函数(即 string.h 函数)将读取每个字节之后的一个other 遇到 '\0' 就会停止。所以检查这个例子,你会有不同的看法。

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

     printf("\n %s", str3);
     str3[5] = '[=10=]';
     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;
}

我们打印的不是我们在 memory.Especially 中所拥有的,使用 %s 将流式传输 char 数组并在命中 '\0' 时停止。 你清楚这个例子中发生了什么吗?