string в C++: строки простыми словами

В стандартной библиотеке C++ std::string является ключевым классом для работы со строками. Этот класс предоставляет разработчикам удобный способ управления и манипуляции строками, заменяя традиционные массивы символов. В этой статье мы рассмотрим основные аспекты std::string и его возможности в C++.

Интересное
Последние новости в мире программирования
Самые свежие новости и полезные материалы в моем telegram канале.
go

Что такое строки (string) в C++

Иллюстрация строк в C++

string - это более удобная альтернатива строками в стиле C, которую можно использовать в C++. Внутреннее устройство string похоже на вектор символов, мы можем изменять строку и ее размер на лету.

Давайте рассмотрим простой пример работы со строками в C++:

#include <iostream>
using namespace std;

int main() {
    string greeting = "Привет"; // инициализация строки
    string world("Мир");        // явный вызов конструктора
    string exclamation{'!'};    // инициализация как массива символов

    cout << greeting << " " << world << exclamation << endl;

    return 0;
}

Вывод данной программы:

Привет Мир!

Теперь давайте разберем, что делает данная программа:

  1. в строке 6 мы присваиваем значение переменной типа string при помощи оператора =. Этот вариант вы будете встречать наиболее часто.
  2. в строке 7 мы явно вызываем конструктор string и передаем туда нужную нам строку.
  3. в строке 8 мы используем тот факт, что строка работает как вектор символов, поэтому мы можем использовать конструкцию вида {<элемент 1>, <элемент 2>, ...}.
  4. в строке 10 мы выводим строки на экран используя стандартный cout.

Теперь давайте рассмотрим операции, которые мы можем производить над строками.

Объединение строк (конкатенация)

Чтобы соединить две строки достаточно воспользоваться оператором +:

string c = "С";
string pp = "++";
string cpp = c + pp;

cout << "cpp = " << cpp << endl;

Вывод программы:

cpp = C++

При этом не обязательно соединять значения из нескольких переменных. Мы можем объединить строку с C строкой "строка в формате C" (массивом символов char[]):

string c = "С";
string cpp = c + "++";

cout << "cpp = " << cpp << endl;

Нельзя соединить два строковых литерала "C" + "++", поскольку оператор + не определен на массивах типа char[]. Для того чтобы сложить две строки при помощи +, обязательно на одной из сторон оператора + должна находиться строка string.

Вывод программы идентичен предыдущему:

cpp = C++

Помимо оператора +, есть метод append, который позволяет добавить одну строку к другой:

string lang = "С";
lang.append("++");

cout << "lang = " << lang << endl;

Вывод программы:

lang = C++

Отличие метода append от + заключается в том, что append меняет существующую строку, в то время как + создает новую.

Поскольку append меняет существующую строку, он работает быстрее чем + особенно при многократных слияниях строк.

Числа и строки

Стоит отметить, что нельзя получить сумму чисел внутри строки при помощи оператора +. Давайте рассмотрим пример:

string a = "12";
string b = "34";

cout << "a + b = " << a + b << endl;

Вывод:

a + b = 1234

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

string a = "12";
cout << a + 34 << endl; // Invalid operands to binary expression ('std::string' and 'int')

Что будет выведено на экран:

string a = "23";
string b = "45";

cout << a + b << endl;
26
68
2345
2345.0
Интересное
Последние новости в мире программирования
Самые свежие новости и полезные материалы в моем telegram канале.
go

Получение длины строки

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

string s = "C++";
cout << "s.length() = " << s.length() << endl;

Вывод:

s.length() = 3

У метода length есть “брат-близнец” - size:

string s = "C++";
cout << "s.size() = " << s.size() << endl;

Вывод:

s.size() = 3

Между ними нет разницы, поэтому вы можете выбрать название метода на свой вкус.

Получение и изменение символа в строке

string позволяет нам получать любой символ по указанному индексу при помощи оператора []. При этом можно также использовать метод at, однако оператор [] является более компактным и встречается чаще в реальных программах:

