C++ Primer学习笔记12章知识点

C++ Primer学习笔记12章知识点

C++ Primer学习笔记12章知识点学好泛型,受用无穷!

STL的容器都是定义在std namespace;所以光是包含相应的头文件是不可取的,至少加上:

using namespace std; 或者是:using std:: ×××(你用的容器);

在预处理器的后面。

其实对于gnu c++来说,.c后缀和.cpp后缀没有什么分别,但对于MS VS来说就是C程序和C++程序的区别了;

/*************************************************************************

其实lippman先生写的下面的这个程序的执行并非像是书上的那么理想。在处理大写字母和符号上有些问题(他老人家很可能是故意的)。此程序的主要功能是:从两个text files中读取string,每一个text files 都被放入string vector, 而这两个string vector又被放入一个string vector中,这样泛型算法处理的对象就有了,然后执行各种泛型操作。这个程序皆是由泛型算法+函数对象进行串处理。有些事情说来真是悲哀:越是看到最后越觉是理所当然。of course

是我们该出手的时候了,我们要修改这个程序,使这个玩具完善起来。我们模仿第六章的做法对string vector先进行大小写字母的转换,然后,擦除句中的标点,最后再进行一系列的操作。

*************************************************************************/

#include <vector>

#include <string>

#include <algorithm>

#include <iterator>

//#include <iostream.h>

#include <iostream>

using namespace std;

class GreaterThan {

public:

GreaterThan( int size = 6 ) : _size( size ){}

int size() { return _size; }

bool operator()(const string & s1) {

return s1.size() > 6;

}

private:

int _size;

};

template <class Type>

class PrintElem {

public:

void operator()( const Type &elem )

{

++_cnt;

if ( _cnt % 8 == 0 ) { cout << endl; }

cout << elem << " ";

}

 

private:

static int _cnt;

};

template < class Type >

int PrintElem<Type>::_cnt = 0;

class LessThan {

public:

bool operator()(const string & s1, const string & s2 ) {

return s1.size() < s2.size();

}

};

typedef vector<string> textwords;

void process_vocab( vector<textwords> *pvec )

{

if ( ! pvec )

// issue warning message

return;

vector< string > texts;

vector<textwords>::iterator iter = pvec->begin();

for ( ; iter != pvec->end(); ++iter )

copy( (*iter).begin(), (*iter).end(), back_inserter( texts ));

// sort the elements of texts

sort( texts.begin(), texts.end() );

for_each( texts.begin(), texts.end(), PrintElem<string>() );

cout << endl << endl;

// delete all duplicate elements

vector<string>::iterator it;

it = unique( texts.begin(), texts.end() );

texts.erase( it, texts.end() );

for_each( texts.begin(), texts.end(), PrintElem<string>() );

cout << endl << endl;

stable_sort( texts.begin(), texts.end(), LessThan() );

for_each( texts.begin(), texts.end(), PrintElem<string>() );

cout << endl << endl;

// count number of strings greater than length 6

int cnt = 0;

// obsolete form of count -- standard changes this

cnt = count_if( texts.begin(), texts.end(), GreaterThan());

cout << "Number of words greater than length six are "

<< cnt << endl;

// ...

static string rw[] = { "and", "if", "or", "but", "the" };

vector<string> remove_words( rw, rw+5 );

vector<string>::iterator it2 = remove_words.begin();

for ( ; it2 != remove_words.end(); ++it2 ) {

int cnt = 0;

// obsolete form of count -- standard changes this

cnt = count( texts.begin(), texts.end(), *it2);

 

cout << cnt << " instances removed: "

<< (*it2) << endl;

 

texts.erase(

remove(texts.begin(),texts.end(),*it2),

texts.end()

);

}

cout << endl << endl;

for_each( texts.begin(), texts.end(), PrintElem<string>() );

}

typedef vector<string>::difference_type diff_type;

#include <fstream>

main()

