Private-Bookers
C++. Сборник рецептов
вернуться

Когсуэлл Джефф

Шрифт:

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] << '\n';

 }

}

Обсуждение

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

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));

 }

}

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

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

Пример 4.10 разбивает строку с помощью простого алгоритма. Начиная с начала строки, он ищет первое вхождение разделителя с, а затем считает, что все, что стоит после начала строки или предыдущего найденного вхождения и до этого вхождения, является очередным фрагментом текста. Для поиска первого вхождения символа в оригинальной строке

string
пример использует метод
find
, а для копирования символов диапазона в новую
string
, помещаемую в
vector
, — метод
substr
. Это тот же самый принцип, который используется в функциях разбиения строк большинства скриптовых языков и является специальным случаем разделения строки текста на лексемы (tokenizing), описываемого в рецепте 4.7.

Разделение строки, использующей единственный символ-разделитель, является очень распространенной задачей, и неудивительно, что ее решение есть в библиотеке Boost String Algorithms. Оно просто в использовании. Чтобы увидеть, как разделить строку с помощью функции

split
из Boost, посмотрите на пример 4.11.

Пример 4.11. Разделение строки с помощью Boost

#include <iostream>

#include <string>

#include <list>

#include <boost/algorithm/string.hpp>

using namespace std;

using namespace boost;

int main {

 string s = "one,two,three,four";

 list<string> results;

 split(results, s, is_any_of(",")); // Обратите внимание - это boost::split

 for (list<string>::const_iterator p = results.begin;

p != results.end; ++p) {

  • Читать дальше
  • 1
  • ...
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • ...

Private-Bookers - русскоязычная библиотека для чтения онлайн. Здесь удобно открывать книги с телефона и ПК, возвращаться к сохраненной странице и держать любимые произведения под рукой. Материалы добавляются пользователями; если считаете, что ваши права нарушены, воспользуйтесь формой обратной связи.

Полезные ссылки

  • Моя полка