Выбрать главу

word.erase(pos,1);

Первый аргумент этой функции означает позицию подстроки, а второй – ее длину. Мы удаляем один символ, находящийся в позиции pos. Второй аргумент является необязательным; если его опустить, будут удалены все символы от pos до конца строки.

Вот полный текст функции filter_text(). Она имеет два параметра: указатель на вектор строк, содержащий текст, и строку с символами, которые нужно убрать.

void

filter_text( vectorstring *words, string filter )

{

vectorstring::iterator iter = words-begin();

vectorstring::iterator iter_end = words-end();

// Если filter не задан, зададим его сами

if ( ! filter.size() )

filter.insert( 0, "\".," );

while ( iter != iter_end ) {

string::size_type pos = 0;

// удалим каждый найденный элемент

while (( pos = (*iter).find_first_of( filter, pos ))

!= string::npos )

(*iter).erase(pos,1);

iter++;

}

}

Почему мы не увеличиваем значение pos на каждой итерации? Что было бы, если бы мы написали:

while (( pos = (*iter).find_first_of( filter, pos ))

!= string::npos )

{

(*iter).erase(pos,1);

++ pos; // неправильно...

}

Возьмем строку

thing,"

На первой итерации pos получит значение 5 , т.е. позиции, в которой находится запятая. После удаления запятой строка примет вид

thing"

Теперь в 5-й позиции стоит двойная кавычка. Если мы увеличим значение pos, то пропустим этот символ.

Так мы будем вызывать функцию filter_text():

string filt_elems( "\",.;:!?)(\\/" );

filter_text( text_locations-first, filt_elems );

А вот часть распечатки, сделанной тестовой версией filter_text():

filter_text: untamed.

found! : pos: 7.

after: untamed

filter_text: "Daddy,

found! : pos: 0.

after: Daddy,

found! : pos: 5.

after: Daddy

filter_text: thing,"

found! : pos: 5.

after: thing"

found! : pos: 5.

after: thing

filter_text: "I

found! : pos: 0.

after: I

filter_text: Daddy,

found! : pos: 5.

after: Daddy

filter_text: there?"

found! : pos: 5.

after: there"

found! : pos: 5.

after: there

Упражнение 6.15

Напишите программу, которая удаляет все символы, кроме STL из строки:

"/.+(STL).$1/"

используя сначала erase(pos,count), а затем erase(iter,iter).

Упражнение 6.16

Напишите программу, которая с помощью разных функций вставки из строк

string sentence( "kind of" );

string s1 ( "whistle" )

string s2 ( "pixie" )

составит предложение

"A whistling-dixie kind of walk"

6.10. Приводим слова к стандартной форме

Одной из проблем при разработке текстовых поисковых систем является необходимость распознавать слова в различных словоформах, такие, как cry, cries и cried, baby и babies, и, что гораздо проще, написанные заглавными и строчными буквами, например home и Home. Первая задача, распознавание словоформ, слишком сложна, поэтому мы приведем здесь ее заведомо неполное решение. Сначала заменим все прописные буквы строчными:

void

strip_caps( vectorstring,allocator *words )

{

vectorstring,allocator::iterator iter=words-begin() ;

vectorstring,allocator::iterator iter_end=words-end() ;

string caps( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );

while ( iter != iter_end ) {

string::size_type pos = 0;

while (( pos = (*iter).find_first_of( caps, pos ))

!= string::npos )

(*iter)[ pos ] = to1ower( (*iter)[pos] );

++iter;

}

}

Функция

to1ower( (*iter)[pos] );

входит в стандартную библиотеку С. Она заменяет прописную букву соответствующей ей строчной. Для использования tolower() необходимо включить заголовочный файл:

#include ctype.h

(В этом файле объявлены и другие функции, такие, как isalpha(), isdigit(), ispunct(), isspace(), toupper(). Полное описание этих функций см. [PLAUGER92]. Стандартная библиотека С++ включает класс ctype, который инкапсулирует всю функциональность стандартной библиотеки Си, а также набор функций, не являющихся членами, например toupper(), tolower() и т.д. Для их использования нужно включить заголовочный файл

#include locale

Однако наша реализация компилятора еще не поддерживала класс ctype, и нам пришлось использовать стандартную библиотеку Си.)

Проблема словоформ слишком сложна для того, чтобы пытаться решить ее в общем виде. Но даже самый примитивный вариант способен значительно улучшить работу нашей поисковой системы. Все, что мы сделаем в данном направлении, – удалим букву 's' на концах слов: