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";