#c #string
#c #строка
Вопрос:
Если бы я использовал strncpy
функцию для строк cat
и dog
. Я не понимаю
, учитывается ли символ или нет, поэтому я хотел бы знать, будет ли конечный результат catdo
? или это будет что-то вроде catdo
strncpy("cat", "dog", 2);
Комментарии:
1. Вы не можете этого сделать.
"cat"
является строковым литералом, а не строкой. Вы не можете присвоить ему новое значение, не больше, чем вы могли бы сделать4 = 5;
2. Предполагая
"cat"
, что на самом деле это указатель на доступный для записи массив символов, а не строковый литерал, это установило бы для первых двух элементов значения'd'
and'o'
и stop . Не используйтеstrncpy()
.3. Зачем вам вообще использовать эту функцию?
Ответ №1:
Вы вообще не должны использовать функции strncpy
and strncat
.
Их имена начинаются с str
, но на самом деле они не работают со строками. В C строка определяется как «последовательность символов, завершающаяся ''
«. Эти функции не гарантируют, что результирующий массив символов всегда заканчивается нулем.
Лучшими альтернативами являются strlcpy
и strlcat
, но они доступны не везде.
Еще лучше была бы отдельная библиотека строк, в которой определение длины строки было бы операцией постоянного времени. Но это отвлекает.
Комментарии:
1.
strncat
гораздо менее проблематично, чемstrncpy
, но я согласен, что ни один из них не должен использоваться.
Ответ №2:
Как упоминал torstenvl, "cat"
и "dog"
являются строковыми литералами, поэтому здесь вы неправильно используете функцию. Первый параметр — это пункт назначения, второй параметр — источник, а третий параметр — количество байтов для копирования.
char *strncpy(char *restrict s1, const char *restrict s2, size_t n)
Чтобы ответить на ваш конкретный вопрос: да; нулевой терминатор копируется в строку назначения. n
записываются байты, и если ваша исходная строка s2
короче n
байтов, NULL
заполняется до n
тех пор, пока не будут записаны байты.
В вашем вопросе похоже, что вы пытаетесь добавить две строки. Чтобы сделать это на C, вам нужно сначала выделить буфер исходной строки, скопировать первую строку, затем скопировать вторую строку, начиная с конца второй строки. В зависимости от того, с чего вы начинаете последний шаг, вы можете получить либо «catdog 0», либо «cat 0dog 0». Это еще один пример типичных ошибок «отключено на единицу».
Для начала вам нужно вычислить длину двух строк, которые вы хотите добавить. Вы можете сделать это с помощью strlen
, из string.h
. strlen
не учитывает нулевой ограничитель как часть длины, поэтому помните, что для получения длины конечной строки вам нужно будет выполнить strlen(s1) strlen(s2) 1
.
Затем вы можете скопировать первую строку, как обычно. Простой способ сделать вторую копию — сделать это:
char* s2start = finalString[strlen(s1) 1];
Затем вы можете сделать strncpy(s2start, s2, [the size of s2])
, и таким образом вы знаете, что начинаете прямо с нулевого терминатора s1, избегая ошибки «cat 0dog».
Надеюсь, это поможет, удачи.
Ответ №3:
Когда вы записываете строку типа "cat"
или "dog"
в c, массивы не могут быть изменены, если вы попытаетесь, это приведет к неопределенному поведению. Вы можете использовать их только в том случае, если функция ожидает const char * input
, const
сообщает вам, что она не может / не будет изменена в функции. При записи "dog"
данных в массив символов будет выглядеть примерно так:
{'d','o','g',''}
Обратите внимание, что он завершается нулевым значением.
Функция, которую вы используете:
char *strncpy(char *dest, const char *src, size_t n)
Копии src
в dst
с максимальной длиной n
, которую вы не можете скопировать в "cat"
, как упоминалось выше, вы можете видеть char *dest
, не является постоянным, но const char * src
является постоянным. Таким образом, источником может быть "cat"
или "dog"
Если вы должны были выделить место для строки, вам разрешено ее изменять:
char cat_str[] = "cat";
теперь массив символов cat_str
инициализирован "cat"
, но мы всегда можем его изменить, обратите внимание, что его длина будет равна 4 (по одной на каждую букву плюс NUL), потому что мы не указали длину. Поэтому убедитесь, что ничего не изменилось после cat_str[3], вы можете проиндексировать его от 0 до 3
Комментарии:
1. Я должен использовать его для колледжа, я также не уверен, что я должен его использовать
2. В этом объяснении отсутствует главное в этой функции: никогда не используйте
strncpy
… даже если вы случайно знаете, что он делает, следующий читатель вашего кода может не знать и будет введен в заблуждение, думая, что он делает что-то полезное.
Ответ №4:
Существует распространенное заблуждение некоторых инструментов статического анализа, которое strncpy
является более безопасной версией strcpy
. Это не так, у него другое назначение. Если мы настаиваем на его использовании для предотвращения переполнения буфера, вы должны осознавать тот факт, что для его подписи
char * strncpy ( char * destination, const char * source, size_t num );
Нулевой символ неявно добавляется в конце destination
, если source
он длиннее, чем num
. Таким образом, в этом случае destination
строка C не должна считаться завершенной нулем (чтение ее как таковой приведет к переполнению).
Итак, если вы знаете, что ваш источник представляет собой строку C с нулевым завершением, вы можете сделать следующее:
#include <stdio.h>
#include <string.h>
int main()
{
const char* source = "dog";
char destination[4] = "cat";
printf("source is %sn", source);
printf("destination is %sn", destination);
/* the strlen 1 accounts for null termination on source */
/* but you need to be sure that source can fit into destination */
/* and still be null terminated - (that's on you the programmer) */
strncpy(destination, source, strlen(source) 1);
printf("source is still %sn", source);
printf("destination is now %sn", destination);
return 0;
}