【问题标题】:While performing recursion why the last number is getting added twice? [closed]在执行递归时,为什么最后一个数字被加了两次? [关闭]
【发布时间】:2021-08-02 04:23:18
【问题描述】:

在执行递归以查找前 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;
}

【问题讨论】:

  • sum_of_numbers 从不返回 if 分支中的任何内容。
  • here。阅读this

标签: c recursion


【解决方案1】:

让我们从这个函数开始:

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 的第一次使用评估为“n1 在评估++n1 之前的值”还是“n1 之后的新值”我们做了++n1。”再一次,注意这个语句是一个return 语句,所以在这行执行之后,就再也没有机会再次接触n1。我想你的意思是这样的?

return n1 + some_other_mystery_function(n1 + 1);

这更清楚地意味着“将n1 + 1 作为参数传递给函数。”

这导致通用的、可转移的技能 2:避免使用 +++=-= 等作为函数的参数。在某些情况下,这将正常工作,但在许多情况下,它会引入错误。而是传递value + 1value + 137value - 271 等。

最后,可转移技能 3 - 编译器可以警告您所有这些问题。如今,大多数编译器在您提高警告设置时,会警告您写入未读取的局部变量,或者在函数末尾不返回任何内容,或者增加表达式中其他地方使用的变量。我建议启用这些设置,因为这可能会提示您这里有些地方不太对劲。您可能不了解警告的全部内容,这很好!如果发生这种情况,请随时在网站上的单独问题中发布您的代码和警告消息,其他人可以查看它。

【讨论】:

    【解决方案2】:

    两个问题。

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

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

    【讨论】:

      【解决方案3】:

      首先,虽然我的 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;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-08
        • 2020-02-23
        • 1970-01-01
        • 2021-08-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多