在初始条件为假时进入循环

时间:2011-10-06 17:00:41

标签: c++ recursion

我很困惑,不知道这里发生了什么:

#include <iostream>

void recur();
int i = 1;

int main() {
  recur();
}

void recur() {
  std::cout << "\nvalue of i above while loop : " << i << std::endl;
  while(i++ < 10) {
    recur();
    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
  }
}

这是输出:

value of i above while loop : 1

value of i above while loop : 2

value of i above while loop : 3

value of i above while loop : 4

value of i above while loop : 5

value of i above while loop : 6

value of i above while loop : 7

value of i above while loop : 8

value of i above while loop : 9

value of i above while loop : 10
statement just after the recursive call to tester and here the value of i is :11
statement just after the recursive call to tester and here the value of i is :12
statement just after the recursive call to tester and here the value of i is :13
statement just after the recursive call to tester and here the value of i is :14
statement just after the recursive call to tester and here the value of i is :15
statement just after the recursive call to tester and here the value of i is :16
statement just after the recursive call to tester and here the value of i is :17
statement just after the recursive call to tester and here the value of i is :18
statement just after the recursive call to tester and here the value of i is :19

每次调用函数recur时,它都会打印它的第一行,当值变为等于10时,循环中断。当我们离开循环时,while循环中的语句如何工作/打印?有人可以解释发生了什么吗?

让我验证 我在想什么?在每次调用函数recur时,控件都会返回函数定义的开头。例如:

while(i++<10) { 
   recur();
   //...
}
  |
  |
 \ /
void recur() { // here i is 2
    while(i++ < 10) {
        recur();
        //....
    }
} 
  |
  |
 \ /
void recur() { // here i is 3
    while(i++ < 10) {
        recur();
        //....
    }
} 

这是通话的方式吗?

6 个答案:

答案 0 :(得分:3)

变量i继续递增,因为while条件必须再次执行以确保它为false,导致i递增,即使每次调用recur()都超过10。

如果您将i的增量放在条件之外,则结果将更符合您的预期。例如:

while (i < 10) {
    i++;
    // Do rest.
}

但是使用当前的代码,每次测试条件时,即使条件为假,我也会继续递增。

答案 1 :(得分:2)

你以一种相当奇怪的方式混合递归和迭代。

第一个recur()调用第二个,调用第三个,依此类推。每个增量i。当第十个嵌套函数调用将i递增到10时,它返回。然后第9个函数调用打印消息,再次递增i,退出循环并返回到第8个函数。

没有一个函数多次绕过while循环 - 因为当嵌套的recur()调用返回时,i总是至少为10。

你为什么要这样做?

答案 2 :(得分:1)

不,当recur()返回时,您仍然在while语句中,您必须在std::cout之后执行recur()

void recur() {
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    while(i++ < 10) {
        recur();
        // <b>each time `recur()` returns, its return to here</b>
        std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
      }
}

好的,我画了一个图表

while(i++<10) { 
    recur();
    //...       <---------return to here--
}                                        |
                                         |
void recur() { // here i is 2            |
    while(i++ < 10) {                    |
        recur();                         |
        //....  <-----return to here---- |
    }                                  | |
    return; ------------------------------
}                                      |
                                       |
void recur() { // here i is 3          |
    while(i++ < 10) {                  |
        recur();                       |
        //....                         |
    }                                  |
    return; ----------------------------
} 

答案 3 :(得分:1)

以下是您的计划流程:

value   function    stack depth
-----   --------    -----------
i = 1   recur()     0
i = 1   print i     1
i = 1   i++         1
i = 2   recur()     1
i = 2   print i     2
i = 2   i++         2
i = 3   recur()     2
i = 3   print i     3
i = 3   i++         3
i = 4   recur()     3
i = 4   print i     4
i = 4   i++         4
i = 5   recur()     4
i = 5   print i     5
i = 5   i++         5
i = 6   recur()     5
i = 6   print i     6
i = 6   i++         6
i = 7   recur()     6
i = 7   print i     7
i = 7   i++         7
i = 8   recur()     7
i = 8   print i     8
i = 8   i++         8
i = 9   recur()     8
i = 9   print i     9
i = 9   i++         9
i = 10  recur()     9
i = 10  print i     10
i = 10  i++         10
i = 11  return      10
i = 11  print i     9
i = 11  i++         9
i = 12  return      9
i = 12  print i     8
i = 12  i++         8
i = 13  return      8
i = 13  print i     7
i = 13  i++         7
i = 14  return      7
i = 14  print i     6
i = 14  i++         6
i = 15  return      6
i = 15  print i     5
i = 15  i++         5
i = 16  return      5
i = 16  print i     4
i = 16  i++         4
i = 17  return      4
i = 17  print i     3
i = 17  i++         3
i = 18  return      3
i = 18  print i     2
i = 18  i++         2
i = 19  return      2
i = 19  print i     1
i = 19  i++         1
i = 20  return      1
i = 20

