Кстати, когда потребуется узнать, пуста ли строка, не сравнивайте ее размер с нулем, а просто вызовите метод empty. Это метод, который возвращает истину, если длина строки равна нулю.

4.5. Обращение строк

Проблема

Требуется обратить (реверсировать) строку.

Решение

Чтобы обратить строку «на месте», не используя временной строки, используйте шаблон функции reverse из заголовочного файла <algorithm>:

std::reverse(s.begin(), s.end());

Обсуждение

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

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

std::string s = 'Los Angeles';

std::string rs;

rs.assign(s.rbegin(), s.rend());

rbegin и rend возвращают реверсивные итераторы. Реверсивные итераторы ведут себя так, как будто они просматривают последовательность в обратном порядке. rbegin возвращает итератор, который указывает на последний элемент, a rend возвращает итератор, указывающий на позицию перед первым элементом. Это в точности обратно тому, что делают begin и end.

Но должны ли вы обращать строку? С помощью rbegin и rend для обратной строки можно использовать все методы или алгоритмы, работающие с диапазонами итераторов. А если требуется выполнить поиск в строке, то можно использовать rfind, которая делает то же, что и find, но начинает с конца строки и движется к ее началу. Для больших строк или большого количества строк обращение может оказаться очень дорогостоящим, так что при возможности избегайте его.

4.6. Разделение строки

Проблема

Требуется разделить строку с разделителями на несколько строк. Например, может потребоваться разделить строку 'Name|Address|Phone' на три отдельных строки — 'Name', 'Address' и 'Phone', удалив при этом разделитель.

Решение

Для перехода от одного вхождения разделителя к следующему используйте метод find класса basic_string, а для копирования каждой подстроки используйте substr. Для хранения результатов используйте любую стандартную последовательность. Пример 4.10 использует vector.

Пример 4.10. Разделение строки с разделителями

#include <string>

#include <vector>

#include <functional>

#include <iostream>

using namespace std;

void split(const string& s, char c, vector<string>& v) {

 string::size_type i = 0;

 string::size_type j = s.find(c);

 while (j != string::npos) {

  v.push_back(s.substr(i, j-i));

  i = ++j;

  j = s.find(c, j);

  if (j == string::npos)

   v.push_back(s.substr(i, s.length()));

 }

}

int main() {

 vector<string> v;

 string s = 'Account Name|Address 1|Address 2 |City';

 split(s, '|', v);

 for (int i = 0; i < v.size(); ++i) {

  cout << v[i] << ' ';

 }

}

Обсуждение

Превращение приведенного выше примера в шаблон функции, принимающий любой тип символов, тривиально — просто параметризуйте тип символов и замените случаи использования string на basic_string<T>.

template<typename T>

void split(const basic_string<T>& s, T c,

 vector<basic_string<T> >& v) {

 basic_string<T>::size_type i = 0;

 basic_string<T>::size_type j = s.find(c);

 while (j != basic_string<T>::npos) {

  v.push_back(s.substr(i, j-i));

  i = ++j;

  j = s.find(c, j);

  if (j == basic_string<T>::npos)

   v.push back(s.substr(i, s.length()));

 }

}

Логика при этом не меняется.

Однако обратите внимание, что между двумя последними угловыми скобками в последней строке заголовка функции добавлен один пробел. Это требуется для того, чтобы сказать компилятору, что это не оператор сдвига вправо.

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату