Search code examples
cstringstrcpystrlcpy

Why does this implementation of 'strncpy' work?


I have to rewrite for an assignment a function that mimics the behavior of the strncpy, after many trials and error, some external help, here's the final code :

 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 }

It works flawlessly, but I don't get this part :

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

At this point, the value of i should be (n - 1) right ? So '\0' goes into dest[n-1] and the loop ends because i becomes equal to n and then the function ends.

We're left with a string that would look something like this :

"string copied\0not copied part"

And be printed like : string copiednot copied part.

My question is :

  • Why does dest[n-1]='\0' or dest[n]='\0' instead of that while loop, return string copied instead of 'string copiednot copied part' when they basically do the same thing ?

  • Why does the \0 seem to be 'ignored' when printed out after the while loop, when it's considered a full stop when I use dest[n-1] = '\0' instead ?

Here's the main/alternative function I used to run test and try to understand :

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);
 }

Solution

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

    This is not necessarily the case, since the first while loop exits when it encounters a \0 character (even if i is less than n-1).

    The while-loop is used to ensure the remainder of the dest array is properly initialized to \0.

    The "wrong" behavior you are seeing (the string being printed beyond the end of the copied string) is due to the fact that both loops exit with the same condition: the first loop exits when i becomes n and since the second loop has the check i<n, it does not run.

    This corresponds to the behavior described in the manual:

    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.

    If you were to copy a string str with the value abc, it would properly display it in the example below:

    #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] = '\0';
            i++;
        }
        return (dest);
    }
    
    int main()
    {
         char str[] = "test de chaine";
         char *str2 = "abc";
    
         ft_strncpy(str, str2, 6);
         printf("%s\n", str);
         return 0;
    }