如何递归使用函数?

use*_*809 6 c recursion sum

我有一个程序,提示用户输入最多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
Run Code Online (Sandbox Code Playgroud)

Plo*_*rzz 1

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

话虽这么说,您的结构方式sum_divisors非常接近它应该的样子,接受它缺少递归调用,因此只需要进行一些更改即可使其递归。

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

      if( a <= 1 )
          return;
    
    Run Code Online (Sandbox Code Playgroud)

    以便函数知道何时停止

  • 正如我之前所说,for 循环可以更改为更通用的循环,没有幻数。我们可以替换102a-1a省略除数计数,而不是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
}
Run Code Online (Sandbox Code Playgroud)

和你最初的没有太大区别