用递归函数创建一个C程序来检查给定的整数是否是4的倍数,为什么我的实现失败了?

jhkqcmku  于 2023-04-19  发布在  其他
关注(0)|答案(2)|浏览(114)

我尝试创建这个程序:
函数power 4接受一个命令行参数“n”,它将其转换为整数(因为在命令行中,所有内容都被格式化为字符串),并且它会做一些事情来说明“n”是否是4的倍数。
输出格式必须相同:“4*i=n”,需要使用递归。
因为我需要使用递归,我不能使用模数“%”操作数;我已经使用了减法,递归的基本情况必须是当“n == 0”,或者当“n〈0”(或者当n = 1,如果它不是4的倍数),归纳步骤是“power 4(n - 4,i + 1)”。
我使用strtol函数将“n”转换为整数,并使用 *p检查strtol是否成功。
我是这样做的:

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

void power4(int n, int i) {
    if (n < 0 || n == 1) {
        printf("!p4"); 
        return; 
    } 
    if (n == 0) {
        printf("4*");
        printf("%d", i);
        printf("=%d", n); 
    }
    power4(n - 4, i + 1); 

}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        return 1; 
    }
    int ptr = 0; 
    int* p = &ptr; 
    int c = strtol(argv[1], p, 10); 
    if (p == NULL) {
        return 1; 
    }
    power4(c, 1); 
    return 0; 
}

我试过这个程序“n = 12”(即4的倍数),但它说它不是倍数,为什么它不能正常工作?
编辑:这是我的解决方案的更新版本:

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

void power4(int n, int i) {
    if (n < 0 || n == 1) {
        printf("!p4"); 
        return; 
    } 
    if (n == 0) {
        printf("4*");
        printf("%d", i);
        printf("=%d", n); 
        return; 
    }
    power4(n - 4, i + 1); 
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        return 1; 
    }
    int c = strtol(argv[1], NULL, 10); 
    power4(c, 1); 
    return 0; 
}

编辑:我已经改变了递归算法,但现在的错误是argc!=2总是true,因此它总是返回1。

#include <stdio.h>
#include <stdlib.h>
void power4(int n1, int i, int n2) {
    // base case
    if (n1 % 4 != 0 && n1 != 1) {
        printf("!p4"); 
        return; 
}
    if (n1 == 1) {
        printf("4^%d=%d", i, n2); 
        return; 
    }
    // inductive step
    power4(n1 / 4, i + 1, n2); 
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        return 1; 
    }
    int c = strtol(argv[1], NULL, 10); 
    power4(c, 0, c); 
    return 0; 
}
3okqufwl

3okqufwl1#

对于初学者来说,函数不应该输出任何消息,而是函数的调用者发出消息。
因此,函数的返回类型不应该是void
使用你的方法,函数将不能正确地处理有符号整数。因此,将函数参数声明为有符号整数类型int是没有意义的。并且函数应该只有一个参数。
该函数可以通过下面的演示程序中所示的以下方式定义。

#include <stdio.h>

unsigned int power4( unsigned int n )
{
    if (n == 0)
    {
        return 0;
    }
    else if (n < 4)
    {
        return -1;
    }
    else
    {
        unsigned int i = power4( n - 4 );
        return i == -1 ? -1 : 1 + i;
    }
}

int main( void )
{
    for ( unsigned int n = 0; n < 13; n++ )
    {
        unsigned int i = power4( n );

        if (i != -1)
        {
            printf( "4*%d = %d\n", i, n );
        }
        else
        {
            puts( "!p4" );
        }
    }
}

程序输出为

4*0 = 0
!p4
!p4
!p4
4*1 = 4
!p4
!p4
!p4
4*2 = 8
!p4
!p4
!p4
4*3 = 12

要转换命令行参数,可以使用标准函数strtoul,例如

unsigned int n = ( unsigned int )strtoul( argv[1], NULL, 10 );

如果要检查转换是否成功,则需要提供strtoul调用的第二个参数,该参数不等于NULL,并在调用后检查其值和errno的值。

r7s23pms

r7s23pms2#

你需要在n==0的时候捕获case,然后返回。你在输入-4的时候前进了一个太深的层次:

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

int power4(int n, int i) {
  if (n == 0)
    return 1;
  if (n < 0 || n == 1)
    return -1;
  return power4(n - 4, i + 1);
}

int main(int argc, char* argv[]) {
  int c;
  if (argc != 2)
    return 1;
  c = strtol(&argv[1][2],NULL, 10);
  if (errno == EINVAL || errno == ERANGE)
    return 1;
  if(c != 0)
    c = power4(c, 1);
  printf("%sMultiple of Four\n",c > 0?"":"Not a ");
  return 0;
}

相关问题