c-在执行递归时,为什么最后一个数字被加了两次



在执行递归以查找前25个自然数的和时,为了查看添加的所有数字,我使用printf来查看,但它只显示25一次。

#include <stdio.h>

int sum_of_numbers(int);
int main(){
int sum, num1 = 1;
sum = sum_of_numbers(num1);
printf("nSum of first 25 natural numbers is %d.", sum);
}
int sum_of_numbers(int n1){
int sum;
if(n1 <= 25){
printf("%d ", n1);
sum = n1 + sum_of_numbers(++n1);
}
else
return 0;
}

让我们从这个函数开始:

int sum_of_numbers(int n1){
int sum;
if(n1 <= 25){
printf("%d ", n1);
sum = n1 + sum_of_numbers(++n1);
}
else
return 0;
}

暂时忽略这是一个递归函数这一事实。事实上,让我们用一个非递归的调用来代替递归调用:

int sum_of_numbers(int n1){
int sum;
if(n1 <= 25){
printf("%d ", n1);
sum = n1 + some_other_mystery_function(++n1);
}
else
return 0;
}

根据经验,当你第一次学习递归时,假装递归调用是对不同函数的通常是有帮助的。递归中的许多错误实际上是函数调用和返回中更简单的错误,它们会被忽略,因为您过于关注递归部分。

有了这个改变,你注意到这个功能有什么不寻常的地方吗?具体来说,如果传入小于或等于25的值n1,会返回什么值?在这种情况下,函数到达末尾时不会返回任何内容。具体来说,我们输入if语句,执行printf,调用some_other_mystery_function,然后从函数的末尾掉下来,什么都不返回。在C中,这是未定义的行为,返回的值本质上取决于编译器、操作系统和行星排列的突发奇想。

这导致了一般的可转移技能1:确保在编写递归函数时始终返回值。大多数函数都是这样,尤其是在递归的情况下。

这里还有其他一些可疑的东西。请注意,您将sum变量设置为某个值,但sum是一个局部变量,以后在函数中从未引用过。这应该会引发一些警钟——为什么我们在不读取局部变量的情况下设置它?

我想你的意思更像这样:

int sum_of_numbers(int n1){
if(n1 <= 25){
printf("%d ", n1);
return n1 + some_other_mystery_function(++n1);
}
else
return 0;
}

这总是返回一个值,并且从不向未读取的局部变量写入。

不过,这里还有另一个问题。看看这行:

return n1 + some_other_mystery_function(++n1);

在这里,您在表达式的某个点读取n1,在另一个点写入++n1。这是一件坏事,因为没有办法保证n1的第一次使用是否评估为"0";在评估CCD_ 11之前CCD_;或";CCD_ 12在CCD_"再次注意,这个语句是一个return语句,所以在执行完这行之后,就再也没有机会触摸n1了。我想你的意思是这样的?

return n1 + some_other_mystery_function(n1 + 1);

这更清楚地意味着";将n1 + 1作为参数传递给函数">

这导致了通用的可转移技能编号2:避免使用+++=-=等作为函数的参数。在某些情况下,这将正确工作,但在许多情况下,它会引入错误。相反,通过value + 1value + 137value - 271

最后,可转移技能编号3-编译器可以警告您所有这些问题。现在,当你启动警告设置时,大多数编译器都会警告你写入未读取的局部变量,或者从函数末尾掉下来而不返回任何内容,或者增加表达式中其他地方使用的变量。我建议启用这些设置,因为这可能会让你知道这里有些地方不太对劲。你可能不明白这些警告是怎么回事,没关系!如果发生这种情况,请随时在网站上的另一个问题中发布您的代码和警告消息,其他人可以查看。

两个问题。

如果n小于或等于25,则永远不会显式返回。这会导致奇怪的事情发生。

此外,在这种情况下,当您可以只使用n1 + 1时,没有理由使用++n1,因为您传递的是值。++运算符可能很有用,但前缀++并没有起到您可能认为的作用。

首先,您没有从递归函数的主体返回值,尽管我的GNU g++编译器没有抱怨它并做这项工作,但您不能假设它工作。

其次,增加变量++n1,这也增加了调用语句中n1的值。所以你实际要做的是加2到26,而不是1到25。您可以使用n1 + 1,不需要更改变量,也不应该更改。您可以将代码更改为以下内容来解决问题:

#include <stdio.h>

int sum_of_numbers(int);
int main() {
int sum, num1 = 1;
sum = sum_of_numbers(num1);
printf("nSum of first 25 natural numbers is %d.", sum);
}
int sum_of_numbers(int n1){
int sum;
if (n1 <= 25) {
printf("%d ", n1);
sum = n1 + sum_of_numbers(n1 + 1);
return sum;
}
else {
return 0;
}
}

最新更新