自定义一个简单的迭代器(line_iterator)

STL是容器、迭代器、算法三位一体的好东西,使用STL编写的程序看起来非常简洁。比如从cin输入若干字符串,每一字符串占一行,然后将这些字符串按字典序排序并输出到cout中,相关的代码如下所示:

 
  1. /* 迭代器的使用

  2. * created: btwsmile

  3. * date: 2011-12-17

  4. *

  5. */

  6. #include<iostream>

  7. #include<vector>

  8. #include<string>

  9. #include<iterator>

  10. #include<algorithm>

  11. using namespace std;

  12. int main()

  13. {

  14. vector<string> v;

  15. string temp;

  16. while(getline(cin,temp))

  17. {

  18. v.push_back(temp);

  19. }

  20. sort(v.begin(),v.end());

  21. copy(v.begin(),v.end(),ostream_iterator<string>(cout," "));

  22. system("pause");

  23. return 0;

  24. }

包含的头文件非常:

主函数中用到cin/cout以及getline,因此必须包含iostream;

主函数中用到vector<string>,因此必须包含vector和string;

主函数中用到ostream_iterator,因此必须包含iterator;

主函数还调用了sort和copy函数,因此必须包含algorithm。

除了iostream外,其它头文件都是STL头文件。vector和string是容器,iterator是迭代器,algorithm是算法。

编译运行此程序,结果如下所示:

 
  1. you

  2. are

  3. the

  4. apple

  5. of

  6. my

  7. eye

  8. ^Z

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

如果想倒过来排,只要在把sort(v.begin(),v.end())改写成sort(v.begin(),sort.end(),greater<string>())即可。

现在我们提出一个稍微高一点的要求,上面的程序不是将cout包装到迭代器里了吗,能不能将cin也包装到迭代器里面呢?当然是可以,我们定义一个类来实现:

 
  1. /* line_iterator.h

  2. * created: btwsmile

  3. * date: 2011-12-17

  4. *

  5. */

  6. class line_iterator

  7. {

  8. istream* in;

  9. string line;

  10. bool is_valid;

  11. void read()

  12. {

  13. if(*in)

  14. getline(*in,line);

  15. is_valid = (*in) ? true : false;

  16. }

  17.  
  18. public:

  19. typedef input_iterator_tag iterator_category;

  20. typedef string value_type;

  21. typedef ptrdiff_t difference_type;

  22. typedef const string* pointer;

  23. typedef const string& reference;

  24.  
  25. reference operator*()

  26. {

  27. return line;

  28. }

  29. pointer operator->()

  30. {

  31. return &line;

  32. }

  33. line_iterator():in(&cin),is_valid(false)

  34. {

  35. }

  36. line_iterator(istream& s):in(&s)

  37. {

  38. read();

  39. }

  40. line_iterator operator++()

  41. {

  42. read();

  43. return *this;

  44. }

  45. line_iterator operator++(int)

  46. {

  47. line_iterator temp = *this;

  48. read();

  49. return temp;

  50. }

  51. bool operator==(const line_iterator& rhs)

  52. {

  53. if(in == rhs.in && is_valid == rhs.is_valid)

  54. return true;

  55. if(is_valid == false && rhs.is_valid == false)

  56. return true;

  57. return false;

  58. }

  59. bool operator!= (const line_iterator& rhs)

  60. {

  61. return !(*this == rhs);

  62. }

  63. };

代码比较长,看似很复杂,在解释它之前先看看它怎么使用:

 
  1. /* 迭代器的使用 版本2

  2. * created: btwsmile

  3. * date: 2011-12-17

  4. *

  5. */

  6. #include<iostream>

  7. #include<vector>

  8. #include<string>

  9. #include<iterator>

  10. #include<algorithm>

  11. using namespace std;

  12. #include"line_iterator.h"

  13. int main()

  14. {

  15. line_iterator iter(cin);

  16. line_iterator end_of_file;

  17. vector<string> v(iter,end_of_file);

  18. sort(v.begin(),v.end());

  19. copy(v.begin(),v.end(),ostream_iterator<string>(cout," "));

  20. system("pause");

  21. return 0;

  22. }

毫不意外,运行这个新版的程序,结果与旧程序是一样的。比较起来,新版的程序中看不到明显地输入语句。显然这是我们自定义的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进行更深一步的学习了。

猜你喜欢

转载自blog.csdn.net/pql925/article/details/82767329