Использование текстовой информации во время работы с базами данных, файлами, для получения и отправления сообщений, является неотъемлемой частью работы каждого программиста.
Строки применяются, как для внутренних целей (отладки и тестирования кода), так и для решения общих задач, передачи данных клиенту, оформления графического интерфейса. Ввиду этого следует уделить особое внимание тому, как устроены строки в языке С++, как работать с их базовыми операции и какие методы обработки объектов типа string быстрее, либо целесообразнее в той или иной ситуации.
Строки в языке C++ могут представлять собой массивы символов char – это встроенный тип, который применялся в С. Либо экземпляры класса string, который включен в стандартную библиотеку С++. Следует заметить, что при создании объекта данного типа мы практически получаем динамически изменяющийся массив, т.е. тот, которому нет необходимости задавать начальные размеры, поскольку они могут меняться в процессе работы с сущностью.
В первом случае строка размещается в памяти, как массив. Через указатель типа char осуществляется доступ к ней. Данный подход чреват ошибками и является довольно сложным, поскольку реализован на низком уровне.
Объекты класса string облегчают работу, через них можно получить доступ к стандартным операциям над строками. Они же входят в пространство имен stl (Standard Template Library). Для дальнейшего использования стандартных библиотек С необходимо подключить заголовочный файл:
1 | #include <cstring> |
Простейшим примером использования переменной строчного типа будет выведение её на экран. Но усложним задачу и попробуем, для начала, считать значение строки, а после её оперировать.
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <iostream> #include <string> using namespace std; int main() { string myString; // создаем переменную, в которую поместим строку cout << "What is your name? "; getline(cin, myString); // считываем введенную строку cout << "Hey, " << myString << "! \n"; // выводим значение переменной на экран } |
Метод getline() позволяет считывать данные из потока cin, а также записывать их в переменную, которая указывается после запятой.
В случае, когда необходимо инициализировать переменную во время ее создания, следует использовать следующий синтаксис:
1 | string oneMoreString = "Here is my new string!"; |
Рассмотрим базовые методы класса string, которые позволяют модифицировать строки и получать информацию о их параметрах.
Для получения длины строки можно применять два метода. Один из них size() другой length(). Оба метода возвращают численное количество символов. Но следует заметить, что нумерация элементов в строковом массиве все равно начинается с 0.
Листинг для проверки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <iostream> #include <string> using namespace std; int main() { string myString; cout << "What is your name? "; getline(cin, myString); cout << "Hey, " << myString << "! \n"; cout << "Size is " << myString.size() << "\n"; cout << "Length is " << myString.length() << "\n"; } |
Далее мы видим, что оба метода возвращают одинаковые значения.
Для проверки строковой переменной на наличие данных в ней используется функция empty(), которая возвращает булевое значение ( 0 если false или 1 если true). Данная операция полезна, когда необходимо себя обезопасить от потери данных.
Чтобы обнулить строчную переменную применяется метод clear(). В результате после его выполнения myString.size() вернет 0, а myString.empty() – значение true, т.е. 1.
Листинг кода для проверки функций:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <iostream> #include <string> using namespace std; int main() { string myString = "Not a bug, but a feature!"; cout << "Is empty? " << myString.empty() << "\n"; cout << "Size is " << myString.size() << "\n"; cout << "Clear it all! \n"; myString.clear(); // удаляем данные cout << "Is empty now? " << myString.empty() << "\n"; cout << "Size is " << myString.size() << "\n"; } |
Теперь рассмотрим менее тривиальные операции, которые позволят сэкономить время и усилия программистов, а также избежать использования массивных циклов для перебора каждого значения строкового массива.
Функция push_back (char) позволяет добавить в конец текущей строки любой символ типа char. При этом, нам нет необходимости пересохранять новое значение строки, старая переменная просто будет модифицированной.
Класс string позволяет манипулировать двумя строками одновременно, записывая значения из одной в другую. Для этого на объекте строки следует вызвать метод insert (int startInResultString, string from, int startInSourceString, int amount). Где startInResultString – стартовая позиция ячейки в строке, в которую производится запись новых данных, т.е. новые значения будут размещаться начиная с этого индекса.
Строчная переменная from – представляет собой строку из которой берутся данные, далее все параметры относятся именно к ней. Начальное значение индекса с которого начнется копирование данных обозначено startInSourceString. Общее количество символов, которые будут скопированы из строки from обозначено amount, отсчет производится начиная со стартового индекса.
Листинг кода позволит лучше разобраться со входными параметрами функции.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <iostream> #include <string> using namespace std; int main() { string myString1 = "Not a bug, But a feature!"; string myString2 = " said a developer."; cout << myString1 << "\n"; cout << myString2 << "\n"; myString1.insert(10, myString2, 0, 20); cout << myString1; } |
Были разобраны не все, но наиболее часто-используемые функции для работы со строковыми объектами. Преимущество класса string состоит в простоте использования и поддержке большого количества методов. Тем не менее, строковые объекты обрабатываются медленно. В некоторых случаях может случиться потеря данных либо разрыв целостности строки, которую потом нельзя будет никак вывести и проверить визуально.
Экспериментируйте – создайте объект класса string и вызывайте его методы по-очереди. Старайтесь сами разобраться, что они делают и как работают. Во многих учебниках предлагается самостоятельно написать свой собственный (конечно же укрощенный) класс для работы со строками. Это совсем несложно и вы отлично разберетесь с тем, как устроен настоящий класс string. Мы подготовим для вас несколько задач, для закрепления этого материала.
Обязательно посмотрите видео по теме класс (автор Денис Марков):
Видео о том как создать свой класс String поможет разобраться, как всё устроено:
Хорошая статья, может лучшая во всём цикле статей – по сбалансированности детальности и простоте изложения.
Только непонятно, почему везде в тексте класс называется String (с большой буквы), если даже в примерах он везде используется как string (с маленькой буквы). Если вы напишете String в коде, то тут же получите грубую синтаксическую ошибку.
Ещё хорошо бы упомянуть, хотя бы вскользь (или отдельной темой в продолжение, “использование string”?):
1. что из string всегда можно “извлечь” более привычное представление char* (в стиле C) методом c_str():
string s = “xxx”;
char *c = s.c_str();
2. о переопределённых операциях += и + для string, как конкатенация строк:
string h = “Hello “, w = “world”;
cout << h + w << endl;
h += w;
cout << h << endl;
3. о целой большой группе методов-представления строк для изображения числовых значений:
string d( "123" ), f( "1.23" );
long i = d.stoul();
float z = d.stof();
И последнее … замечание:
> Оба метода возвращают численное количество символов.
length() и size() возвращают не количество символов, а количество байт в содержимом строки. Для ASCII (английских) символов – это одно и то же. Но для русских (и других языков) – нет, и зависит от используемой кодировки.
string priv( "привет!" );
, в зависимости от того, в каком редакторе и какой кодировке работаете с кодом программы.cout << priv.size( ) << " | " << priv.length( );
Точные значения здесь не важны… Но важно знать, что length() и size() для русских строк не дают предполагаемое число символов, что может порождать трудно находимые ошибки!
Олег, спасибо за дополнения к статье.
… съела, гадость, несколько строк примера!
Но должно быть понятно, что длина “привет!” будет равна 13.
#include
#include
using namespace std;
int main()
{
string myString; // создаем переменную, в которую поместим строку
cout << "What is your name? ";
getline(cin, myString); // считываем введенную строку
cout << "Hey, " << myString << "! \n"; // выводим значение переменной на экран
}
У меня почему-то getline(cin, myString); не робит
Извиняюсь, что не в
hydc8j