8

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

fun(stringArray[i]) 

其中 i 是函数被调用的次数。

因此,以更简单的方式,如下所示。但我需要跟踪函数 fun 执行了多少次。

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

int main(){

    fun();
}

在这个例子中,假设我只想打印 10 次,所以想要一个递增的变量,当达到 10 时,它会停止。那么总的来说,我能做些什么来跟踪它呢?我尝试使用全局变量,但它们似乎不适用于函数。有什么建议么?

4

6 回答 6

12

我看到这里很乱,所以我决定把这些东西清理干净。

解决方案 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
于 2013-05-23T06:44:50.623 回答
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

于 2013-05-23T05:07:26.377 回答
1
void fun(int& x){
    if(x>=10)
        return;
    ... Do something
    ++x;
    fun(x);
}

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

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

于 2013-05-23T05:09:04.917 回答
0

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

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

于 2013-05-23T05:03:20.267 回答
0

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

void fun(int i){

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

int main(){

    fun(0);
}

希望有帮助吗?

于 2013-05-23T05:07:15.937 回答
0

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

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

方法 #1:在 C 中使用指针

假设我们用rf()表示递归函数

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

    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);

  3. 将invocations变量的增量语句从更改(*invocations)++;为仅invocations++在 rf() 主体内。

就这样。两种解决方案都会产生相同的效果。它们都适用于我的情况。告诉我解决方案是否在任何步骤都不清楚,或者它在您的情况下是否无效。

于 2020-05-19T18:16:16.487 回答