Основы программирования на С++ для начинающих

Классы string и wstring. Часть 5

Класс string стандартной библиотеки C++ хорошо известен и охотно используем. Но не все и не всегда задумываются над тем, что класс string, при некоторых отличиях в деталях — это и есть контейнер вектор: vector<char> . Правда, он дополнен некоторыми особенностями (но такой код и вы сами могли бы написать):

  • Метод size() задублирован методом length(). Они полностью тождественны, из соображений удобства. Просто для строки естественнее иметь длину, чем размер;

  • Определены перегруженные операции +, += которые возвращают конкатенацию (объединение) строк;

  • Определён конструктор, инициализирующий string при создании начальным значением символьной строки в формате ASCIIZ (char* — указатель на символьный массив в стиле C завершающийся нулём);

  • Определён метод c_str(), который возвращает указатель на внутреннее содержимое строки в формате ASCIIZ. Поскольку это внутреннее значение, его можно использовать, но не стоит пытаться его изменять. Это хорошо не закончится.

Во всём же остальном строки ведут себя точно как вектор, и к ним применимы все операции над векторами. Понимание того, что представляет собой класс string (vector<char>) может позволить создать ряд неожиданных эффектов. Например, поскольку нулевой символ не имеет для vector<char> никакого особого значения (в отличие от строки C), то его тоже вполне можно «заталкивать» в конец string. Тем самым можно поместить в единственную переменную string целый массив C-строк или даже целый текст.

Вот, как подобным образом поместить весь набор переменных окружения (environment) операционной системы в одну переменную string:

Примечание: здесь мы использовали ещё одну из допускаемых форм главной функции программы main() – 3-м параметром которой является массив указателей строк (char*) переменных окружения (environment). Признаком окончания массива строк envp является указатель NULL (тех. документация операционной системы).

Результат:класс string, класс wstrting, контейнеры STL C++ , Standard Template Library, контейнер с++

Что относительно типа wstring? wstring — это эквивалент vector<wchar_t> , вектор «широких», локализованных символов, представляющих интернациональную кодировку символами Unicode. Разбор содержимого (поиск, выделение слов, разбиение на строки и т.д.) русскоязычной или любой другой строки (китайской например) можно делать только в формате wtring (не string).

При этом необходимо предварительно установить правильную локаль для программы (локаль по умолчанию “С” предполагает только ASCII символы в 7-битном представлении). А для ввода-вывода wstring предлагаются потоки, соответственно wcin и wcout, вместо cin и cout, предназначенных для string. Это написано для напоминания.

В порядке иллюстрации рассмотрим анализ локализованной строки wstring на предмет того, является ли она палиндромом.

Пробелы и знаки препинания при сравнениях пропускаются:

Буква L перед символьной константой означает, что записанная дальше строка , записана в широких символах wchar_t

Результат:класс string, класс wstrting, контейнеры STL C++ , Standard Template Library, контейнер с++

Локализации — это уже совершенно другая тема, которая далеко уведёт нас от нашей основной темы. Обсуждение вопросов локализации и широких символов в C/C++ можно почитать здесь.

Наверное, в этой части уместно отметить следующие обстоятельства, относящиеся ко всем типам контейнеров STL. При создании контейнера конструктором без параметров, создаётся пустой контейнер, не содержащий ещё ни одного элемента (заготовка для будущего заполнения контейнера).

Размер такого контейнера (метод size(), или length() для строк) равен нулю. Но эффективнее, с точки зрения производительности, проверять контейнеры на пустоту методом empty(), который присутствует во всех типах контейнеров.

5 thoughts on “Классы string и wstring. Часть 5

  1. Спасибо автору за статьи.
    Но у меня вопрос – почему вы не заключаете оператор условия в фигурные скобки? Это ведь не очень читабельно. Например:
    while (*p != 0) {
    if (0 == strncmp(p, find, strlen(find)))
    break;
    p += strlen(p) + 1;
    }

    или так:
    while (*p != 0) {
    if (0 == strncmp(p, find, strlen(find))) {
    break;
    }
    p += strlen(p) + 1;
    }

    Второй вариант однозначно нагляднее…

    1. Потому, что вопрос форматирования кода – дело вкуса, предпочтений, и на этот счёт есть достаточно много разных мнений.

      P.S. Юное дурачьё (например на Хабрахабр) гордо называет это кодестайл и делают из этого фетиш, самоцель. Но программный код пишется не для эстетического удовольствия (как красивше скобочки расставить), а для того, чтобы он безукоризненно работал. Но об этом, том что это инженерная специальность, а не эстетическая забава, в последние лет 10 как-то стали забывать.

      1. Любой дурак может написать код, понятный компьютеру. Хороший программист пишет код, понятный человеку.
        – Мартин Фаулер

        Видите ли… если Вы пишете код для компьютера, для достижения собственных целей и для собственного удовлетворения – то пожалуйста, никто не запрещает и не сказал бы Вам ничего против, но почему-то этот мне и людям приходится видеть этот код, читать его…
        В последнее время чтение кода людьми и понимание написанного играет ключевую роль в написании программных систем, люди меняются, а разрабатывать продукт нужно продолжать, хотя конечно, как я и сказал ранее, это не относится если Вы пишете код только в своём проекте над которым не работают другие люди.

        p/s:
        в данной ситуации, действительно лишь дело вкуса ставить скобочки или нет, я пишу лишь по поводу Вашего ответа.

      2. Дмитрий, ещё раз повторю … для лучшей усвояемости: существуют несколько разных стилей форматирования кода C/C++. И ни один из них не лучше и не хуже остальных.
        Мне довелось работать в нескольких разработческих софтверных компаниях, у которых были совершенно разные корпоративные требования (кодестайл). Так что стиль нужно выбирать тот, который используется в текущем проекте.

Добавить комментарий для Olej Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *