С++ для начинающих


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


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

void

strip_caps( vector<string,allocator> *words )

{

    vector<string,allocator>::iterator iter=words->begin() ;

    vector<string,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' на концах слов:

void suffix_text( vector<string,allocator> *words )


{

    vector<string,allocator>::iterator

                  iter = words->begin(),

                  iter_end = words->end();

    while ( iter != iter_end ) {

        // оставим слова короче трех букв как есть

        if ( (*iter).size() <= 3 )

            { ++iter; continue; }

        if ( (*iter)[ (*iter).size()-1 ] == 's' )

            suffix_s( *iter );

        // здесь мы могли бы обработать суффиксы

        // ed, ing, 1y

        ++iter;

    }

}

Слова из трех и менее букв мы пропускаем. Это позволяет оставить без изменения, например, has, its, is и т.д., однако слова tv и tvs мы не сможем распознать как одинаковые.

Если слово кончается на "ies", как babies и cries, необходимо заменить "ies" на "y":

string::size_type pos() = word.size()-3;

string ies( "ies" );

if ( ! word.compare( pos3, 3, ies )) {

    word.replace( pos3, 3, 1, 'у' );

    return;

}

compare() возвращает 0, если две строки равны. Первый аргумент, pos3, обозначает начальную позицию, второй – длину сравниваемой подстроки (в нашем случае 3). Третий аргумент, ies, – строка-эталон. (На самом деле существует шесть вариантов функции compare(). Остальные мы покажем в следующем разделе.)

replace() заменяет подстроку набором символов. В данном случае мы заменяем подстроку "ies" длиной в 3 символа единичным символом 'y'. (Имеется десять перегруженных вариантов функции replace(). В следующем разделе мы коснемся остальных вариантов.)

Если слово заканчивается на "ses", как promises или purposes, нужно удалить суффикс "es"[16]:

string ses( "ses" );

if ( ! word.compare( pos3, 3, ses )) {

    word.erase( pos3+l, 2 );

    return;

}

Если слово кончается на "ous", как oblivious, fulvous, cretaceous, или на "is", как genesis, mimesis, hepatitis, мы не будем изменять его. (Наша система несовершенна. Например, в слове kiwis надо убрать последнее 's'.) Пропустим и слова, оканчивающиеся на "ius" (genius) или на "ss" (hiss, lateness, less). Нам поможет вторая форма функции compare():



string::size_type spos = 0;

string::size_type pos3 = word.size()-3;

// "ous", "ss", "is", "ius"

string suffixes( "oussisius" );

if ( ! word.compare( pos3, 3, suffixes, spos, 3 ) ||     // ous

     ! word.compare( pos3, 3, suffixes, spos+6, 3 ) ||   // ius

     ! word.compare( pos3+l, 2, suffixes, spos+2, 2 ) || // ss

     ! word.compare( pos3+l, 2, suffixes, spos+4, 2 ) )  // is

    return;

В противном случае удалим последнее 's':

// удалим последнее 's'

word.erase( pos3+2 );

Имена собственные, например Pythagoras, Brahms, Burne-Jones, не подпадают под общие правила. Этот случай мы оставим как упражнение для читателя, когда будем рассказывать об ассоциативных контейнерах.

Но прежде чем перейти к ним, рассмотрим оставшиеся строковые операции.

Упражнение 6.17

Наша программа не умеет обрабатывать суффиксы ed (surprised), ly (surprisingly) и ing (surprisingly). Реализуйте одну из функций для этого случая:

(a) suffix_ed()   (b) suffix_ly()      (c) suffix_ing()


Содержание раздела