C++抽象编程——递归策略(3)——foreach语句的简单实现

来源:互联网 发布:中国造不出圆珠笔知乎 编辑:程序博客网 时间:2024/06/05 07:12

我想,foreach循环大家都不会陌生,但凡熟悉一点高级的语言的人都是很熟悉的。它遍历每一个元素,并且对它进行处理,方便了很多。我第一次接触foreach的时候,是我在大一的时候学习的C#接触的。很可惜,在java跟C#中都有的这样的方便工具,但是C++是没有的(虽然在C++11中添加了for_each语句,详细用法看: C++抽象编程——STL实战(2)——查找与修改,但是我感觉用法上没那么方便)。本来我没打算写这个的,但是我下一篇的文章中要用到这个原理。所以这里我们先提一下foreach语句。

遍历与操作

通过遍历每一个元素并且能对它进行操作,是任何集合(STL)类的基本操作。此外,如果收集类的包装设计良好,客户端应该能够使用相同的策略来执行该操作,无论它们是循环遍历vector还是set中的所有元素,map中的所有key或value。标准模板库(STL)提供了一个强大的机制,称为迭代器,(迭代器的介绍:C++抽象编程——STL实战(1)——迭代器详解”)用于执行此操作。 不幸的是,理解这些标准迭代器取决于对C ++的低级细节的高度熟悉,最引人注目的是指针的概念。我们真正需要的一些方法是表达以下伪代码建议的算法思想:

For each element in a particular collection {    Process that element}

即遍历集合中的每一个元素,然后对其进行操作。

其他语言的foreach语法

我们现在来看看C#中的 foreach 语句的语法 :

foreach (type variable in collection) {    body of the loop.}

比如我这里有一个string类的set,即set< string > ss.有下面的代码:

foreach (string word in ss) {    if (word.length() == 2) {    cout << word << endl;   }}

这个操作的意思是,遍历ss集合,并将遍历的内容存储在word中,一旦发现集合中有长度等于2的单词,就将它输出。

迭代的顺序

当您使用foreach模式时,了解处理各个独立的值的顺序有时是有帮助。在这里没有特定的的规则。通常是基于效率的考虑。我们已经看到的类对于值的顺序有以下的特点:

  • 在处理一些类似与vector类的foreach时,过程类似与:
for (int i = 0; i < vec.size(); i++) {    code to process vec[i]}
  • 在处理二维的时候,foreach类似于:
for (int row = 0; row < grid.numRows(); row++) {    for (int col = 0; col < grid.numCols(); col++) {    code to process grid[row][col]    }}

行下标出现在外部循环中的这个顺序称为行主顺序(row-major order)。

  • 在处理STL的时候,foreach类似于
for (it = ss.begin(); it != ss.end(); it++){    code to process cletion;}

其中,it为迭代器。

C++中foreach的简单实现

我们既然知道了foreach的原理,那么能不能利用C++的强大去实现呢?我试了一下,很开心,我做到了。下面就说说过程吧。
先看我们上面的foreach语句:

set<string> ss;foreach (string word in ss) { //遍历    if (word.length() == 2) { //操作    cout << word << endl;   }}

我们可以写成这样:

set<string> ss;string word;  //因为set的类型为string类型set<string>::iterator it; //创建迭代器for (it = ss.begin(); it != ss.end(); it++){ // 遍历        word = (*it); //将每一个元素存入对应的类型中,注意是这个集合中每一个独立的元素        if (word.length() == 2) { //执行操作        cout << word << endl;     }}

然后我们就可以根据这一个思路来写一个foreach函数了,比如这样的函数原型:

void foreach(string str, set<string> ss);

当然这只是设想而已,我就不写了,下面的生成排列数的连接就用实际的例子来证明这样的正确性:生成排列数

0 0
原创粉丝点击