string s = "ABCDE";
cout << "s[1] = " << s[1] << endl;

Первый символ в строке имеет индекс 0.

Вывод:

s[1] = B

Так же, как и с массивами, мы можем присвоить любой ячейке новое значение:

string s = "ABCDE";
s[1] = 'X';
cout << "s[1] = " << s[1] << endl;

Вывод:

s[1] = X
Изменение символа в строке

Специальные символы

А как же нам объявить строку, которая состоит из двух линий? Для этого достаточно воспользоваться специальным символом \n:

string s = "Первая строка.\nВторая строка";
cout << s << endl;

Вывод:

Первая строка.
Вторая строка

В C++ все специальные символы в строках начинаются с \. Вот примеры часто используемых специальных символов:

  • \n - перенос строки
  • \' - одинарная кавычка
  • \" - двойная кавычка
  • \\ - обратный слеш

Что будет выведено на экран:

cout << "Привет, мир\\nПривет снова!" << endl;
Привет, мир
Привет снова!
Привет, мир Привет снова!
Привет, мир\nПривет снова!
Привет, мир\nПривет\nснова!
Интересное
Последние новости в мире программирования
Самые свежие новости и полезные материалы в моем telegram канале.
go

Ввод строк из консоли используя cin

cin позволяет нам вводить строки напрямую из консоли. Для этого достаточно указать переменную типа string в которую будет записана строка введенная пользователем:

string name;
cout << "Введите ваше имя: ";
cin >> name;
cout << "Ваше имя: " << name << endl;

Пример работы программы:

Введите ваше имя: Дима
Ваше имя: Дима

Однако, если мы попытаемся ввести строку с пробелом, то cin считает строку только до первого пробела. Если мы хотим считать строку полностью, нужно использовать функцию getline:

string name;
cout << "Введите ваше имя: ";
getline(cin, name);
cout << "Ваше имя: " << name << endl;

Пример работы программы:

Введите ваше имя: Вася Пупкин
Ваше имя: Вася Пупкин

Теперь давайте познакомимся подробнее с методами, которые есть у string.

Методы для строк

Мы уже видели несколько методов: length, size и append. Однако у строк есть еще много полезных функций, которые упростят вам жизнь:

  • begin/end - получить итератор для строки
  • empty - проверка на пустоту
  • clear - очистка строки
  • front/back - получить первый/последний символ
  • insert - вставить подстроку
  • erase - удалить подстроку
  • replace - изменить подстроку
  • find - найти подстроку
  • compare - сравнить две строки

begin/end

string — это контейнер в C++. Как и другие контейнеры в C++, он предоставляет возможность обхода своих элементов. Для этого можно использовать итераторы, получаемые с помощью методов begin и end:

string s = "123";
for (auto it = s.begin(); it != s.end(); it++) {
    cout << *it << " ";
}

Вывод данной программы:

1 2 3

Чтобы получить вывод 3 2 1, нужно использовать методы rbegin/rend вместо begin/end.

Интересное
Последние новости в мире программирования
Самые свежие новости и полезные материалы в моем telegram канале.
go

empty

Вместо того, чтобы писать s.length() == 0, мы можем воспользоваться методом empty:

string s = "";
cout << "s = " << (s.empty() ? "<пустая строка>" : s) << endl;

Вывод:

s = <пустая строка>

clear

Метод clear позволяет нам очистить существующую строку:

string s = "Длинная строка";
cout << "s = " << s << endl;
s.clear();
cout << "s = " << (s.empty() ? "<пустая строка>" : s) << endl;

Вывод:

s = Длинная строка
s = <пустая строка>

front/back

Вместо обращения к индексам 0 и s.length() - 1 напрямую, можно воспользоваться методами front и back:

string s = "12345";
cout << "front = " << s.front() << endl;
cout << "back = " << s.back() << endl;

Вывод:

front = 1
back = 5
Интересное
Последние новости в мире программирования
Самые свежие новости и полезные материалы в моем telegram канале.
go

