跟踪在 C++ 中调用递归函数的次数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16705934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Keep track of how many times a recursive function has been called in C++
提问by bachkoi32
I am trying to work on a program that has a function whose parameter is an vector of string. I want to use recursive on that function but everytime the function is called, I want to change the parameter to say for example
我正在尝试处理一个程序,该程序具有一个参数是字符串向量的函数。我想在该函数上使用递归,但每次调用该函数时,我都想更改参数以说例如
fun(stringArray[i])
where i is the number of time the function has been called.
其中 i 是函数被调用的次数。
So in simpler way something like following. But I need to keep track of how many times the function fun has been executed.
所以以更简单的方式类似于以下内容。但是我需要跟踪函数 fun 执行了多少次。
void fun(){
cout<<hi;
if(x!=10)
fun()
}
int main(){
fun();
}
In this one let's say I want to print it out just 10 times, so want to have a varible that increments, and when reaches 10, it stops. So in general what can I do to keep track of it? I tried using global variables but they don't seem to work with functions. Any suggestions?
在这个假设中,我只想打印 10 次,所以想要一个递增的变量,当达到 10 时,它会停止。那么总的来说,我可以做些什么来跟踪它?我尝试使用全局变量,但它们似乎不适用于函数。有什么建议?
回答by Nicola Pezzotti
I've seen quite a mess here so I decided to clear the things out.
我看到这里很乱,所以我决定把事情清理干净。
Solution 0: Static Variable
解决方案 0:静态变量
Consider the code proposed with a small modification
考虑通过小修改提出的代码
#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();
}
resulting in this output:
导致此输出:
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
As you can see, using static variables could lead to some unexpected behaviour.
如您所见,使用静态变量可能会导致一些意外行为。
This is a one shot functionthat will cause you quite some headaches in the future. Furthermore, the usage of static variables leads to an unreadable code that is error prone
这是一个一次性功能,将来会让您头疼。此外,静态变量的使用会导致代码不可读,容易出错
Just don't do it!
不要这样做!
Solution 1: Variable passed by value
方案一:变量传值
Consider this code:
考虑这个代码:
#include <iostream>
using namespace std;
void fun(int i){
cout<<i<<endl;
if(i!=3) {
i++;
fun(i);
fun(i);
}
}
int main(){
fun(0);
}
This is the output:
这是输出:
0
1
2
3
3
2
3
3
1
2
3
3
2
3
3
As you can see the output is not the number of times the function is called
如您所见,输出不是函数被调用的次数
Solution 2: Variable passed by reference
解决方案 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();
}
will print
将打印
Entry point
1
2
3
4
5
6
7
8
9
10
This approach will work also with some more exotic recursive pattern like this one
这种方法也适用于一些更奇特的递归模式,比如这个
#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();
}
Output:
输出:
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
回答by Sanish
Add a static
variable as counter.
添加一个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
variables are initialized only once and the value will be retained across function calls. See this link http://en.wikipedia.org/wiki/Static_variable
static
变量仅初始化一次,并且该值将在函数调用中保留。请参阅此链接http://en.wikipedia.org/wiki/Static_variable
回答by Nicola Pezzotti
void fun(int& x){
if(x>=10)
return;
... Do something
++x;
fun(x);
}
You should use a reference to an external variable
您应该使用对外部变量的引用
If you pass the counter by value you can't make multiple calls in the same function
如果按值传递计数器,则不能在同一个函数中进行多次调用
回答by Nicola Pezzotti
use static variable inside the recursive function. static int i =0; and in the beginning of the function, say i++.
在递归函数中使用静态变量。静态 int i = 0; 在函数的开头,说 i++。
every time the function is called, this i will be incremented. and if the value of i become 10, you can terminate.
每次调用该函数时,这个 i 都会增加。如果 i 的值变为 10,则可以终止。
回答by theshadow124
if you need to make it recursive...
如果你需要让它递归......
void fun(int i){
cout<<hi;
if(i!=10) {
i++;
fun(i);
}
}
int main(){
fun(0);
}
Hope that helps?
希望有帮助吗?
回答by Divya Gupta
I know I am really late to answer this question. But anyway, the approach, followed by me involves pointersconcept in #1, and pass by referenceconcept in #2. I have tested this solution for Towers of Hanoiproblem, and it will work nearly for all kind of recursive functions in my opinion.
我知道我回答这个问题真的晚了。但无论如何,我遵循的方法涉及#1 中的指针概念,以及#2 中的通过引用概念。我已经针对河内塔问题测试了这个解决方案,在我看来,它几乎适用于所有类型的递归函数。
Actually, code written in first approach is originally in C, but it will work in C++ too, for obvious reasons.
实际上,用第一种方法编写的代码最初是用 C 编写的,但出于显而易见的原因,它也可以用 C++ 编写。
Approach #1: Using pointers in C.
方法#1:在 C 中使用指针。
Lets say we denote the recursive function by rf()
假设我们用rf()表示递归函数
- An integer variable, lets say, with name invocationshas to be created, to be passed to the recursive function along with other arguments (if present). It must be created in main() or the calling function. Initialize it to 0.
Then, in the recursive function parameter list, add another parameter with type integer pointer, and in the calling function, pass to recursive function, the value of this parameter as the address of the variable invocationsdefined in this calling function. e.g.
void main(){ int invocations=0; rf(n,&invocations); // address of variable 'invocations' is passed here }
Then, in the declaration part of recursive function, where you have added an extra parameter for counting function invocations, and declared its type as int pointer, in the first line of function body itself, increment the value pointed by this integer pointer by 1 in the following way,
void rf(int n, int* invocations){ (*invocations)++; /* rest of the function logic goes here */ }
- 可以说,必须创建一个带有名称调用的整数变量,然后将其与其他参数(如果存在)一起传递给递归函数。它必须在 main() 或调用函数中创建。将其初始化为 0。
然后,在递归函数参数列表中,再添加一个整数指针类型的参数,在调用函数中,传递给递归函数,这个参数的值作为这个调用函数中定义的变量调用的地址。例如
void main(){ int invocations=0; rf(n,&invocations); // address of variable 'invocations' is passed here }
然后,在递归函数的声明部分,添加了一个额外的参数用于计数函数调用,并将其类型声明为int指针,在函数体本身的第一行中,将此整数指针指向的值增加1以下方式,
void rf(int n, int* invocations){ (*invocations)++; /* rest of the function logic goes here */ }
Notice here that I have put the de-referencing operator (*), asterisk, inside parentheses in order to tell compiler to evaluate it first, as if I don't do that, the increment operator on its right will be evaluated first in absence of the parentheses (since * and ++ have same precedence, and if present in the same expression, they will be evaluated from right to left)
请注意,我将取消引用运算符 (*)、星号放在括号内,以便告诉编译器首先对其进行评估,就好像我不这样做一样,它右侧的增量运算符将在不存在的情况下首先进行评估括号(因为 * 和 ++ 具有相同的优先级,如果出现在同一个表达式中,它们将从右到左计算)
Next, print the value of invocation variable, after all the recursive function calls are over in the calling function, here in our case, inside main(). Like this,
void main(){ ...... int invocations=0; ....... rf(n, &invocations); printf("\nNumber of invocations of rf()=%d\n", invocations); }
接下来,打印调用变量的值,在调用函数中所有递归函数调用结束后,在我们的例子中,在 main() 中。像这样,
void main(){ ...... int invocations=0; ....... rf(n, &invocations); printf("\nNumber of invocations of rf()=%d\n", invocations); }
Approach #2: Using pass by reference in C++
方法#2:在 C++ 中使用按引用传递
All the above steps are same, only changes involved are in following ways,
上面所有步骤都是一样的,只是涉及到的变化有以下几种,
Change the parameter type in rf() declaration from
int*
toint&
. Likevoid rf(int n, int* invocations)
tovoid rf(int n, int& invocations)
Change the rf() call statement, pass the variable value, not its address.(remove simply the &), like
rf(n, &invocations);
torf(n, invocations);
Change the incrementation statement of invocationsvariable from
(*invocations)++;
to simplyinvocations++
inside rf() body.
将 rf() 声明中的参数类型从
int*
更改为int&
。像void rf(int n, int* invocations)
到void rf(int n, int& invocations)
更改 rf() 调用语句,传递变量值,而不是其地址。(简单地和删除),如
rf(n, &invocations);
以rf(n, invocations);
将调用变量的增量语句从rf() 主体内部更改
(*invocations)++;
为简单invocations++
。
That's all. Both the solutions will produce same effect. Both of them works in my case. Tell me if the solution is unclear at any step or if it fails to work in your case.
就这样。两种解决方案都会产生相同的效果。它们都适用于我的情况。告诉我解决方案是否在任何步骤不清楚,或者它是否在您的情况下不起作用。