我正在写一个用于练习的阶乘函数.在Main上,我声明变量并按如下方式调用它:

int main(){
    unsigned long n = 0;
    scanf("%lu", &n);
    unsigned long result = factorial(n);
    printf("%lu \n", result);
    return 0;
}

它起作用了,并给出了我想要的结果.但我觉得它看起来有点糟糕,所以我这样重构了它:

int main(){
    unsigned long n = 0;
    printf("%lu \n", factorial(scanf("%lu", &n)));
}

不管怎么说,结果都是1.为什么?以下是阶乘函数,以防万一:

unsigned long factorial(unsigned long n){
    if(n == 1){
        return n;
    }
    else if(n <= 0){
        printf("No factorial for negative numbers");
    }
    else{
        return (n * factorial(n - 1));
    }
    return 0;
}

我在Python上做了同样的练习,并以同样的方式格式化了函数调用,结果它工作了,所以我很困惑为什么C不接受它.它不是先调用函数的函数(scanf,然后factorial,然后是printf)吗?

推荐答案

  1. 失踪包括.

  2. 正如@ RetiredNinja所说,问题是scanf()返回成功时匹配的参数数量,而不是n的值(如果出错,它会返回n). 我在这里添加了错误判断以进一步澄清这一点.

  3. factorial():n是无符号的,所以n <= 0最好写成n == 0!n.

  4. factorial():return 0;语句的放置是奇怪的,因为它只为 case n <= 0执行.

  5. factorial():return n并没有错,但由于它是一个基本情况,所以使用return 1更清楚.

  6. (未修复)由于溢出,我的系统上的factorial()(带有sizeof(long) == 8)返回n > 65的0.或许再加一张上限支票?

  7. (不固定)factorial():更喜欢迭代实现,因为C不能保证尾部调用优化. 如果输入足够大,在我的系统上,在n = 250k到275k之间的某个地方,程序将粉碎堆栈并(希望)segfault. (默认)堆栈大小是特定于操作系统的.

  8. 比起main(),我更喜欢签名main(void).在实践中,他们将做同样的事情,但只有前者在标准中定义(与main(int, char *[])一起).

  9. (不固定)你可能只想在n > 0的情况下调用factorial(),或者像你的初始实现一样将值存储在变量中,这样你就可以忽略n == 0的输出,而不是:

    0
    No factorial for zero
    0
    
#include <stdio.h>

unsigned long factorial(unsigned long n) {
    if(!n) {
        printf("No factorial for zero\n");
        return 0;
    }
    if(n == 1)
        return 1;
    return n * factorial(n - 1);
}

int main(void) {
    unsigned long n;
    if(scanf("%lu", &n) != 1) {
        printf("scanf failed\n");
        return 1;
    }
    printf("%lu\n", factorial(n));
}

示例运行:

6
720 

C++相关问答推荐

我可以动态分配具有空类型函数的矩阵吗?

C:gcc返回多个错误定义,但msvc—不""'

通过MQTT/蚊子发送大文件—限制在4MB

getchar读css + z还是返回css?

如何在C宏中确定Windows主目录?

Malloc(sizeof(char[Length]))是否不正确?

创建一个fork导致fget无限地重新读取文件

如何跨平台处理UTF-16字符串?

正确的TCP/IP数据包 struct

双指针指向常量双指针的指针类型赋值不兼容

每次除以或乘以整数都会得到0.0000

通过k&;r语法的c声明无效

链表删除 node 错误

使用Open62541向OPCUA服务器发送读请求时内存泄漏

无法理解 fgets 输出

'printf("%s", user_input)' 危险吗?

函数的typedef是标准 C 语法吗?它与函数指针的typedef有何不同?

在C中定义函数指针?

SSE 向量与 Epsilon 的比较

C 中类型说明符的顺序重要吗?