【问题标题】:Segmentation fault in odd/even recursive function奇/偶递归函数中的分段错误
【发布时间】:2022-01-12 14:46:58
【问题描述】:

我编写了以下代码,以便使用递归函数查找数字是偶数还是奇数。

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

int posneg(int n){ 
    
    if (posneg(n-1)%2 == 0){
        return 1;
    }
    else {
        return 0;
    }
}

main () { 
    int num;
    
    do{ 
        printf("Provide a number"); 
        scanf("%d",&num); 
    } while (num <= 0);
    if (posneg(num) == 1)
        printf("The number is even");
    else 
        printf("The number is odd");

}

代码编译成功,但出现分段错误。

任何想法是什么原因?

【问题讨论】:

  • 你的 posneg 函数的递归什么时候停止?
  • "posneg" 是偶数还是奇数?令人着迷。
  • 当数字是奇数或偶数时
  • 整数总是奇数或偶数,所以你是说posneg函数永远不会递归?
  • 尝试手动跟踪逻辑。你会看到它永远不会停止。您需要在递归调用之前测试n

标签: c recursion segmentation-fault


【解决方案1】:

您遇到分段错误,因为您的代码导致堆栈溢出

int posneg(int n){ 
        
    if (posneg(n-1)%2 == 0){
        return 1;
    }
    else {
        return 0;
    }
}

每次递归函数调用自身时,都会将新的激活记录添加到包含新调用参数的堆栈中。

这个递归函数永远不会评估基本情况,因为它必须确定它是否可以被 2 整除,为了做到这一点,你必须调用函数来评估它。重复此操作,直到您的程序用完堆栈。

【讨论】:

    【解决方案2】:

    确定一个数是偶数还是奇数的函数不适合递归实现,除非目标是说明递归通常不是理想的解决方案。

    递归解决方案必须有一个基本情况,否则它将继续调用自己,直到系统耗尽资源并且程序崩溃。

    如何递归判断一个数是偶数还是奇数?一种方法是从数字中逐渐加或减 2,直到我们得到 -1、0 或 1(我们的基本情况):

    // Let's say a return value of '1' means odd and '0' means even
    int evenodd (int n)
    {
        if(-1 == n || 1 == n) // base case: n is odd
        {
            return 1;
        }
        else if(0 == n) // base case: n is even
        {
            return 0;
        }
        else
        {
            return evenodd(n > 0 ? n-2 : n+2);
        }
    }
    

    【讨论】:

    • @ikegami 当 n == INT_MIN 时会导致 UB。坏主意。
    • 0___________,好的,if (n &gt; 0) n = -n; 然后 :) 但这感觉很奇怪。
    【解决方案3】:

    对于根据 C 标准的初学者,不带参数的函数 main 应声明为

    int main( void )
    

    你不能省略函数的返回类型。

    其次,如果您期望一个非负数,则将变量 num 声明为具有 int 类型没有什么意义。该变量应声明为具有unsigned int 类型。

    由于函数内部的 if 语句,函数会产生无限递归

    int posneg(int n){ 
        
        if (posneg(n-1)%2 == 0){
            return 1;
        }
        else {
            return 0;
        }
    }
    

    使用您定义函数的方法,它可以如下面的演示程序所示,例如以下方式

    #include <stdio.h>
    
    int posneg( unsigned int n )
    { 
        return ( n == 0 ) || ( ( 1 + posneg( n - 1 ) ) % 2 );
    }
    
    int main( void )
    {
        while ( 1 )
        {
            printf( "Provide a non-negative number (0 - exit): " );
            
            unsigned int n;
            
            if ( scanf( "%u", &n ) != 1 || n == 0 ) break;
            
            if ( posneg( n ))
            {
                printf( "The number %u is even.\n", n );
            }           
            else
            {
                printf( "The number %u is odd.\n", n );
            }
                
        }
    }
    

    程序输出可能看起来像

    Provide a non-negative number (0 - exit): 1
    The number 1 is odd.
    Provide a non-negative number (0 - exit): 2
    The number 2 is even.
    Provide a non-negative number (0 - exit): 3
    The number 3 is odd.
    Provide a non-negative number (0 - exit): 4
    The number 4 is even.
    Provide a non-negative number (0 - exit): 5
    The number 5 is odd.
    Provide a non-negative number (0 - exit): 6
    The number 6 is even.
    Provide a non-negative number (0 - exit): 7
    The number 7 is odd.
    Provide a non-negative number (0 - exit): 8
    The number 8 is even.
    Provide a non-negative number (0 - exit): 9
    The number 9 is odd.
    Provide a non-negative number (0 - exit): 0
    

    【讨论】:

      猜你喜欢
      • 2017-02-02
      • 2013-03-05
      • 2014-11-05
      • 2015-04-10
      • 2019-11-16
      • 2017-12-25
      • 1970-01-01
      相关资源
      最近更新 更多