自定义一个简单的迭代器(line_iterator)
来源:互联网 发布:集成指挥平台大数据 编辑:程序博客网 时间:2024/05/21 10:06
STL是容器、迭代器、算法三位一体的好东西,使用STL编写的程序看起来非常简洁。比如从cin输入若干字符串,每一字符串占一行,然后将这些字符串按字典序排序并输出到cout中,相关的代码如下所示:
/* 迭代器的使用 * created: btwsmile * date: 2011-12-17 * */#include<iostream>#include<vector>#include<string>#include<iterator>#include<algorithm>using namespace std;int main(){ vector<string> v; string temp; while(getline(cin,temp)) { v.push_back(temp); } sort(v.begin(),v.end()); copy(v.begin(),v.end(),ostream_iterator<string>(cout," ")); system("pause"); return 0;}
包含的头文件非常:
主函数中用到cin/cout以及getline,因此必须包含iostream;
主函数中用到vector<string>,因此必须包含vector和string;
主函数中用到ostream_iterator,因此必须包含iterator;
主函数还调用了sort和copy函数,因此必须包含algorithm。
除了iostream外,其它头文件都是STL头文件。vector和string是容器,iterator是迭代器,algorithm是算法。
编译运行此程序,结果如下所示:
youaretheappleofmyeye^Zapple are eye my of the you 请按任意键继续. . .
如果想倒过来排,只要在把sort(v.begin(),v.end())改写成sort(v.begin(),sort.end(),greater<string>())即可。
现在我们提出一个稍微高一点的要求,上面的程序不是将cout包装到迭代器里了吗,能不能将cin也包装到迭代器里面呢?当然是可以,我们定义一个类来实现:
/* line_iterator.h * created: btwsmile * date: 2011-12-17 * */class line_iterator{ istream* in; string line; bool is_valid; void read() { if(*in) getline(*in,line); is_valid = (*in) ? true : false; }public: typedef input_iterator_tag iterator_category; typedef string value_type; typedef ptrdiff_t difference_type; typedef const string* pointer; typedef const string& reference; reference operator*() { return line; } pointer operator->() { return &line; } line_iterator():in(&cin),is_valid(false) { } line_iterator(istream& s):in(&s) { read(); } line_iterator operator++() { read(); return *this; } line_iterator operator++(int) { line_iterator temp = *this; read(); return temp; } bool operator==(const line_iterator& rhs) { if(in == rhs.in && is_valid == rhs.is_valid) return true; if(is_valid == false && rhs.is_valid == false) return true; return false; } bool operator!= (const line_iterator& rhs) { return !(*this == rhs); }};
代码比较长,看似很复杂,在解释它之前先看看它怎么使用:
/* 迭代器的使用 版本2 * created: btwsmile * date: 2011-12-17 * */#include<iostream>#include<vector>#include<string>#include<iterator>#include<algorithm>using namespace std;#include"line_iterator.h"int main(){ line_iterator iter(cin); line_iterator end_of_file; vector<string> v(iter,end_of_file); sort(v.begin(),v.end()); copy(v.begin(),v.end(),ostream_iterator<string>(cout," ")); system("pause"); return 0;}
毫不意外,运行这个新版的程序,结果与旧程序是一样的。比较起来,新版的程序中看不到明显地输入语句。显然这是我们自定义的line_iterator带来的妙处。
新程序中的输入是在哪里实现的呢?请看vector<string> v(iter,end_of_file),用迭代器区间来构造vector,在这个构造方法内部隐含的一定有一个while循环,就是将字符串从iter开始到end_of_file一个接一个的拷贝到vector v中。必然的,它将调用line_iterator的operator++、operator!=等操作符方法。而end_of_file看起来不跟任何变量相关,但是回头看line_iterator的无参构造方法,你会发现它实际上还是跟标准输入cin挂上了钩。所以,在判断有没有到达输入的尾端时,将比较is_valid标记。
line_iterator定义内部的其它成员同样不可或缺,那些看似没用的typedef,实际在于vector以及sort、copy等联合工作的时候被频繁使用到。想要搞懂它们就需要对iterator进行更深一步的学习了。
- 自定义一个简单的迭代器(line_iterator)
- line_iterator
- 一个简单的自定义Collection
- 自定义一个简单的ScrollView
- 一个简单的自定义popupwindow
- 自定义一个简单的PopupWindow
- 一个简单的自定义TopBar
- 一个简单的自定义SwitchButton
- 一个简单的自定义控件
- 一个简单的自定义Dialog
- 一个简单的自定义DialogFragment
- 自定义一个简单的viewpagerIndicator
- 一个简单的自定义Dialog
- 一个简单的自定义Compass
- 自定义一个简单的imageload
- 一个简单的自定义ClassLoader的实现
- 一个简单的自定义ClassLoader的实现
- 一个简单的MenuStrip的自定义Renderer
- 到底什么情况该选择开发Web App?
- 根据表名得到除主键外的所有字段用来Update
- 浅谈用户体验的那些事情
- serial driver 2
- 根据表名得到除主键外的所有字段及字段类型
- 自定义一个简单的迭代器(line_iterator)
- dm9000 driver 1
- 根据表名生成有关SelectAll的存储过程
- dm9000 driver 2
- 如何寻找客户的需求
- 根据表名生成有关Update的存储过程
- 关于#define
- 获取SQL所有数据库名、所有表名、所有字段名、表字段长度
- 0/1背包问题