C++. Сборник рецептов - [65]

Шрифт
Интервал

> }

>}

Обсуждение

Разбиение строки с четко определенной структурой, как в примере 4.10, конечно, хорошо, но не все так просто. Предположим, что, вместо того чтобы просто разделить строку на основе единственного разделителя, требуется разбить строку на лексемы. Наиболее частым вариантом этой задачи является разделение на лексемы с игнорированием пробелов. Пример 4.12 дает реализацию класса >StringTokenizer (аналогичного стандартному классу Java™ с таким же именем) для C++, который принимает символы-разделители, но по умолчанию использует пробелы.

Наиболее важные строки в >StringTokenizer используют методы >find_first_of и >find_first_not_of шаблона класса >basic_string. Их описание и примеры использования даны в рецепте 4.9. Пример 4.12 дает такой вывод.

>Здесь содержится 3 лексемы.

>token = razzle

>token = dazzle

>token = giddyup

>StringTokenizer — это более гибкая форма функции >split из примера 4.10. Он поддерживает свое состояние, так что можно просто последовательно переходить с одной лексемы на другую, не разбивая вначале всю строку на части. Также есть возможность подсчитать число лексем.

В >StringTokenizer можно внести пару усовершенствований. Во-первых, для простоты >StringTokenizer написан так, что он работает только с простыми строками — другими словами, строками из узких символов. Если требуется, чтобы один и тот же класс работал как с узкими, так и с широкими символами, параметризуйте тип символов, как это сделано в предыдущих рецептах. Другим улучшением является расширение >StringTokenizer так, чтобы он обеспечивал более дружественное взаимодействие с последовательностями и был более гибок. Вы всегда можете сделать это сами, а можете использовать имеющийся класс разбиения на лексемы. Проект Boost содержит класс >tokenizer, делающий все это. За подробностями обратитесь к www.boost.org.

Смотри также

Рецепт 4.24.

4.8. Объединение нескольких строк

Проблема

Имея последовательность строк, такую как вывод примера 4.10, вам требуется объединить их в одну длинную строку, возможно, с разделителями.

Решение

В цикле переберите всю последовательность строк и добавьте каждую из них в выходную строку. В качестве входа можно обрабатывать любую стандартную последовательность. Пример 4.13 использует >vector из элементов типа >string.

Пример 4.13. Объединение последовательности строк

>#include

>#include

>#include


>using namespace std;


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

> s.clear();

> for (vector::const_iterator p = v.begin();

>  p ! = v.end(); ++p) {

>  s += *p;

>  if (p != v.end() - 1) s += c;

> }

>}


>int main() {

> vector v;

> vector v2;

> string s;

> v.push_back(string("fее"));

> v.push_back(string("fi"));

> v.push_back(string("foe"));

> v.push_back(string("fum"));

> join(v, '/', s);

> cout << s << '\n';

>}

Обсуждение

Пример 4.13 содержит одну методику, которая несколько отличается от предыдущие примеров. Посмотрите на эту строку.

>for (vector::const_iterator p = v.begin();

Предыдущие примеры работы со строками использовали >iterator'ы без части «const», но здесь без этого не обойтись, так как >v объявлен как ссылка на объект >const. Если имеется объект контейнера >const, то для доступа к его элементам можно использовать только >const_iterator. Это так потому, что простой >iterator позволяет записывать в объект, на который он указывает, что, конечно, нельзя делать в случае с объектами контейнера типа >const.

>v объявлен как >const по двум причинам. Во-первых, я знаю, что я не собираюсь изменять его содержимое, так что я хочу, чтобы компилятор выдал сообщение об ошибке, если это произойдет. Компилятор гораздо лучше меня в деле поиска таких вещей, особенно когда к такому присвоению приводит тонкая семантическая или синтаксическая ошибка. Во-вторых, я хочу показать пользователям этой функции, что я ничего не делаю с их контейнером, и >const — это великолепный способ сделать это. Теперь я просто должен создать обобщенную версию, которая работает с различными типами символов.

Как и в рецепте 4.6, превращение >join в общий шаблон функции очень просто. Все, что требуется сделать, — это изменить заголовок, параметризовав тип символов, как здесь:

>template

>void join(const std::vector >& v, T c,

> std::basic_string& s)

Но >vector может оказаться не единственным возможным входом функции. Вам может потребоваться объединить строки в стиле С. Класс >string C++ предпочтительнее строк в стиле С, так что если возникает такая задача, объединяйте их в C++ >string. После этого всегда можно получить версию С, вызвав метод >string c_str, который возвращает указатель >const на завершающийся нулем массив символов.

Пример 4.14 предлагает общую версию >join, которая объединяет массив символов в >string. Так как новая общая версия параметризована по типу символов, она будет работать как для массивов узких, так и для массивов широких символов.

Пример 4.14 Объединение строк в стиле C

>#include

>#include


>const static int MAGIC_NUMBER = 4;


>template

>void join(T* arr[], size_t n, T c, std::basic_string& s) {

> s.clear();


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

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


Симуляция частичной специализации

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


Обработка событий в С++

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


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.