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


Обрабатываем знаки препинания


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

magical but untamed. "Daddy, shush, there is no such thing,"

у нас получился такой набор слов:

magical

but

untamed.

"Daddy,

shush,

there

is

no

such

thing,"



Как нам теперь удалить ненужные знаки препинания? Для начала определим строку, содержащую все символы, которые мы хотим удалить:

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

(Обратная косая черта указывает на то, что следующий за ней символ должен в данном контексте восприниматься буквально, а не как специальная величина. Так, \" обозначает символ двойной кавычки, а не конец строки, а \\ – символ обратной косой черты.)

Теперь можно применить функцию-член find_first_of() для поиска всех вхождений нежелательных символов:

while (( pos = word.find_first_of( filt_elems, pos ))

            != string::npos )

Найденный символ удаляется с помощью функции-члена erase():

word.erase(pos,1);

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

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

void

filter_text( vector<string> *words, string filter )

{

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

    vector<string>::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"


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