{

vector<textwords> sample;

vector<string> t1, t2;

string t1fn, t2fn;

cout << "text file #1: "; cin >> t1fn;

cout << "text file #2: "; cin >> t2fn;

ifstream infile1( t1fn.c_str());

ifstream infile2( t2fn.c_str());

istream_iterator< string > input_set1( infile1 ), eos;

istream_iterator< string > input_set2( infile2 );

copy( input_set1, eos, back_inserter( t1 ));

copy( input_set2, eos, back_inserter( t2 ));

sample.push_back( t1 ); sample.push_back( t2 );

process_vocab( &sample );

}

首先我们增加过滤标点符号的函数:

void filter_text(vector<string>&text)

{

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

if( filt_elems.empty() ) return;

vector<string>::iterator iter = text.begin();

vector<string>::iterator iter_end = text.end();

while( iter != iter_end ){

string::size_type pos = 0;

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

!= string::npos )

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

++iter;

}

}

其次增加转换大写为小写的函数:

void strip_caps(vector<string>&text)

{

 

const string caps( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );

vector<string>::iterator iter = text.begin();

vector<string>::iterator iter_end = text.end();

while( iter != iter_end ){

string::size_type pos = 0;

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

!= string::npos )

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

++iter;

}

}

OK,在适当的位置插入这两个函数。

最终的程序如下所示:

#include <vector>

#include <string>

#include <algorithm>

#include <iterator>

#include <iomanip>

#include <iostream>

using namespace std;

#include <ctype.h>

 

//prestandard syntax for <iostream>

//#include <iostream>


//过滤标点符号的函数

void filter_text(vector<string>&text)

{

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

if( filt_elems.empty() ) return;

vector<string>::iterator iter = text.begin();

vector<string>::iterator iter_end = text.end();

while( iter != iter_end ){

string::size_type pos = 0;

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

!= string::npos )

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

++iter;

}

}

//大小写字母转换函数

void strip_caps(vector<string>&text)

{

 

const string caps( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );

vector<string>::iterator iter = text.begin();

vector<string>::iterator iter_end = text.end();

while( iter != iter_end ){

string::size_type pos = 0;

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

!= string::npos )

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

++iter;

}

}

//所谓的函数对象,是为了函数所以对象

class GreaterThan {

public:

GreaterThan( int sz = 6 ) : _size( sz ) { }

int size() { return _size; }

bool operator()( const string & s1 )

{ return s1.size() > _size; }

private:

int _size;

};

class PrintElem {

public:

PrintElem( int lineLen = 8 )

: _line_length( lineLen ), _cnt( 0 )

{ }

void operator()( const string &elem ) {

++_cnt;

if ( _cnt % _line_length == 0 ) {

cout << '/n';

}

cout << elem << " ";

}

private:

int _line_length;

int _cnt;

};

// a function object -- the operation is

// implemented as an instance of operator()

class LessThan {

public:

bool operator()( const string & s1,

const string & s2 )

{

return s1.size() < s2.size();

}

};

// The following code has been commented because 'allocator'

// being a template class, should be given template arguments.

// typedef vector<string, allocator> textwords;

typedef vector<string> textwords;

// The following code has been commented because 'allocator'

// being a template class, should be given template arguments.

// void process_vocab( vector<textwords, allocator> *pvec )

void process_vocab( vector<textwords> *pvec )

{

if ( !pvec ) {

//test pointer to vector<textwords>

// issue warning message

cout << "Invalid argument...../n";

return;

}

// The following code has been commented because 'allocator'

// being a template class, should be given template arguments.

// vector<string, allocator> texts;

vector<string> texts;

// The following code has been commented because 'allocator'

// being a template class, should be given template arguments.

// vector<textwords, allocator>::iterator iter;

vector<textwords>::iterator iter;

for ( iter = pvec->begin(); iter != pvec->end(); ++iter )

copy( ( *iter ).begin(), ( *iter ).end(),

back_inserter( texts ) );

 

//before operate

cout << "/nBefor operating 'texts' contains:/n";

for_each( texts.begin(), texts.end(), PrintElem() );

cout << "/n/n";

 

filter_text(texts);

strip_caps(texts);

 

// sort the elements of texts

sort( texts.begin(), texts.end() );

// ok, let's see what we have

cout << "/nAfter applying 'sort()' the vector 'texts' contains: /n";

for_each( texts.begin(), texts.end(), PrintElem() );

cout << "/n/n";