insert

Метод insert позволяет нам добавить символы в любую часть существующей строки:

string s = "125";
s.insert(2, "34");
cout << "s = " << s << endl;

Вывод:

s = 12345

Первый аргумент метода insert указывает, куда вставить. Второй аргумент - это подстрока, которую следует вставить по указанному индексу.

erase

Метод erase удаляет часть строки:

string s = "123__45";
s.erase(3, 2);
cout << "s = " << s << endl;

Вывод:

s = 12345

erase принимает два аргумента:

  1. позиция, с которой начинать удалять
  2. сколько символов нужно удалить

replace

Метод replace является комбинацией методов erase и insert:

string s = "12__5";
s.replace(2, 2, "34");
cout << "s = " << s << endl;

Вывод:

s = 12345

Метод replace принимает:

  1. позиция, с которой начинать замену
  2. количество символов, которые нужно заменить
  3. строка, на которую нужно заменить
Интересное
Последние новости в мире программирования
Самые свежие новости и полезные материалы в моем telegram канале.
go

find

Метод find позволяет нам найти подстроку в другой строке. Данный метод принимает строку, которую нужно найти. В случае если строку удалось найти, мы получим индекс первого вхождения данной подстроки. Если же подстроку найти не удалось, find вернет -1:

string s = "Не имей сто рублей, а имей сто друзей.";
int index = s.find("сто");
cout << "индекс первого вхождения \"сто\" = " << index << endl;

index = s.find("миллион");
cout << "index = " << index << endl;

Вывод данной программы:

индекс первого вхождения "сто" = 14
index = -1

Вас может удивить индекс вхождения подстроки “сто”. Все дело в том, что string хранит набор байт. Русские символы занимают два байта в отличии от пробела или цифр. Получается: “Не” - 4 байта, ” ” - 1 байт, “имей” - 8 байт, ” ” - 1 байт. В сумме - 14 байт. Вы можете подробнее почитать почему разные символы используют разное количество байт в статье про UTF-8.

Что будет выведено на экран:

string s = "Привет, мир!";
int index = s.find("мир");
cout << "index = " << index << endl;
index = 7
index = 8
index = 10
index = 14

compare

Закончим мы на методе compare. Данный метод позволяет нам сравнить две строки и узнать, какая из них лексикографически больше. a.compare(b) вернет:

  • -1 если a < b
  • 0 если a = b
  • 1 если a > b

Вот наглядный пример:

string a = "123";
string b = "43";
string c = "1234";

cout << "123.compare(123 ) = " << a.compare(a) << endl;
cout << "123.compare(43  ) = " << a.compare(b) << endl;
cout << "123.compare(1234) = " << a.compare(c) << endl;
cout << "43 .compare(1234) = " << b.compare(c) << endl;

Вывод:

123.compare(123 ) = 0
123.compare(43  ) = -1
123.compare(1234) = -1
43 .compare(1234) = 1

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

Упражнения

  1. Использование front и back:
    Напишите программу, которая:
    • Запрашивает у пользователя строку.
    • Используя методы front и back, выводит на экран первый и последний символы этой строки.
  2. Редактирование строки:
    Разработайте программу, которая:
    • Запрашивает у пользователя исходную строку.
    • Предоставляет меню с 4 опциями: insert, erase, replace, и find.
    • В зависимости от выбора пользователя, программа предоставляет инструкции для использования соответствующего метода и выводит результат.
  3. Сравнение строк с помощью compare:
    Напишите программу, которая:
    • Запрашивает у пользователя две строки.
    • Использует метод compare для сравнения этих строк.
    • Выводит на экран результат сравнения (какая строка лексикографически больше, или если они равны).

Если хотите всегда быть в курсе последних новостей в мире программирования и IT, подписываетесь на мой Telegram-канал, где я делюсь свежими статьями, новостями и полезными советами. Буду рад видеть вас среди подписчиков!

Обсуждение