跟踪在C ++中调用递归函数的次数

时间:2013-05-23 04:58:04

标签: c++ recursion global-variables

我正在尝试使用一个函数,该函数的参数是一个字符串向量。我想在该函数上使用递归,但每次调用该函数时,我都想更改参数,例如

fun(stringArray[i]) 

其中i是调用函数的时间。

所以更简单的方式就像跟随。但我需要跟踪功能乐趣的执行次数。

void fun(){
    cout<<hi;
    if(x!=10)
    fun()
}

int main(){

    fun();
}

在这一个中,我想说我想要将它打印10次,所以想要增加一个变量,当它达到10时,它会停止。所以一般来说我该怎么做才能跟踪呢?我尝试使用全局变量,但它们似乎不适用于函数。有什么建议吗?

6 个答案:

答案 0 :(得分:10)

我在这里看到了很多混乱所以我决定清除这些事情。

解决方案0:静态变量

考虑使用轻微修改提出的代码

#include<iostream>
using namespace std;

void fun()
{
    static int count=1;
    count++;
    cout << "fun() is called " << count << " times" << endl;
    if(count<=10)
    {
            fun();
    }
}

int main()
{
    cout << "first call" << endl;
    fun();
    cout << "second call" << endl;
    fun();
    cout << "third call" << endl;
    fun();
}

这是输出:

first call
fun() is called 2 times
fun() is called 3 times
fun() is called 4 times
fun() is called 5 times
fun() is called 6 times
fun() is called 7 times
fun() is called 8 times
fun() is called 9 times
fun() is called 10 times
fun() is called 11 times
second call
fun() is called 12 times
third call
fun() is called 13 times

正如您所看到的,静态变量的使用可能会导致一些可怕的错误。

在这里你有一个一次性功能,将来会给你带来很大的痛苦。

此外,静态变量的使用会导致难以理解的代码容易出错

就是不要这样做!

解决方案1:按值传递的变量

考虑以下代码:

#include <iostream>
using namespace std;

void fun(int i){
    cout<<i<<endl;
    if(i!=3) {
        i++;
        fun(i);
        fun(i);
    }
}

int main(){
    fun(0);
}

这是输出:

0
1
2
3
3
2
3
3
1
2
3
3
2
3
3

如您所见,输出不是调用函数的次数

解决方案2:通过引用传递的变量

#include <iostream>
using namespace std;

void fun(int& x){
    if(x>=10)
        return;
    ++x;
    cout << x << endl;
    fun(x);
}

void funEntry(){
    int x = 0;
    cout << "Entry point" << endl;
    fun(x);
}

int main(){
    funEntry();
    funEntry();
}

将打印

Entry point
1
2
3
4
5
6
7
8
9
10

这种方法也适用于一些更具异国情调的递归模式,比如这个

#include <iostream>
using namespace std;

void fun(int i, int& x){
    if(i>=4)
        return;
    ++x;
    cout << i << " " << x << endl;
    fun(i+1,x);
    fun(i+2,x);
}

void funEntry(){
    int x = 0;
    cout << "Entry point" << endl;
    fun(0,x);
}

int main(){
    funEntry();
    funEntry();
}

输出:

Entry point
0 1
1 2
2 3
3 4
3 5
2 6
3 7
Entry point
0 1
1 2
2 3
3 4
3 5
2 6
3 7

答案 1 :(得分:4)

添加static变量作为计数器。

#include<iostream>
using namespace std;

void fun()
{
    static int count=1;
    count++;
    cout << "fun() is called " << count << " times" << endl;
    if(count<=10)
    {
            fun();
    }
}

int main()
{
    fun();
}

static个变量只初始化一次,并且值将在函数调用中保留。请参阅此链接http://en.wikipedia.org/wiki/Static_variable

答案 2 :(得分:1)

void fun(int& x){
    if(x>=10)
        return;
    ... Do something
    ++x;
    fun(x);
}

您应该使用对外部变量的引用

如果您按值传递计数器,则无法在同一函数中进行多次调用

答案 3 :(得分:0)

在递归函数中使用静态变量。 static int i = 0; 在函数的开头,比如说i ++。

每次调用该函数时,此i都会递增。如果i的值变为10,则可以终止。

答案 4 :(得分:0)

如果你需要让它递归......

void fun(int i){

    cout<<hi;
    if(i!=10) {
        i++;
        fun(i);
    }
}

int main(){

    fun(0);
}

希望有帮助吗?

答案 5 :(得分:0)

我知道我回答这个问题真的很晚。但是无论如何,我所遵循的方法是在#1中涉及 pointers 概念,在#2中涉及引用引用概念。我已经针对河内塔楼问题测试了该解决方案,在我看来,它几乎可以用于所有递归函数。

实际上,用第一种方法编写的代码最初是用C语言编写的,但出于明显的原因,它也可以在C ++中工作。

方法1 :在C中使用指针

让我们说我们用 rf()

表示递归函数
  1. 必须创建一个名称为 invocations 的整数变量,并将其与其他参数(如果存在)一起传递给递归函数。它必须在main()或调用函数中创建。将其初始化为0。
  2. 然后,在递归函数参数列表中,添加另一个类型为整数指针的参数,并在调用函数中传递给递归函数,将此参数的值作为地址此调用函数中定义的变量 invocations 。 例如

    void main(){
    
    int invocations=0;
    
    rf(n,&invocations); // address of variable 'invocations' is passed here
    }
    
  3. 然后,在递归函数的声明部分中,您添加了一个额外的参数来计算函数调用,并将其类型声明为int指针, 在函数主体本身的第一行中,按以下方式将此整数指针指向的值加1,

    void rf(int n, int* invocations){
    
    (*invocations)++;
    
    /* rest of the function logic goes here */
    
    }
    

这里请注意,我已经在括号内放置了反引用运算符(*),星号,以便告诉编译器首先对其进行评估,就好像我不这样做一样,其右侧的增量运算符也会被评估首先没有括号(因为*和++具有相同的优先级,并且如果存在于相同的表达式中,则它们将从右到左求值)

  1. 接下来,在调用函数中所有递归函数调用都结束之后,在此例中,在main()内部,打印调用变量的值。 像这样

    void main(){
    ......
    int invocations=0;
    .......
    rf(n, &invocations);
    printf("\nNumber of invocations of rf()=%d\n", invocations);
    }
    

方法#2 :在C ++中使用按引用传递

以上所有步骤都是相同的,仅涉及以下方面的更改,

  1. 将rf()声明中的参数类型从int*更改为int&。喜欢 void rf(int n, int* invocations)void rf(int n, int& invocations)

  2. 更改rf()调用语句,传递变量值,而不是其地址。(仅删除&),例如从rf(n, &invocations);rf(n, invocations); < / p>

  3. 调用变量的增量语句从(*invocations)++;更改为rf()主体内的invocations++

仅此而已。两种解决方案都会产生相同的效果。在我的情况下,它们都可以工作。 告诉我解决方案在任何步骤上是否不清楚,或者在您的情况下是否行不通。