【问题标题】:C - Print list of Prime Numbers (recursion)C - 打印素数列表(递归)
【发布时间】:2016-05-07 20:20:17
【问题描述】:

我在学校的 C 编程作业中遇到了一些问题。我应该返回给定范围内的素数,并且必须使用递归来完成。

到目前为止我得到的代码是这样的:

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

int primeNumberList(int n, int m, int z);

int main() {
    int n1 = 0,
        n2 = 10,
        d = 2;

    printf("n1 = %d | n2 = %d | d = %d\n\n", n1, n2, d);    
    printf("Prime Numbers between %d and %d are: \n", n1, n2);

    primeNumberList(n1, n2, d);

    printf("\n\n");

    return 0;
}

int primeNumberList(int n, int m, int z) {
    int notPrime = 0;

    if (n <= 1) {
        primeNumberList(n + 1, m, z);
    } else
    if (n < m) {
        if (z <= n / 2) {
            if (n % z == 0) {
                notPrime = 1;
                z = 2;
            } else {
                primeNumberList(n, m, z + 1);
            }
        }
        if (notPrime == 0) {
            printf("%d ", n);
        }
        primeNumberList(n + 1, m, z);
    }
}

当我运行它时会发生什么,在它遍历所有数字达到限制之后(在函数中它是mn2main))它不会中断递归,但是不知何故设法从n 中减去数字,并开始打印其他一些不是素数的数字。 当我在调试中运行它时,它似乎在最后循环,但没有什么可以循环...我尝试添加一个return 0;,甚至是一个带有一些文本的printf,但它完全忽略了它。

谁能看到我在这里做错了什么?为什么n &lt; m时不停止?

【问题讨论】:

  • primeNumberList 没有return 声明?
  • if(z
  • @Ben:使用“return 0;”或“返回;”也不起作用,如果这是您的意思,或者您的意思是应该将值分配给返回的变量?
  • @Christoffer 您有可能为每个调用进行两次递归调用,我认为这就是让您感到困惑的原因。目前,在primeNumberList 的开头添加if(n == m-1) exit(1); 是一种可行的hacky 解决方案。
  • @River:非常感谢,它应该可以正常工作!您提到这是一个 hacky 解决方案,这是否意味着您通常不应该使用它,或者仅仅是因为我的编码有点混乱,因此它比替代方案更容易使用?

标签: c if-statement recursion primes


【解决方案1】:

我发现了你的问题。每次调用 primeNumberList 时,您都有可能进行两次递归调用。

primeNumberList(n, m, z+1);(最里面的else 下方)返回后,您仍然可以继续打印素数并调用primeNumberList(n+1, m, z);。这不是你想要的行为,你想在这个内部 else 调用之后直接返回。

因此,只需在每次调用 primeNumberList 之前添加一个 returnprimeNumberList(x); 变为 return primeNumberList(x);)并在此函数末尾添加一个 return 0(最后一个 return 只是为了编译器很高兴)。

【讨论】:

    【解决方案2】:

    尝试更简洁的方法:定义一个单独的 isPrime 函数并调用它。

    http://www.cquestions.com/2011/08/prime-number-program-in-c-using.html

    int isPrime(int num,int i){
    
      if(i==1){
          return 1;
      }else{
         if(num%i==0)
           return 0;
         else
           isPrime(num,i-1);
      }
    }
    

    【讨论】:

      【解决方案3】:

      您的递归函数退出条件不正确。

      当您调用递归函数时,它会先结束,然后再结束。当我逐步运行您的代码时,由于它正在缠绕 ,我得到了完整的素数列表,如下所示:

      然后继续打印以下数字:

      你的问题为什么当 n
      因为当您开始展开时,存储在值n 中的值也会通过已调用的递归迭代开始展开,从而允许执行流留在循环中。 此外,如果 unwind 将执行流程带到通过 printf("%d ", n); 语句的点,则将打印出 n 的值,无论它在该 unwind 迭代中是什么。

      不打印n == 10 之外的任何内容的一种方法是创建一个旁路变量,并将其用作打印标准:

      static done = 0;  
      

      如果您不想在展开时再打印任何值,请将done 设置为 1。

      这是一个修改后的函数:

      int primeNumberList(int n, int m, int z) {
          int notPrime = 0;
          static done = 0;//add a bypass variable, init to zero
      
          if (n <= 1) {
              primeNumberList(n + 1, m, z);
          } 
          else
          {
              if(n == 10)
                  {
                      done = 1; //at this point all primes (except 1) are printed
                                //so set done to 1
                  }
              if (n < m) 
              {
                  if (z <= n / 2) 
                  {
                      if (n % z == 0) 
                      {
                          notPrime = 1;
                          z = 2;
                      } 
                      else 
                      {
                          primeNumberList(n, m, z + 1);
                      }
                  }
                  if ((notPrime == 0) && (!done)) //test done before printing
                  {
                      printf("%d ", n);
                  }
                  primeNumberList(n + 1, m, z);
              }
          }
          return 0;//add this return statement
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-31
        • 1970-01-01
        • 2021-06-06
        • 2022-01-02
        • 2017-06-22
        • 2013-12-12
        • 1970-01-01
        • 2022-01-18
        相关资源
        最近更新 更多