Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 [ 7 ] 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

strstream

sprintf

Стандартность?

Да: (С++03], хотя и

объявлен

нежелательным

Да: (С90], [€++03], C99J

Простота использования и ясность?

Эффективность, без излишних распределений памяти?

Безопасность в плане переполнения буфера?

Безопасность типов?

Использование в шаблонах

Несколько смущает тот факт, что настолько хорошая вещь оказалась вдруг нежелательной, но такова жизнь...

Альтернатива №4: boost::lexicaLcast г) boost::1exical cast

Если вы еще незнакомы с Boost [Boost], мой совет - познакомьтесь. Это открытая библиотека для С-ь + , написанная в основном членами комитета по стандартизации С++, которая представляет собой ие только пример хорошего кода, написаииого профессионалами в стиле стандартной библиотеки С+ + . Возможности этой библиотеки, по сути, претендуют на включение в очередной стандарт С+-, так что с ними стоит ознакомиться заранее. Кроме того, вы можете использовать се сейчас и совершенно бесплатно.

Одна нз интересных возможностей, предусмотренных в Boost, ~- boost: :lexical cast, которая представляет собой оболочку вокруг stringstream. Boost включает также более мощные подходы, которые используют внутренние потоки и обеспечивают большое количество опций форматирования, в частности, boost: :format, но поскольку код, написанный Кэвлином Хенни (Kevlin Henncy), предельно краток и очень элегантен, я МОР) полностью представить его здесь (исключив обходные пути .оля старых компиляторов). И я делаю это, несмотря на то, что это - иеста1щарт11ая возможность.

tempiate<typename Target, typename Source> Target 1exical cast( Source arg ) {

std::stri ngstream interpreter;

Target result;

i f(!(i nterpreter « arg) !(i nterpreter » result) j !(i nterpreter >> std::ws).eot())

throw bad lexical cast(); return result;

Заметим, что шаблон 1 exi cal„cast не предназначен для конкуренции с гораздо более мощным средством форматирования строк, таким как spri ntf. 1 exi cal cast предназначен для конвертирования данных из одного типа в другой, так что он может представить конкуренцию скорее для функций С типа atoi () и подобных. OflfraKo данный шаблон настолько близок рассматриваемой теме, что не упомянуть о нем просто невозможно.

Ниже представлен пример 3-1 при использовании 1 exi cal„cast (требование вывода как минимум 4 си.мволов удалено).

Пример 3-4: строковое представление данных в С++ с использованием boost::1exical cast.



void PrettyFormatC int i, string& s ) { предельно просто: s = ]exical..cast<string>C i ) ;

/. Простота использования и ясность. Не стоит и доказывать, что данный код проще и понятнее всех ранее рассмотренных вариантов.

2. Эффективность (возможность непосредственного использования существующих буферов). Поскольку lexical cast использует stringstream, не удивительно, что при работе он требует вьлдсления па.мяти, как минимум, в том же количестве, что и stri ngstream. На одной из опробованных мною платформ в примере 3-4 было выполнено на одно выделение памяти больше, чем требуется при использовании обычного stri ngstream (см. пример 3-2); на другой платформе дополнительного выделения памяти не было.

В остальных аспектах - безопасности и возможности использования в шаблонах 1exical „cast соответствует stringstream.

Результаты сравнения lexical cast и spri ntf представлены в следующей таблице.

!exical cast

sprintf

Оандартность?

Нет (возможный кандидат Да; С90], [С+-ь03], [C99J в стандарт С++0,х)

Простота использования и ясность?

Эффективность, без излишних распределений памяти?

Безопасность в плане переполнения

буфера

Безопасность типов?

Использование в шаблонах?

Резюме

Конечно, ряд вопросов не бьгл рассмотрен нами подробно. Например, все форматирование строк рассматривалось нами только в отношении обычных символов, а во-ггросы использования "широких" символов нами не затрагивались. Кроме того, вопросы эффективности затрагивались нами в плане непосредственного использования существующих буферов, но другая сторона этой эффективности - необходимость угфавления памятью программистом при использовании sprintf, snprintf и strstream, в то время как применение stri ngstream, strstream и 1 exi cal cast позволяет вам избежать этого. (Здесь нет опечатки или противоречия, strstream внесен в оба списка в связи с тем, что его можно использовать и так, и этак,)

Помимо 1 exi calcast, рассмотренного здесь в силу его краткости и элегантности, имеется масса других нестандартных альтернатив функции sprintf, в том числе в самой библиотеке Boost (например, такая замечательная и очень мошная вещь, как boost: : format, позволяющая добавить форматирование в стиле spri ntf к уже рассмотренным stri ngstream и strstream),

Лосле обобщения результатов исследований мы получили сводную табл, 3,1, из которой понятно, что идеального варианта не существует, но, тем не Metiee, можно дать определенные рекомендации, которые сведенЬ1 в табл, 3,2,

» Если необходимо преобразовать значение в строку stri ng (или во что-то иное) - используйте boost: : 1 exical cast.



Для простого форматирования, или при необходимости поддержки широких строк, или для использования в шаблонах выбирайте stringstream или strstream.

Для выполнения более сложного форматирования, если не требуется поддержка широких строк или использование в шаблонах, воспользуйтесь функцией snpri ntf. То, что это функция из С, вовсе не означает, что она не может быть использованной в С++!

Если проведенные измерения показывают, что проблема производительности действительно связана с использованием неэффективного метода форматирования, только в этом случае, только в этих конкретных местах кода имеет смысл воспользоваться одной из более быстрых альтернатив -- strstream или

snprintf.

Никогда не используйте spri ntf.

Таблица 3.1. Сравнение различных методов форматирования строк

sprintf

snprintf

stringstream

strstream

boost::lexicai cast

Стандартность

[С90]

(распространенное расширение)

[C++03J

(распространенное расширение)

Да, но нежелательно

[С99]

С++{к

Вероятно

Вероятно

Возможно

(предположительно)

Простота использования

Простота

использования и

ясность?

Эффективность, без

излишних

распределений

памяти?

Безопасность в плане

переполнения буфера?

Безопасность типов?

Использование в

шаблонах?



0 1 2 3 4 5 6 [ 7 ] 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85