Окончательная программа
Ниже представлен полный текст программы, разработанной в этой главе, с двумя модификациями: мы инкапсулировали все структуры данных и функции в класс TextQuery (в последующих главах мы обсудим подобное использование классов), кроме того, текст был изменен, так как наш компилятор поддерживал стандарт С++ не полностью.
Например, библиотека iostream не соответствовала текущему стандарту. Шаблоны не поддерживали значения аргументов по умолчанию. Возможно, вам придется изменить кое-что в этой программе, чтобы она компилировалась в вашей системе.
// стандартные заголовочные файлы С++
#include <algorithm>
#include <string>
#include <vector>
#include <utility>
#include <map>
#include <set>
// заголовочный файл iostream, не отвечающий стандарту
#include <fstream.h>
// заголовочные файлы С
#include <stddef.h>
#include <ctype.h>
// typedef для удобства чтения
typedef pair<short,short> location;
typedef vector<location,allocator> loc;
typedef vector<string,allocator> text;
typedef pair<text*,loc*> text_loc;
class TextQuery {
public:
TextQuery() { memset( this, 0, sizeof( TextQuery )); }
static void
filter_elements( string felems ) { filt_elems = felems; }
void query_text();
void display_map_text();
void display_text_locations();
void doit() {
retrieve_text();
separate_words();
filter_text();
suffix_text();
strip_caps();
build_word_map();
}
private:
void retrieve_text();
void separate_words():
void filter_text();
void strip_caps();
void suffix_textQ;
void suffix_s( string& );
void build_word_map();
private:
vector<string,allocator> *lines_of_text;
text_loc *text_locations;
map< string,loc*,
less<string>,allocator> *word_map;
ааа static stringаааааааааааааааа filt_elems;
};
string TextQuery::filt_elems( "\", Х;: !?)(\V" );
int main()
{
ааа TextQuery tq;
ааа tq.doit();
ааа tq.query_text();
ааа tq.display_map_text();
}
void
TextQuery::
retrieve_text()
{
ааа string file_name;
ааа cout << " please enter file name: ";
ааа cin >> file_name;
ааа ifstream infile( file_name.c_str(), ios::in );
ааа if ( !infile ) {
ааааааа cerr << "oops' unable to open file "
аааааааааааа << file_name <<ааа " -- bailing out!\n";
аааааа аexit( -1 );
ааа }
ааа else cout << "\n";
ааа lines_of_text = new vector<string,allocator>;
ааа string textline;
ааа while ( getline( infile, textline, '\n' ))
ааааааа lines_of_text->push_back( textline );
}
void
TextQuery::
separate_words()
{
ааа vector<string,allocator> *words =
аааааааааааааа new vector<string,allocator>;
ааа vector<location,allocator> *locations =
аааааааааааааа new vector<location,allocator>;
ааа for ( short line_pos = 0; line_pos < lines_of_text->size();
ааааааа line_pos++ )
ааа {
ааааааа short word_pos = 0;
ааааааа string textline = (*lines_of_text)[ line_pos ];
ааааааа string::size_type eol = textline.1ength();
ааааааа string::size_type pos = 0, prev_pos = 0;
ааааааа while (( pos = textline.find_first_of( ' ', pos ))
ааааааааа аааааааааа!= string::npos )
ааааааа {
ааааааааааа words->push_back(
ааааааааааааааа textline.substr( prev_pos, pos - prev_pos ));
ааааааааааа locations->push_back(
ааааааааааааааа make_pair( line_pos, word_pos ));
ааааааааааа word_pos++; pos++; prev_pos = pos;
ааааааа }
ааааааа words->push_back(
ааааааааааа textline.substr( prev_pos, pos - prev_pos ));
ааааааа locations->push_back(make_pair(line_pos,word_pos));
ааа }
ааа text_locations = new text_loc( words, locations );
}
void
TextQuery::
filter_text()
{
ааа if ( filt_elems.empty() )
ааааааа return;
ааа vector<string,allocator> *words = text_locations->first;
ааа vector<string,allocator>:: iterator iter = words->begin();
ааа vector<string,allocator>::iterator iter_end = words->end();
ааа while ( iter != iter_end )
ааа {
ааааааа string::size_type pos = 0;
ааааааа while ((pos = (*iter).find_first_of(filt_elems, pos))
аааааааааааааааааа != string::npos )
ааааааааааа (*iter).erase(pos,l);
ааааааа ++iter;
ааа }
}
void
TextQuery::
suffix_text()
{
ааа vector<string,allocator> *words = text_locations->first;
ааа vector<string,allocator>::iterator iter = words->begin();
ааа vector<string,allocator>::iterator iter_end = words->end() ;
ааа while ( iter != iter_end ) {
ааааааа if ( (*iter).size() <= 3 )
аааааааа ааа{ iter++; continue; }
ааааааа if ( (*iter)[ (*iter).size()-l ] == 's' )
ааааааааааа suffix_s( *iter );
ааааааа // фюяюыэшЄхы№эр юсЁрсюЄър ёєЇЇшъёют...
ааааааа iter++;
ааа }
}
void
TextQuery::
suffix_s( string &word )
{
ааа 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 ) ||
аааааааа ! word.compare( pos3, 3, suffixes, spos+6, 3) ||
аааааааа ! word.compare( pos3+l, 2, suffixes, spos+2, 2 ) ||
аааааааа ! word.compare( pos3+l, 2, suffixes, spos+4, 2 ))
ааааааааааа return;
ааа string ies( "ies" );
ааа if ( ! word.compare( pos3, 3, ies ))
ааа {
ааааааа word.replace( pos3, 3, 1, 'є' );
ааааааа return;
ааа }
ааа string ses( "ses" );
ааа if ( ! word.compare( pos3, 3, ses ))
ааа {
ааааааа word.erase( pos3+l, 2 );
ааааааа return;
ааа }
ааа // єфрышь 's' т ъюэЎх
ааа word.erase( pos3+2 );
ааа // єфрышь "'s"
ааа if ( word[ pos3+l ] == '\'' )
ааааааа word.erase( pos3+l );
}
void
TextQuery::
strip_caps()
{
ааа vector<string,allocator> *words = text_locations->first;
ааа vector<string,allocator>::iterator iter = words->begin();
ааа vector<string,allocator>::iterator iter_end = words->end();
ааа string caps( "ABCDEFGHI3KLMNOPQRSTUVWXYZ" );
ааа 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;
ааа }
}
void
TextQuery::
build_word_map()
{
ааа word_map = new map<string,loc*,less<string>,allocator>;
ааа typedef map<string,loc*,less<string>,allocator>::value_type
ааааааа value_type;
ааа typedef set<string,less<string>,allocator>::difference_type
ааааааа diff_type;
ааа set<string,less<string>,allocator> exclusion_set;
ааа ifstream infile( "exclusion_set" );
ааа if ( !infile )
ааа {
ааааааа static string default_excluded_words[25] = {
ааааааааа "the","and","but","that","then","are","been",
ааааааааа "can","can't","cannot","could","did","for",
ааааааааа "had","have","him","his","her","its"."into",
ааааааааа "were","which","when","with","would"
ааааааа };
ааааааа cerr <<
аааааааааа "warning! unable to open word exclusion file! -- "
аааааааааааа << "using default set\n";
ааааааа copy( default_excluded_words,
ааааааааааааа default_excluded_words+25,
ааааааааааааа inserter(exclusion_set, exclusion_set.begin()));
ааа }
ааа else {
ааааааа istream_iterator< string, diff_type >
ааааааааааа input_set( infile ), eos;
ааааааа copy( input_set, eos,
ааааааааааа inserter( exclusion_set, exclusion_set.begin() ));
ааа }
ааа // яЁюсхцшьё яю тёхь ёыютрь, тёЄрты ярЁv
ааа vector<string,allocator> *text_words =
ааааааа text_locations->first;
ааа vector<location,allocator> *text.locs =
ааааааа text_locations->second;
ааа register int elem_cnt = text_words->size();
ааа for ( int ix = 0; ix < elem_cnt; ++-ix )
ааа {
ааааааа string textword = ( *text_words )[ ix ];
ааааааа if ( textword.size() < 3 ||
ааааааааааа exclusion_set.count( textword ))
ааааааааааааааа continue;
ааааааа if ( ! word_map->count((*text_words)[ix] ))
ааааааа { // ёыютю юЄёєЄёЄтєхЄ, фюсртшь:
ааааааааааа loc *ploc = new vector<location,allocator>;
ааааааааааа ploc->push_back( (*text_locs)[ix] );
ааааааааааа word_map->
ааааааааааааааа insert( value_type( (*text_words)[ix],ploc ));
ааааааа }
ааааааа else (*word_map) [(*text_words) [ix]]->
ааааааааааааааа push_back( (*text_locs) [ix] );
ааа }
}
void
TextQuery::
query_text()
{
ааа string query_text;
ааа do {
ааааааа cout
ааааааа << "enter a word against which to search the text.\n"
ааааааа << "to quit, enter a single character ==> ";
ааааааа cin >> query_text;
ааааааа if ( query_text.size() < 2 ) break;
ааааааа string caps( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
ааааааа string::size_type pos = 0;
ааааааа while (( pos = query_text.find_first_of( caps, pos ))
ааааааааааааааааа аа!= string::npos )
ааааааааааа query_text[ pos ] = to1ower( query_text[pos] );
ааааааа // query_text фюыцэю сvЄ№ ттхфхэю
ааааааа if ( !word_map->count( query_text )) {
ааааааааааа cout << "\nSorry. There are no entries for "
аааааааааааааааа << query_text << ".\n\n";
ааааааааааа continue;
ааааааа }
ааааааа loc *ploc = (*word_map) [ query_text ];
ааааааа set<short,less<short>,allocator> occurrence_1i nes;
ааааааа loc::iterator liter = ploc->begin(),
ааааааааааааааааааааа liter_end = ploc->end();
ааааа ааwhile ( liter != liter_end ) {
аааааааааааа occurrence_lines.1nsert(
аааааааааааааааааа occurrence_lines.end(), (*liter).first);
аааааааааааа ++liter;
ааааааа }
ааааааа register int size = occurrence_lines.size();
ааааааа cout << "\n" << query_text
ааа ааааааааа<< " occurs " << size
аааааааааааа << (size == 1 ? " time:" : " times:")
аааааааааааа << "\n\n";
ааааааа set<short,less<short>,allocator>::iterator
ааааааааааааа it=occurrence_lines.begin();
ааааааа for ( ; it != occurrence_"lines.end(); ++it ) {
ааааааааааа int line = *it;
ааааааааааа cout << "\t( line "
аааааааааааааааа // сєфхь эєьхЁютрЄ№ ёЄЁюъш ё 1,
аааааааааааааааа // ъръ ¤Єю яЁшэ Єю тхчфх
аааааааааааааааа << line + 1 << " ) "
аааааааааааааааа << (*lines_of_text)[line] << endl;
ааааааа }
ааааааа cout << endl;
ааа }
ааа while ( ! query_text.empty() );
ааа cout << "Ok, bye!\n";
}
void
TextQuery::
display_map_text()
{
ааа typedef map<string,loc*, less<string>, allocator> map_text;
ааа map_text::iterator iter = word_map->begin(),
аааааааааааааааааааааа iter_end = word_map->end();
ааа while ( iter != iter_end ) {
ааааааа cout << "word: " << (*iter).first << " (";
ааааааа intаааааааааа loc_cnt = 0;
ааааааа locааааааааа *text_locs = (*iter).second;
ааааааа loc::iterator literаааа = text_locs->begin(),
ааааааааааааааааааааа liter_end = text_locs->end();
ааааааа while ( liter != liter_end )
ааааааа {
ааааааааааа if ( loc_cnt )
ааааааааааааааа cout << ",";
ааааааааааа else ++loc_cnt;
ааааааааааа cout << "(" << (*liter).first
аааааааааааааааа << "," << (*liter).second << ")";
ааааааааааа ++"liter;
ааааааа }
ааааааа cout << ")\n";
ааааааа ++iter;
ааа }
ааа cout << endl;
}
void
TextQuery::
disp1ay_text_locations()
{
ааа vector<string,allocator> *text_words =
ааааааа text_locations->first;
ааа vector<location,allocator> *text_locs =
ааааааа text_locations->second;
ааа register int elem_cnt = text_words->size();
ааа if ( elem_cnt != text_locs->size() )
ааа {
ааааааа cerr
аааааааа << "oops! internal error: word and position vectors "
аааааааа << "are of unequal size\n"
аааааааа << "words: " << elem_cnt << " "
аааааааа << "locs: " << text_locs->size()
аааааааа << " -- bailing out!\n";
ааааааа exit( -2 );
ааа }
ааа for ( int ix=0; ix < elem_cnt; ix++ )
ааа {
ааааааа cout << "word: " << (*text_words)[ ix ] << "\t"
аааааааааааа << "location: ("
аааааааааааа << (*text_locs)[ix].first << ","
аааааааааааа << (*text.locs)[ix].second << ")"
аааааааааааа << "\n";
ааа }
ааа cout << endl;
}
LяЁрцэхэшх 6.25
+с· ёэшЄх, яюўхьє эрь яюЄЁхсютрыё ёяхЎшры№эvщ ъырёё inserter фы чряюыэхэш эрсюЁр ёЄюя-ёыют (¤Єю єяюьшэрхЄё т Ёрчфхых 6.13.1, р фхЄры№эю ЁрёёьрЄЁштрхЄё т 12.4.1).
set<string> exclusion_set;
ifstreamааа infile( "exclusion_set" );
copy( default_excluded_words, default_excluded_words+25,
ааааа inserter(exclusion_set, exclusion_set.begin() ));
LяЁрцэхэшх 6.26
¦хЁтюэрўры№эр ЁхрышчрЎш яюшёъютющ ёшёЄхьv юЄЁрцрхЄ яЁюЎхфєЁэvщ яюфїюф: эрсюЁ уыюсры№эvї ЇєэъЎшщ юяхЁшЁєхЄ эрсюЁюь эхчртшёшьvї ёЄЁєъЄєЁ фрээvї. +ъюэўрЄхы№эvщ трЁшрэЄ яЁхфёЄрты хЄ ёюсющ ры№ЄхЁэрЄштэvщ яюфїюф, ъюуфр ьv шэъряёєышЁєхь ЇєэъЎшш ш фрээvх т ъырёё TextQuery. TЁртэшЄх юср ёяюёюср. ¦ръютv эхфюёЄрЄъш ш яЁхшьє•хёЄтр ърцфюую?
LяЁрцэхэшх 6.27
T фрээющ тхЁёшш яЁюуЁрььv шь Їрщыр ё ЄхъёЄюь ттюфшЄё яю чряЁюёє. +юыхх єфюсэю сvыю сv чрфртрЄ№ хую ъръ ярЁрьхЄЁ ъюьрэфэющ ёЄЁюъш; т уыртх 7 ьv яюърцхь, ъръ ¤Єю фхырхЄё . ¦ръшх х•х ярЁрьхЄЁv ъюьрэфэющ ёЄЁюъш цхырЄхы№эю ЁхрышчютрЄ№?