尾递归:Return 语句放置

Tail Recursion: Return Statement placement

虽然我的程序按照我想要的方式工作,但我很好奇为什么当我做了一个小的改变来去掉一行时我会得到不同的结果?

#include <stdio.h>
int sum(int i);
int main(void)
{
    int num;
    printf("Enter an integer greater than zero, (q to quit): ");
    while (scanf("%d",&num)==1)
    {
        //Checks if the entered integer is positive
        if (num<0)
            printf("Please enter a positive integer.\n");
        //Prints out the sum of the entered integer
        else
            printf("Sum(%d) = %d\n",num, sum(num));
        printf("Enter an integer greater than zero, (q to quit): ");
    }
    printf("Bye.");
    return 0;
}
//Calculates the sum of inputted value
int sum(int i)
{
    int answer;
    //Runs until the sum is added in reverse order
    if (i>0)
        answer=i+(sum(i-1));
    else
        answer=0;
    return answer;
}

在函数中,我将 "return answer;" 移动到 "answer=0" 所在的位置,它产生的结果与我预期的不同。有人知道为什么吗? 输入 1、4、5 和 7 会产生一个看似随机的数字。 1-10 中的任何其他数字都会产生正确答案。 谢谢你的帮助! 干杯, 威尔.

因为该函数不会 return 否则,这是未定义的行为。删掉一行并不一定会提升代码,不要因为代码少就删掉,其实我会这样写

int
sum(int input)
{
    int answer;
    if (input > 0) {
        answer = input + (sum(input - 1));
    } else {
        answer = 0;
    }
    return answer;
}

更多“代码”,但也更具可读性。我说“code”是因为它们的编译完全相同,但这个版本更容易阅读。

虽然我同意 Iharob 可读性是首要考虑因素,但仍然存在您尝试将此函数转换为尾递归的问题。

现在,如果您只是这样做:

int sum(int i)
{
    return i > 0 ? i + sum(i-1) : 0;
}

那么该函数是一个没有未定义行为的递归单行函数,但它不是尾递归。它不是尾递归的,因为递归函数调用不是函数中的最后一个操作,那个角色是加法。您不只是 return 递归调用的结果。

幸运的是,使这个尾递归很容易:

int sum(int i, int n)
{
    return i > 0 ? sum(i - 1, i + n) : n;
}

通过引入一个保存总和的新变量,您可以简单地return递归调用的结果。


如果你必须坚持一个单一的参数原型,你总是可以sum一个真正的尾递归函数的包装器:

int sum_impl(int i, int n)
{
    return i > 0 ? sum_impl(i - 1, i + n) : n;
}

int sum(int i)
{
    return sum_impl(i, 0);
}