【问题标题】:How to use a function recursively?如何递归使用函数?
【发布时间】:2015-10-31 02:00:29
【问题描述】:

我有一个程序提示用户输入最多 10 位数字。然后,该程序使用一个函数返回输入的每个数字的除数之和减去自身并显示它,直到该数字等于 1 或 0。我的问题是该函数在 45 的除数相加后停止。我在这里尝试使用递归,因为该函数将被调用 'n' 次,直到每个等于 0 或 1。是什么让递归在这种情况下如此有用,我如何在这里应用它?关于这个函数的调用方式,我有什么遗漏吗?有人可以帮我吗?

例如,

如果用户输入:25 -4 6 45(然后按回车键)

程序应该输出:

25 1 0

-4 0 0

6 6

45 33 15 9 4 3 1 0 0

6 是一个完美数的示例,并且会重复,因此如果出现一个完美数,它应该停止对除数求和。当总和等于 0 时应该打印一次然后停止。 -4 也超出范围,因此它也应该打印 0。必须大于 1。

#include<stdio.h>
#include<stdlib.h>

  int main(void)
  {

    //Fields
    int i=0, j=0, k=0, l=0, num = 0, x = 0, count = 0, total = 0, z = 0;
    signed int b[11] = {0};
    char discard;


    //Prompt message
    printf( "\n\nPlease enter your list of numbers: " );


    //This while loop scans until the enter button is pressed
    while(i < 11 && (scanf("%d%1[^\n]s", &b[i], &discard)) == 2)
    {
      ++count;
      i++;
    } 
    puts("");
    puts("");
    //Display Factors 

    while(k <= count)
    { 
      x=b[k];
      num = sum_divisors(x);
      printf("%d " , num);
      k++;  
      puts("");
    }


   }//End of main

    //function to sum the divisors together
    int sum_divisors(int a)
    {
      int total = 0;
      int z = 0;

      printf("%d ", a);

      if(a < 1)
      { 
         total = 0;
      }else
      {     
         if((a%1 == 0) && a !=1)
              total = total + 1;

         for(z=2; z<102; z++)
         {
           if((a%z == 0) && a != z)
           {
             total = total + z;
           }//if
         }//for
      }//end if/else statement
      //  printf("%d ", total); 
      return total;
    }//end function sum_divisors

【问题讨论】:

  • 您标记了greatest-common-divisor。您是否尝试递归地找到 10 个数字的最大公约数并将它们相加?

标签: c recursion sum


【解决方案1】:

首先,我只想提几件事情,第一是声明 a % 1 == 0 对于任何正整数 a 总是为真,因此它不应该在条件中使用,另一个是你应该尽量避免在sum_divisors的for循环中使用magic数字,比如102;有一个更自然、更通用的值可以用来替换102,我想使用这样的常数会导致更大的数字更难计算,而这些数字的除数大于 102。

话虽如此,您构建sum_divisors 的方式非常接近应有的方式,接受它缺少递归调用,因此只需进行一些更改即可使其递归。

  • 由于您只想打印除数的总和,我看不出有任何理由让sum_divisors 返回一个值(可能接受它重复出现的次数),所以void 的返回值似乎更合适。
  • 让我们摆脱 (a%1==0)&amp;&amp;(a!=1) 并将基本情况更改为。

      if( a <= 1 )
          return;
    

    让函数知道何时停止

  • 正如我之前所说,for 循环可以更改为更通用的循环,没有幻数。我们可以将102 替换为a-1,以省略将a 作为除数而不是a!=z
  • 检查 a 是否为完美数
  • 现在调用递归调用,sum_divisors( total );

另一件事是初始化总计,例如total = 1,因此我们不需要将a=1 视为基本情况的例外。

一切都说完了,这就是剩下的

void sum_divisors( int a ) 
{
    int total = 1;     // divisor sum of a
    int z;

    printf("%d ", a);  // print value

    if( a <= 1 )       // base case
        return;

    for( z = 2; z < a-1; ++z)  // z < a-1 as to not include a in total
    {    
        if( a%z == 0 )
        {
            total += z;
        }
    }   
    if( total == a )   // a is a perfect number so we're done
        return;

    sum_divisors( total ); // call sum_divisors recursively with a = total
}

和你最初的差别不大

【讨论】:

  • 这仍然没有产生正确的答案,但它解决了我关于递归的问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-12
  • 2018-09-03
  • 2023-03-23
  • 2012-11-12
  • 1970-01-01
  • 1970-01-01
  • 2015-03-09
相关资源
最近更新 更多