上一个示例的改进--自定义仿函数(functional)

上一篇文章中(点击查看),我们自定义了一个迭代器line_iterator来封装cin,并借助vector的构造方法,隐式调用了while循环实现若干字符串的输入。示例程序使用了string类,效率不够高,因为构造vector的时候是简单的深拷贝,在sort过程中也是将string对象移动来移动去的,很消耗内存和CPU。现在,我们换一种方式,干脆不用string类,只用char来实现同样的功能。当然,改进的示例仍然用到STL的诸多特性,这正是学习STL的好机会。代码如下所示:

/* 使用迭代器 版本3
 * created: ume
 * date: 2011-12-17
 * remarks:
 *  本例定义了函数对象strtab_cmp及strtab_print
 */
#include<iostream>
#include<vector>
#include<iterator>
#include<algorithm>
using namespace std;
// functional: strtab_cmp
struct strtab_cmp
{
    typedef vector<char>::iterator strtab_iterator;
    bool operator()(pair<strtab_iterator,strtab_iterator>& lhs, 
                    pair<strtab_iterator,strtab_iterator>& rhs)
    {
        return lexicographical_compare(lhs.first,lhs.second,rhs.first,rhs.second);
    }
};
// functional: strtab_print
struct strtab_print
{
    ostream* out;
    strtab_print(ostream& os):out(&os)
    {
    }
    typedef vector<char>::iterator strtab_iterator;
    void operator()(pair<strtab_iterator,strtab_iterator>& line)
    {
        copy(line.first,line.second,ostream_iterator<char>(*out));
    }
};
// main function
int main()
{
    vector<char> strtab;
    char ch;
    while(cin.get(ch))
    {
        strtab.push_back(ch);
    }

    // 分析字符串表,并构造字符串行vector
    typedef vector<char>::iterator strtab_iterator;
    vector<pair<strtab_iterator,strtab_iterator> > lines;
    strtab_iterator start = strtab.begin();
    while(start != strtab.end())
    {
        strtab_iterator next = find(start,strtab.end(),'\n');
        *next = ' ';
        if(next != strtab.end())
            next++;
        lines.push_back(make_pair(start,next));
        start = next;
    }
    // 排序并输出
    sort(lines.begin(),lines.end(),strtab_cmp());
    for_each(lines.begin(),lines.end(),strtab_print(cout));

    system("pause");
    return 0;
}

运行这个示例程序,结果为:

you
are
the
apple
of
my
eye
^Z
apple are eye my of the you 请按任意键继续. . .

与旧的示例程序比起来,运行结果是完全一样的,但实现方法却迥然不同了。

首先观察头文件,这里并没有包含string,因为本例直接用char来保存输入的数据。我们看main函数中的strtab变量,它保存着输入的所有字符。但排序的对象是字符串啊,于是这里用到了另外一个vector,它的元素类型是pair<>,记录的就是每个字符串在strtab中的“指针”,排序(sort)的时候传入sort的也是pair<>的“指针”。这时候不能用STL排序算法中自带的operator<了,需要针对pair<>类型编写专门的比较方法。struct strtab_cmp完成了这个任务,不过它却是一个结构体(struct),为什么能够给sort传入一个结构体临时对象呢?注意struct strtab_cmp的成员函数operator(),即括号操作符。这就使得一个对象能够像函数那样去工作,完全可以以假乱真。毕竟sort需要的不过是一个函数指针而已,我们给了它一个strtab_cmp对象的地址,它毫不怀疑的把它当作函数指针使用,假如在sort内部那个函数指针是_func,那么当它调用_func()的时候,strtab_cmp对象立马反应过来,调用自己的括号操作符方法,完成了相同的任务。

strtab_print(cout)与strtab_cmp的道理是一样的,也是函数对象。

此外,为了使得输出的字符串在同一行,每找一个回车字符时,就将它修改成了空格,*next = ' '做的就是这件事情。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值