Статья Автор: Лебедев Дмитрий

Конспект 11. Строки


C++_Строки. Часть 1

Работа со строками в языке С++ во многом напоминает работу с контейнером vector. Например, создать строку из ста символов b можно таким образом:

string s(100, 'b');

Также мы можем изменить ii-й символ в строке:

s[i] = '1';

Узнать длину строки можно с помощью метода size():

s.size()

Добавим символ a в конец строки:

s.push_back('a');

Удалим последний символ из строки:

s.pop_back();

В отличие от векторов над строками есть ещё и другие операции. Например, сложение двух строк:

s = s1 + s2;

И добавление к строке символа:

s = s + '!';

Обратите внимание, что две последние операции работают долго, так как при каждой из них происходит копирование строки. Поэтому для прибавления символа к строке лучше использовать инструкцию push_back.


C++_Строки. Часть 2

В C++ есть много разных методов для работы со строками. Рассмотрим некоторые из них.

Метод substr

Метод substr извлекает из строки подстроку заданной длины с заданным индексом начала. Рассмотрим на примере:

#include <iostream>
#include <string>
 
using namespace std;
 
int main()
{
   string s;
   cin >> s;
   cout << s.substr(3, 2) << endl;
   return 0;
}
 

При входной строке abcdefg результатом будет подстрока de (начинается с индекса 3 длины 2).

Если второй параметр функции substr не задан, то вернётся подстрока, начинающаяся с заданного индекса и идущая до конца строки (суффикс строки). Например:

   string s;
   cin >> s;
   cout << s.substr(3) << endl;

При входной строке abcdefg результатом будет подстрока defg.

Методы find и rfind

Метод find возвращает индекс, начиная с которого впервые встречается данная подстрока. Рассмотрим на примере:

   string s;
   cin >> s;
   cout << s.find("bcd") << endl;
 	 

При входной строке abcdqwerbcd результатом будет 1.

Заметим, что если такой подстроки в строке не было (например, если мы ввели строку aaaaaaa), то вернётся некоторое очень большое число. Это связано с тем, что метод find возвращает число типа unsigned int. Приведём данное число к типу int и получим −1:

   string s;
   cin >> s;
   cout << (int)s.find("bcd") << endl;

Теперь при входной строке aaaaaaa результатом будет число −1.

Аналогично работает функция rfind, определяющая индекс последнего (правого) вхождения строки. Например:

   string s;
   cin >> s;
   cout << (int)s.rfind("bcd") << endl;

При входной строке abcdqwerbcd результатом будет 8.


C++_Строки Часть 3

Задача о количестве вхождений подстроки в строку

Необходимо найти, сколько раз строка ss встречается в качестве подстроки в строке s.

Решение

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

#include <iostream>
#include <string>
 
using namespace std;
 
int main()
{
   string s, ss;
   getline(cin, s);
   getline(cin, ss);
   int cnt = 0;
   int pos = s.find(ss);
   while (pos != -1){
       ++cnt;
       pos = s.find(ss, pos + 1);
   }
   cout << cnt << endl;
   return 0;
}
 

Заметим, что для строк s=aaaaa и ss=aa ответом будет 4, то есть учитываются пересекающиеся вхождения строки. Иногда бывает, что надо учитывать только непересекающиеся. Модифицируем наше решение, чтобы находить количество непересекающихся вхождений подстроки:

#include <iostream>
#include <string>
 
using namespace std;
 
int main()
{
   string s, ss;
   getline(cin, s);
   getline(cin, ss);
   int cnt = 0;
   int pos = s.find(ss);
   while (pos != -1){
       ++cnt;
       pos = s.find(ss, pos + ss.length());
   }
   cout << cnt << endl;
   return 0;
}

C++_Строки Часть 4

Задача о разделении строки на слова

Дана строка, необходимо разделить её на слова.

Решение

#include <iostream>
#include <string>
#include <vector>
 
using namespace std;
 
int main()
{
   string s;
   getline(cin, s);
   vector<string> words(1, "");
   for (auto c: s)
   {
       if (c == ' '){
           words.push_back("");
       } else{
           words.back().push_back(c);
       }
   }
   for (auto word: words){
       cout << word << endl;
   }
   return 0;
}
 

Иногда разделителем слов бывает не пробел, а какой-то другой символ. Например, в формате csv разделителем служит запятая. В этом случае просто меняем условие внутри цикла:

if (c == ',')

Возможны и более сложные варианты разделителя. Например, если разделителем является пробел или запятая:

if (c == ' ' || c == ',')

Если разделители заданы большим количеством вариантов, то хорошим решением бывает сначала заменить все разделители в строке на пробелы, а затем уже разбить строку на слова.


Задачи для тренировки

1) Сначала чётные позиции, потом нечётные

 
2) Подстрока в строке  
3) Замена подстроки  
4) Количество слов  
5) Пробелы по правилам  
6) Слова с прописной буквы  
7) Самая частая буква  


Печать