C++ primer plus 第16章string 类和标准模板库, 使用 STL
C++ primer plus 第16章string 类和标准模板库, 使用 STL
16.6.5使用 STL
STL是一个库,其组成部分被设计成协同工作。STL组件是工具,但也是创建其他工具的基本部件。我们用一个例子说明。假设要编写一个程序,让用户输入单词。希望最后得到一个按输入顺序排列的单词列表、一个按字母顺序排列的单词列表(忽略大小写),并记录每个单词被输入的次数。出于简化的目的,假设输入中不包含数字和标点符号。
输入和保存单词列表很简单。可以按程序清单16.8和程序清单16.9那样创建一个vector对象,并用 push back()将输入的单词添加到矢量中:
vector<string>words;
string input;
while(cin >>input && input != "quit")
words.push back(input);
如何得到按字母顺序排列的单词列表呢?可以使用sort(),然后使用unique(),但这种方法将覆盖原始数据,因为 sor()是就地算法。有一种更简单的方法,可以避免这种问题:创建一个set对象,然后将矢量中的单词复制(使用插入迭代器)到集合中。集合自动对其内容进行排序,因此无需调用sor();集合只允许同一个键出现一次,因此无需调用unique()。这里要求忽略大小写,处理这种情况的方法之一是使用 transfom()而不是 copy(),将矢量中的数据复制到集合中。使用一个转换函数将字符串转换成小写形式。
set<string> wordset;
transform(words.begin(),words .end()
insert_iterator<set<string>>(wordset,wordset.begin()),ToLower);
ToLower()函数很容易编写,只需使用transform()将tolower()函数应用于字符串中的各个元素,并将字符串用作源和目标。记住,string对象也可以使用STL函数。将字符串按引用传递和返回意味着算法不必复制字符串,而可以直接操作原始字符串。下面是函数ToLower()的代码:
string & ToLower(string &st)
{
transform(st.begin(),st.end(),st.begin(), tolower);return st;
}
·个可能出现的问题是:tolower()函数被定义为inttolower(int),而一些编译器希望函数与元素类型(即 char)匹配。一种解决方法是,使用toLower 代替tolower,并提供下面的定义:
char toLower(char ch){return tolower(ch)};
要获得每个单词在输入中出现的次数,可以使用count()函数。它将一个区间和一个值作为参数,并返回这个值在区间中出现的次数。可以使用vector 对象来提供区间,并使用set 对象来提供要计算其出现次数的单词列表。即对于集合中的每个词,都计算它在矢量中出现的次数。要将单词与其出现的次数关联起来,可将单词和计数作为 pair<conststring,in>对象存储在map对象中。单词将作为键(只出现一次),计数作为值。这可以通过一个循环来完成:
map<string,int> wordmap;
set<string>::iterator si;
for(si=wordset.begin();si != wordset.end(); si++)
wordmap.insert(pair<string,int>(*si, count(words.begin()
words.end()*si)));
map类有一个有趣的特征:可以用数组表示法(将键用作索引)来访问存储的值。例如,wordmap[“the”表示与键“te”相关联的值,这里是字符串“the”出现的次数。因为 wordset 容器保存了 wordmap 使用的全部键,所以可以用下面的代码来存储结果,这是一种更具吸引力的方法:
for(si=wordset.begin();si != wordset.end(); si++)
wordmap[*si]=count(words.begin(),words.end()*si);
因为 si指向 wordset 容器中的一个字符串,所以*si是一个字符串,可以用作 wordmap 的键。上述代码将键和值都放到 wordmap 映象中。
同样,也可以使用数组表示法来报告结果:
for(si=wordset.begin();si != wordset.end(); si++)
cout <*si<s":"<< wordmap[*si]<< endl;
如果键无效,则对应的值将为 0。
程序清单16.19把这些想法组合在一起,同时包含了用于显示3个容器(包含输入内容的矢量、包含单词列表的集合和包含单词计数的映象)内容的代码。
程序清单16.19 usealgo.cpp
//usealgo.cpp -- using several STL elements
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <iterator>
#include <algorithm>
#include <cctype>
using namespace std;
char toLower(char ch) { return tolower(ch); }
string & ToLower(string & st);
void display(const string & s);
int main()
{
vector<string> words;
cout << "Enter words (enter quit to quit):\n";
string input;
while (cin >> input && input != "quit")
words.push_back(input);
cout << "You entered the following words:\n";
for_each(words.begin(), words.end(), display);
cout << endl;
// place words in set, converting to lowercase
set<string> wordset;
transform(words.begin(), words.end(),
insert_iterator<set<string> > (wordset, wordset.begin()),
ToLower);
cout << "\nAlphabetic list of words:\n";
for_each(wordset.begin(), wordset.end(), display);
cout << endl;
// place word and frequency in map
map<string, int> wordmap;
set<string>::iterator si;
for (si = wordset.begin(); si != wordset.end(); si++)
wordmap[*si] = count(words.begin(), words.end(), *si);
// display map contents
cout << "\nWord frequency:\n";
for (si = wordset.begin(); si != wordset.end(); si++)
cout << *si << ": " << wordmap[*si] << endl;
// cin.get();
// cin.get();
return 0;
}
string & ToLower(string & st)
{
transform(st.begin(), st.end(), st.begin(), toLower);
return st;
}
void display(const string & s)
{
cout << s << " ";
}
这里的寓意在于,使用STL时应尽可能减少要编写的代码。STL通用、灵活的设计将节省大量工作。
另外,STL设计者就是非常关心效率的算法人员,算法是经过仔细选择的,并且是内联的。