22.1 – std::string и std::wstring

Добавлено 1 октября 2021 в 14:21

Стандартная библиотека C++ содержит множество полезных классов, но, пожалуй, наиболее полезным является std::string. std::stringstd::wstring) – это строковый класс, который предоставляет множество операций для присваивания, сравнения и изменения строк. В данной главе мы подробно рассмотрим эти строковые классы.

Примечание: строки в стиле C мы будем называть «строками в стиле C», тогда как std::stringstd::wstring) будем называть просто «строками».

Необходимость в строковом классе

В предыдущем уроке мы рассмотрели строки в стиле C, в которых для хранения строки символов используются массивы char. Если вы попытаетесь сделать что-нибудь со строками в стиле C, вы очень быстро придете к выводу, что с ними сложно работать, легко испортить и сложно отладить.

Строки в стиле C имеют много недостатков, в первую очередь связанных с тем фактом, что вам придется самостоятельно управлять памятью. Например, если вы захотите присвоить строку "hello!" буферу, вы должны будете сначала динамически выделить память правильной длины для этого буфера:

char *strHello = new char[7];

Не забудьте учесть дополнительный символ для завершающего нуля!

Затем вам нужно будет скопировать в него значение:

strcpy(strHello, "hello!");

Надеюсь, вы сделали буфер достаточно большим, чтобы не было его переполнения!

И, конечно же, поскольку строка размещается динамически, вы должны не забыть правильно удалить ее, когда закончите работу с ней:

delete[] strHello;

Не забывайте использовать удаление для массива вместо обычного удаления!

Более того, многие интуитивно понятные операторы, которые предоставляет C для работы с числами, такие как присваивание и сравнение, просто не работают со строками в стиле C. Иногда может показаться, что они работают, но на самом деле дают неверные результаты – например, сравнение двух строк в стиле C с использованием == на самом деле будет сравнивать указатели, а не строки. Присваивание одной строки в стиле C другой с помощью оператора = поначалу будет казаться, что работает, но на самом деле в этом случае выполняется копирование указателя (поверхностное копирование), что обычно не то, что вам нужно. Подобные вещи могут привести к сбоям программы, которые очень трудно найти и отладить!

Суть в том, что работа со строками в стиле C требует запоминания множества особенностей о том, что безопасно/небезопасно, запоминания набора функций с забавными названиями, такими как strcat() и strcmp(), вместо использования интуитивно понятных операторов, и требует много ручного управления памятью.

К счастью, C++ и стандартная библиотека предоставляют гораздо лучший способ работы со строками: классы std::string и std::wstring. Используя концепции C++, такие как конструкторы, деструкторы и перегрузка операторов, std::string позволяет создавать строки и управлять ими интуитивно и безопасно! Больше никакого управления памятью, никаких странных имен функций и гораздо меньшая вероятность сбоя.

Обзор классов строк

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

#include <string>

На самом деле в заголовке string есть 3 разных класса строк. Первый – это шаблонный базовый класс с именем basic_string:

namespace std
{
    template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
        class basic_string;
}

Вы не будете работать с этим классом напрямую, поэтому пока не беспокойтесь о том, что это за traits и Allocator. Значений по умолчанию будет достаточно почти во всех мыслимых случаях.

Стандартная библиотека предоставляет две разновидности basic_string:

namespace std
{
    typedef basic_string<char> string;
    typedef basic_string<wchar_t> wstring;
}

Это два класса, которые вы непосредственно будете использовать. std::string используется для стандартных строк ASCII и UTF-8. std::wstring используется для строк с расширенными символами / Unicode (UTF-16). Для строк UTF-32 нет встроенного класса (хотя вы можете расширить из basic_string свой собственный класс, если он вам нужен).

Хотя вы будете напрямую использовать std::string и std::wstring, весь строковый функционал реализован в классе basic_string. string и wstring могут получить доступ к этому функционалу напрямую благодаря шаблону. Следовательно, все представленные функции будут работать как для string, так и для wstring. Однако, поскольку basic_string является шаблонным классом, это также означает, что, если вы сделаете что-то синтаксически неверное со string или wstring, компилятор выдаст ужасно выглядящие ошибки шаблона. Не пугайтесь этих ошибок; они выглядят намного хуже, чем они есть на самом деле!

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

ФункцияДействие
Создание и уничтожение
конструкторСоздает или копирует строку
деструкторУничтожает строку
Размер и вместимость
capacity()Возвращает количество символов, которые могут храниться без перераспределения памяти
empty()Возвращает логическое значение, указывающее, пуста ли строка
length(), size()Возвращает количество символов в строке
max_size()Возвращает максимальный размер строки, которая может быть размещена
reserve()Увеличить или уменьшить вместимость строки
Доступ к элементам
[], at()Доступ к символу по определенному индексу
Модификация
=, assign()Присваивает новое значение строке
+=, append(), push_back()Добавляет символы в конец строки
insert()Вставляет символы в строку по произвольному индексу
clear()Удаляет все символы в строке
erase()Стирает символы по произвольному индексу в строке
replace()Заменяет символы с произвольным индексом на другие символы
resize()Расширение или сжатие строки (обрезает или добавляет символы в конце строки)
swap()Меняет местами значения двух строк
Ввод и вывод
>>, getline()Считывает значения из входного потока в строку
<<Записывает значение строки в выходной поток
c_str()Возвращает содержимое строки как строку в стиле C с завершающим нулем
copy()Копирует содержимое (не оканчивающееся нулем) в массив символов
data()То же, что c_str(). Неконстантная перегрузка позволяет выполнять запись в возвращаемую строку
Сравнение строк
==, !=Сравнивает, равны или неравны две строки (возвращает bool)
<, <=, >, >=Сравнивает, являются ли две строки меньше/больше друг друга (возвращает bool)
compare()Сравнивает, равны или неравны две строки (возвращает -1, 0 или 1)
Подстроки и конкатенация
+Объединяет две строки
substr()Возвращает подстроку
Поиск
find()Найти индекс первого символа/подстроки
find_first_of()Найти индекс первого символа из набора символов
find_first_not_of()Найти индекс первого символа, не входящего в набор символов
find_last_of()Найти индекс последнего символа из набора символов
find_last_not_of()Найти индекс последнего символа, не входящего в набор символов
rfind()Найти индекс последнего символа/подстроки
Поддержка итераторов и распределителей памяти (аллокаторов)
begin(), end()Поддержка итератора прямого направления для начала/конца строки
get_allocator()Возвращает распределитель
rbegin(), rend()Поддержка итератора обратного направления для начала/конца строки

Хотя строковые классы библиотеки STL предоставляют множество функций, есть несколько заметных упущений:

  • поддержка регулярных выражений;
  • конструкторы для создания строк из чисел;
  • функции изменения регистра на верхний/нижний;
  • сравнение без учета регистра;
  • разбиение строки на массив;
  • простые функции для получения левой или правой части строки;
  • обрезка пробелов в начале и конце строки;
  • форматирование строки в стиле sprintf;
  • преобразование из UTF-8 в UTF-16 или наоборот.

Для большинства из них вам придется либо написать свои собственные функции, либо преобразовать вашу строку в строку в стиле C (используя c_str()) и использовать функции C, которые предлагают эту функциональность.

В следующих уроках мы более подробно рассмотрим различные функции класса string. Хотя в наших примерах мы будем использовать string, всё в равной степени применимо и к wstring.

Теги

C++ / CppLearnCppstd::stringstd::wstringДля начинающихОбучениеПрограммированиеСтрокаСтрока в стиле C

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.