2010-12-06 1 views
1

Ok, strncpy не предназначен для работы с NULL завершаемыми строками - он не предназначен для строк с завершающим NULL (если dest слишком короткий, он не будет прерван NULL и если dest больше, он будет дополнен нулями).Назад к основам - идиоматический способ копирования строки в статический массив

Итак, вот тривиальный код:

const char *src = ....; // NULL terminated string of unknown length 
char dest[30]; 

Как ЦСИ к Dest? strcpy небезопасен, strncpy - плохой выбор тоже. Итак, я оставил с strlen, а затем memcpy? Я полагаю, что решение будет немного отличаться, когда мне будет нужно заботиться dest не будет усечен (dest меньше длины src) или нет.

Некоторые ограничения:

  • код Legacy, так что я не хочу и не могу изменить его StD :: строка
  • У меня нет strlcpy - НКУ не поставляет Это.
  • Код может использоваться в тех частях приложения, где критическая производительность (например, я не хочу откладывать время процессорного времени с нулями dest как strncpy). Тем не менее, я не говорю о преждевременной оптимизации, а скорее о идиотском способе выполнения строкового копирования на C-образном пути.

Редактировать

Oopps, я имел в виду strncpy и не snprintf. Моя ошибка

+1

Положите `dest [29] = 0`, используйте snprintf с n = 29 и не беспокойтесь о заполнении. – sje397 2010-12-06 05:28:44

+1

Почему «snprintf» - плохой выбор? – MAK 2010-12-06 05:29:01

+3

Вы просто ошибаетесь в своих помещениях. `snprintf` ** всегда null завершает ** и ** никогда не прокладывает **. – 2010-12-06 06:01:30

ответ

1

Я просто катить мой собственный:

for (int i = 0; i < (sizeof(dest) - 1) && src[i] != NULL; i++) 
{ 
    dest[i] = src[i]; 
} 
dest[i] = NULL; 

Это гарантирует, что dest заканчивается нулем, но никогда не добавляет больше аннулирует, чем это необходимо. Если вы действительно чувствительны к производительности, вы можете объявить это как макрос или встроенную функцию в общем заголовке.

3

Если вы не заботитесь о усечения, вы можете использовать strncat():

dest[0] = 0; 
strncat(dest, src, sizeof dest - 1); 
4

strncpy С:

strncpy(dest, src, sizeof(dest) - 1); 
dest[sizeof(dest) - 1] = '\0'; 

This подушечки с нулями, но делает гораздо меньше работы, чем форматирование snprintf. Если вы действительно должны иметь компьютер делать как можно меньше, описать его самостоятельно:

char* last = dest + sizeof(dest) - 1; 
char* curr = dest; /* assuming we must not alter 'dest' */ 
while (curr != last && *src) { *curr++ = *src++; } 
*last = '\0'; /* avoids a branch, but always writes. 
If branch prediction is working well and the text normally fits: 
if (curr == last) { *curr = '\0'; } */ 
0

std::copy(src, src+strlen(src)+1, dest)

1

Использование snprintf. Он всегда завершает нуль и не выполняет никакого заполнения. Не знаю, где у вас есть неправильные представления об этом ...

4

Я думаю, вы говорите о strncpy(), что может не привести к завершению строки и заполнить оставшуюся часть буфера нулями.

snprintf() всегда заканчивает строку назначения (при условии, что буфер имеет размер не менее 1) и не заполняет оставшуюся часть буфера нулями.

Таким образом, snprintf()является, что вы хотите, за исключением того, что вы очень обеспокоены производительностью. Поскольку snprintf() нужно интерпретировать строку формата (даже если все, что она делает, это копирование строки), вам может быть лучше с чем-то вроде strlcpy() для операций с ограниченной копией строк.

(и если вы хотите strlcpy(), но не имеют его, вы можете получить довольно простую source here. Для полноты strlcat()is here)

0

Я не уверен, я понимаю ваш вопрос полностью, но если вы» Re обеспокоены нулевым заполнением, это часто можно сделать довольно эффективно, если вы инициализируете свой массив следующим образом.

char dest[30] = { 0 }; 

Если вы инициализировать его, как, что вы не должны заботиться о дополнительной логики, чтобы добавить «\ 0» в конце строки, и это может оказаться даже быстрее.

Но если вы собираетесь оптимизировать, помните, чтобы измерять производительность до и после оптимизации. В противном случае всегда используйте код с удобочитаемостью и поддержкой.

Смежные вопросы