C++ primer plus 第16章string 类和标准模板库, 使用 STL

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设计者就是非常关心效率的算法人员,算法是经过仔细选择的,并且是内联的。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值