snprintf по сравнению с strcpy (и т.д.). в C

Для того, чтобы сделать конкатенацию строк, я делал основной strcpy, strncpy из символа* буферы. Затем я узнал о snprintf и друзья.

Если я придерживаюсь моего strcpy, strcpy + \0 завершение? Или если я просто использую snprintf в будущем?

7
задан Peter Mortensen 11 April 2018 в 10:29
поделиться

5 ответов

В большинстве случаев я сомневаюсь, что разница между использованием strncpy и snprintf измерима.

Если есть какое-то форматирование, я предпочитаю использовать только snprintf , а не смешивать с strncpy .

Я считаю, что это помогает ясности кода и означает, что вы можете использовать следующую идиому, чтобы отслеживать, где вы находитесь в буфере (таким образом, избегая создания алгоритма Shlemiel the Painter ):

char sBuffer[iBufferSize];
char* pCursor = sBuffer;

pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer),  "some stuff\n");

for(int i = 0; i < 10; i++)
{
   pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer),  " iter %d\n", i);
}

pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer),  "into a string\n");
8
ответ дан 6 December 2019 в 07:05
поделиться

sprintf имеет чрезвычайно полезное возвращаемое значение, которое позволяет эффективно добавлять.

Вот идиома:

char buffer[HUGE] = {0}; 
char *end_of_string = &buffer[0];
end_of_string += sprintf( /* whatever */ );
end_of_string += sprintf( /* whatever */ );
end_of_string += sprintf( /* whatever */ );

Вы уловили идею. Это работает, потому что sprintf возвращает количество символов, записанных в буфер, поэтому продвижение вашего буфера на такое количество позиций приведет к тому, что вы укажете на '\ 0' в конце того, что было написано до сих пор. Поэтому, когда вы передаете обновленную позицию следующему sprintf , он может сразу же начать писать новые символы.

Constrast с strcpy , возвращаемое значение которого должно быть бесполезным. Он возвращает вам тот же аргумент, что и вы. Таким образом, добавление с помощью strcpy подразумевает обход всей первой строки в поисках ее конца. А затем повторное добавление с другим вызовом strcpy подразумевает обход всей первой строки, за которой следует вторая строка, которая теперь живет после нее, в поисках '\ 0' . Третий strcpy повторно переместит уже записанные строки. И так далее.

Таким образом, для множества небольших добавлений в очень большой буфер strcpy обращается к (O ^ n), где n - количество добавлений. Что ужасно.

К тому же, как упоминали другие, они делают разные вещи. sprintf можно использовать для форматирования чисел, значений указателей и т. Д. В вашем буфере.

3
ответ дан 6 December 2019 в 07:05
поделиться

snprintf более надежен, если вы хотите отформатировать строку. Если вы хотите только объединить, используйте strncpy (не используйте strcpy), так как это более эффективно.

6
ответ дан 6 December 2019 в 07:05
поделиться

strcpy, strncpy и т.д. только копируют строки из одной области памяти в другую. Но, используя snprint, вы можете делать больше вещей, например, форматировать строку. Копирование целых чисел в буфер и т.д.

Выбор метода зависит только от ваших требований. Если, согласно вашей логике, strcpy и strncpy уже работают, то нет необходимости переходить к snprintf.

Также не забывайте использовать strncpy для большей безопасности, как советуют другие.

1
ответ дан 6 December 2019 в 07:05
поделиться

Все функции *printf проверяют форматирование и расширяют соответствующий аргумент, поэтому они медленнее, чем простые strcpy/strncpy, которые только копируют заданное количество байт из линейной памяти.

Мое эмпирическое правило таково:

  • Используйте snprintf, когда необходимо форматирование.
  • Придерживайтесь strncpy/memcpy, когда нужно скопировать только блок линейной памяти.
  • Вы можете использовать strcpy, когда вы точно знаете размер буферов, которые копируете. Не используйте его, если у вас нет полного контроля над размером буферов.
3
ответ дан 6 December 2019 в 07:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: