Почему эта реализация 'strncpy' работает?
Я должен переписать для назначения функцию, которая имитирует поведение 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
вместо 'строки, скопированной, не скопированной части', когда они в основном делают то же самое?Почему
\0
кажется, что "игнорируется" при выводе после цикла while, когда это считается полной остановкой, когда я использую 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 ответа
значение i должно быть (n - 1) верно?
Это не обязательно так, так как первый while
цикл выходит, когда он сталкивается с \0
характер (даже если i
меньше чем n-1
).
while
петля используется для обеспечения оставшейся части dest
массив правильно инициализирован в \0
,
"Неправильное" поведение, которое вы видите (строка печатается за концом скопированной строки), связано с тем, что оба цикла завершаются с одинаковым условием: первый цикл завершается, когда i
становится n
и так как второй цикл имеет проверку i<n
не запускается.
Это соответствует поведению, описанному в руководстве:
Функция strncpy() похожа, за исключением того, что самое большее
n
байтыsrc
копируются. Предупреждение: если среди первых нет нулевого байтаn
байтыsrc
строка помещена вdest
не будет иметь нулевое значение
Если вы должны были скопировать строку 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] = '\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;
}
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
Вы должны понимать, что, хотя они выглядят одинаково, массив 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". Вам ясно, что происходит в этом примере?