Лекции по C/C++: строки класса string
В современном стандарте C++ определен класс с функциями и свойствами (переменными) для организации работы со строками (в классическом языке C строк как таковых нет, есть лишь массивы символов char
):
#include <string>
Не путайте с подключением Си-совместимой библиотеки для работы со строками
char *
:#include <string.h>или
#include <cstring>
Для работы со строками также нужно подключить стандартный namespace
:
using namespace std;
В противном случае придётся везде указывать описатель класса std::string
вместо string
.
Ниже приводится пример программы, работающей со string
(в старых си-совместимых компиляторах не работает!):
#include <iostream> #include <string> #include <malloc.h> using namespace std; int main () { string s = "Test"; s.insert (1,"!"); cout << s.c_str() << endl; string *s2 = new string("Hello"); s2->erase(s2->end()); cout << s2->c_str(); cin.get(); return 0; }
Основные возможности, которыми обладает класс string
:
- инициализация массивом символов (строкой встроенного типа) или другим объектом типа
string
. Встроенный тип не обладает второй возможностью; - копирование одной строки в другую. Для встроенного типа приходится использовать функцию
strcpy()
; - доступ к отдельным символам строки для чтения и записи. Во встроенном массиве для этого применяется операция взятия индекса или косвенная адресация с помощью указателя;
- сравнение двух строк на равенство. Для встроенного типа используются функции семейства
strcmp()
; - конкатенация (сцепление) двух строк, дающая результат либо как третью строку, либо вместо одной из исходных. Для встроенного типа применяется функция
strcat()
, однако чтобы получить результат в новой строке, необходимо последовательно задействовать функцииstrcpy()
иstrcat()
, а также позаботиться о выделении памяти; - встроенные средства определения длины строки (функции-члены класса
size()
и length()
). Узнать длину строки встроенного типа можно только вычислением с помощью функцииstrlen()
; - возможность узнать, пуста ли строка.
Рассмотрим эти базовые возможности более подробно.
Инициализация строк при описании и длина строки (не включая завершающий нуль-терминатор):
string st( "Моя строка\n" ); cout << "Длина " << st << ": " << st.size() << " символов, включая символ новой строки\n";
Строка может быть задана и пустой:
string st2;
Для проверки того, пуста ли строка, можно сравнить ее длину с 0:
if ( ! st.size() ) // пустая
или применить метод empty()
, возвращающий true
для пустой строки и false
для непустой:
if ( st.empty() ) // пустая
Третья форма создания строки инициализирует объект типа string
другим объектом того же типа:
string st3( st );
Строка st3
инициализируется строкой st
. Как мы можем убедиться, что эти строки совпадают? Воспользуемся оператором сравнения (==
):
if ( st == st3 ) // инициализация сработала
Как скопировать одну строку в другую? С помощью обычной операции присваивания:
st2 = st3; // копируем st3 в st2
Для сцепления строк используется операция сложения (+
) или операция сложения с присваиванием (+=
). Пусть даны две строки:
string s1( "hello, " ); string s2( "world\n" );
Мы можем получить третью строку, состоящую из конкатенации первых двух, таким образом:
string s3 = s1 + s2;
Если же мы хотим добавить s2
в конец s1
, мы должны написать:
s1 += s2;
Операция сложения может сцеплять объекты класса string не только между собой, но и со строками встроенного типа. Можно переписать пример, приведенный выше, так, чтобы специальные символы и знаки препинания представлялись встроенным типом char *
, а значимые слова – объектами класса string
:
const char *pc = ", "; string s1( "hello" ); string s2( "world" ); string s3 = s1 + pc + s2 + "\n"; cout << endl << s3;
Подобные выражения работают потому, что компилятор "знает", как автоматически преобразовывать объекты встроенного типа в объекты класса string
. Возможно и простое присваивание встроенной строки объекту string
:
string s1; const char *pc = "a character array"; s1 = pc; // правильно
Обратное преобразование при этом не работает. Попытка выполнить следующую инициализацию строки встроенного типа вызовет ошибку компиляции:
char *str = s1; // ошибка компиляции
Чтобы осуществить такое преобразование, необходимо явно вызвать функцию-член с названием c_str()
("строка Си"):
const char *str = s1.c_str();
Функция c_str()
возвращает указатель на символьный массив, содержащий строку объекта string
в том виде, в каком она находилась бы во встроенном строковом типе.
Ключевое слово const
здесь предотвращает "опасную" в современных визуальных средах возможность непосредственной модификации содержимого объекта через указатель.
К отдельным символам объекта типа string
, как и встроенного типа, можно обращаться с помощью операции взятия индекса. Вот, например, фрагмент кода, заменяющего все точки символами подчеркивания:
string str( "www.disney.com" ); int size = str.size(); for ( int i = 0; i < size; i++ ) if ( str[i] == '.' ) str[ i ] = '_'; cout << str;
Но лучше читать документацию по C++ и пользоваться его возможностями. Например, предыдущее действие мы могли бы выполнить вызовом одной-единственной функции replace()
:
replace( str.begin(), str.end(), '.', '_' );
Правда, здесь использован не метод replace
класса string
, а одноимённый алгоритм:
#include <algorithm>
Поскольку объект string
ведет себя как контейнер, к нему могут применяться и другие алгоритмы. Это позволяет решать задачи, не решаемые напрямую функциями класса string
.
Ниже приводится краткое описание основных операторов и функций класса string
, ссылки в таблице ведут к русскоязычным описаниям в интернете. Более полный список возможностей класса string
можно получить, например, в Википедии или на сайте cplusplus.com.
Задание символов в строке |
|
присваивает значения строке |
|
назначает символы строке |
|
Доступ к отдельным символам |
|
получение указанного символа с проверкой выхода индекса за
границы |
|
получение указанного символа |
|
получение первого символа |
|
получение последнего символа |
|
возвращает указатель на первый символ строки |
|
возвращает немодифицируемый
массив символов С, содержащий символы строки |
|
Проверка на вместимость строки |
|
проверяет, является ли строка пустой |
|
возвращает количество символов в строке |
|
возвращает максимальное количество символов |
|
резервирует место под хранение |
|
Операции над строкой |
|
очищает содержимое строки |
|
вставка символов |
|
удаление символов |
|
добавление символа в конец строки |
|
удаляет последний символ |
|
добавляет символы в конец строки |
|
добавляет символы в конец строки |
|
сравнивает две строки |
|
заменяет каждое вхождение указанного символа |
|
возвращает подстроку |
|
копирует символы |
|
изменяет количество хранимых символов |
|
обменивает содержимое |
|
|
|
Поиск в строке |
|
поиск символов в строке |
|
поиск последнего вхождения подстроки |
|
поиск первого вхождения символов |
|
найти первое вхождение отсутствия символов |
|
найти последнее вхождение символов |
|
найти последнее вхождение отсутствия символов |
Следует обратить внимание, что у любой функции класса string
может быть несколько перегрузок - разновидностей с одинаковыми именами, отличающихся между собой списками и типами аргументов.
В качестве недостатков класса string
можно отметить следующее:
- отсутствие в классе встроенных средств для разбора строк по набору разделителей (аналога функции
strtok
для строкchar *
); - возможное замедление быстродействия по отношению к
char *
при сложной обработке данных.
Ниже приведён код для разбора введённой с клавиатуры строки string
на слова. Можно доработать этот код, исключив знаки препинания, стоящие последними символами строк vecstr[i]
, а также слова, не содержащие ни одного алфавитно-цифрового символа.
#include <iostream> #include <sstream> #include <string> #include <vector> using namespace std; int main() { cout << "Enter the string: "; string str; getline(cin, str); vector <string> vecstr; string word; stringstream s(str); while (s >> word) vecstr.push_back(word); int vsize = vecstr.size(); for (int i = 0; i < vsize; i++) cout << vecstr[i] << endl; cin.get(); return 0; }
При написании программы дополнительно использованы возможности стандартных классов vector и и stringstream. Вот здесь пример показан и в "классическом" стиле разбора.
05.11.2015, 08:33 [88375 просмотров]