Хотя вы можете просто использовать другую функцию strlcpy, как рекомендует другой пост, или использовать snprintf(dest, len, "%s", src)
(который всегда завершает буфер), вот что я заметил, глядя на ваш код:
size_t s_strlcpy(char *dest, const char *src, const size_t len)
{
size_t i = 0;
Нет необходимости делать len
константой здесь, но это может быть полезно, так как он проверяет, чтобы убедиться, что вы не модифицировали его.
/* Always copy 1 less then the destination to make room for the nul */
for(i = 0; i < len - 1; i++)
{
К сожалению. Что если len равно 0? size_t
обычно не подписан, поэтому (size_t) 0 - 1 в конечном итоге станет чем-то вроде 4294967295
, в результате чего ваша программа будет перемещаться по памяти вашей программы и вылетать на неотображенную страницу.
/* only copy up to the first nul is reached */
if(*src != '\0') {
*dest++ = *src++;
}
else {
break;
}
}
/* nul terminate the string */
*dest = '\0';
Код выше выглядит хорошо для меня.
/* Return the number of bytes copied */
return i;
}
Согласно Википедии , strlcpy
возвращает strlen(src)
(фактическую длину строки), а не количество скопированных байтов. Следовательно, вам нужно продолжать считать символы в src
, пока вы не нажмете '\0'
, даже если оно превышает len
.
Кроме того, если ваш цикл for завершается при условии len - 1
, ваша функция вернет len-1
, а не len, как вы ожидаете.
Когда я пишу такие функции, я обычно предпочитаю использовать указатель начала (назовите его S) и указатель конца (назовите его E). S указывает на первый символ, а E указывает на один символ после последнего символа (что делает его так, что E - S - длина строки). Хотя эта техника может показаться уродливой и неясной, я считаю ее довольно надежной.
Вот закомментированная версия того, как я написал бы strlcpy:
size_t s_strlcpy(char *dest, const char *src, size_t len)
{
char *d = dest;
char *e = dest + len; /* end of destination buffer */
const char *s = src;
/* Insert characters into the destination buffer
until we reach the end of the source string
or the end of the destination buffer, whichever
comes first. */
while (*s != '\0' && d < e)
*d++ = *s++;
/* Terminate the destination buffer, being wary of the fact
that len might be zero. */
if (d < e) // If the destination buffer still has room.
*d = 0;
else if (len > 0) // We ran out of room, so zero out the last char
// (if the destination buffer has any items at all).
d[-1] = 0;
/* Advance to the end of the source string. */
while (*s != '\0')
s++;
/* Return the number of characters
between *src and *s,
including *src but not including *s .
This is the length of the source string. */
return s - src;
}