答案 4 :(得分:0)

在最里面的recur调用中条件变为false后,它会跳出循环并正确返回。它返回到recur的第二个最里面的调用,它显示i的值,然后返回到while循环的开头以再次检查条件。条件为(i++ < 10),因此它第二次递增i(现在为11),看到它大于10,并返回第三个最里面的调用。第三个最里面的增量检查(i++ < 10),要求它在知道打开它的循环之前递增i(到12)。等

基本上,每次通话都有一个循环。它一次只能打破一个。你想要:

void recur() {
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    i++; //here, outside the loop
    while(i < 10) {
        recur();
        std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
    }
}

[编辑]
是的,当一个函数调用自身时,计算机将再次调用该函数,当内部函数返回时,它将返回到外部函数中的确切位置。基本上,就像任何其他函数调用一样。

答案 5 :(得分:0)

我认为解释它的最好方法是展示我如何重写函数以使其更具可读性。以下每个片段的输出都与原始代码相同(假设首次调用recur()时i == 1)

首先,让我们将postincrement运算符排除在条件之外,因为我觉得它很混乱。此代码是等效的:

void recur() {
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    while(i < 10){
        i++;
        recur();
        std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;

    }
    i++;
}

注意最后有一个i ++。这是因为在原始代码中,我将在(i ++&lt; 10)条件下递增,即使条件不计算为true并且不进入循环。

接下来,您可以通过反复内联代码来“重新排列”重复。每当它的值发生变化时,我也会追踪i的值。

void recur() {
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    while(i < 10){
        i++; //i == 2
        std::cout << "\nvalue of i above while loop : " << i << std::endl;
        while(i < 10){
            i++; //i == 3
            std::cout << "\nvalue of i above while loop : " << i << std::endl;
            while(i < 10){
                i++; //i ==4
                std::cout << "\nvalue of i above while loop : " << i << std::endl;
                while(i < 10){
                    i++; //i == 5
                    std::cout << "\nvalue of i above while loop : " << i << std::endl;
                    while(i < 10){
                        i++; //i == 6
                        std::cout << "\nvalue of i above while loop : " << i << std::endl;
                        while(i < 10){
                            i++; //i == 7
                            std::cout << "\nvalue of i above while loop : " << i << std::endl;
                            while(i < 10){
                                i++; //i == 8
                                std::cout << "\nvalue of i above while loop : " << i << std::endl;
                                while(i < 10){
                                    i++; //i == 9
                                    std::cout << "\nvalue of i above while loop : " << i << std::endl;
                                    while(i < 10){
                                        i++; //i == 10
                                        std::cout << "\nvalue of i above while loop : " << i << std::endl;
                                        while(i < 10){//this doesn't evaluate to true since i == 10
                                            //we stop unrolling here because the interior of this loop won't be executed anyway
                                        }
                                        i++; // i == 11
                                        std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
                                    }
                                    i++;
                                    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
                                }
                                i++;
                                std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
                            }
                            i++;
                            std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
                        }
                        i++;
                        std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
                    }
                    i++;
                    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
                }
                i++;
                std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
            }
            i++;
            std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
        }
        i++;
        std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
    }
    i++;
}

注意每个while循环只执行一次 - 当第一次完成任何单个while循环时,i大于10,因此不会再次输入循环。考虑到这一点,我们可以完全摆脱这些问题,并为自己省去一些缩进。

void recur() {
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    i++; //i == 2
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    i++; //i == 3
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    i++; //i ==4
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    i++; //i == 5
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    i++; //i == 6
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    i++; //i == 7
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    i++; //i == 8
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    i++; //i == 9
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    i++; //i == 10
    std::cout << "\nvalue of i above while loop : " << i << std::endl;
    i++; // i == 11
    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
    i++;
    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
    i++;
    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
    i++;
    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
    i++;
    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
    i++;
    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
    i++;
    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
    i++;
    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
    i++;
    std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
    i++;
}

也可以优化其中一些重复的陈述......

void recur(){
    for(int x = 0; x < 10; x++){
        std::cout << "\nvalue of i above while loop : " << i << std::endl;
        i++;
    }
    for(int x = 0; x < 9; x++){
        std::cout << "statement just after the recursive call to tester and here the value of i is :" << i << std::endl;
        i++;
    }
}

现在很明显看到第一个语句为i = 1到10打印自己,第二个从i = 11到19打印。