如何编写全编译器兼容的C程序?正约数计数程序跨编译器异常求助
C语言正约数计算程序的异常问题排查与修复
我写了一个计算正整数正约数个数的C程序,在本地CodeBlocks的GCC编译器里运行正常,但学校的在线编译器中,部分输入会输出接近22000的数值(比如22019、21873)。比如输入10,本地输出正确的4,在线编译器却输出22019。而且把if语句的条件从if (n<0)改成if (0>n)后,异常数值还会变化(比如从22019变成其他22开头的数)。
原代码如下:
#include <stdio.h> #include <stdlib.h> int main() { int c, n, res = 0; int i = 1; scanf("%d", &n); if (0>n) printf("Wrong Input"); else { while (n>=i) { res = n%i; if (res == 0) { c++; i++; } else { i++; } } printf("%d", c); } return 0; }
问题原因
- 核心问题:变量
c未初始化。C语言中局部变量默认不会自动初始化为0,会保留内存中的随机垃圾值。本地编译器的栈内存刚好让c初始为0,所以结果正确;但在线编译器的内存布局不同,c的初始值是随机的大数值,导致最终输出异常。 - 修改
if条件后异常数值变化,是因为代码结构的细微调整改变了栈上变量的内存位置,c的初始垃圾值也跟着改变,和条件写法本身无关。
修复后的代码
只需要给c显式初始化为0即可:
#include <stdio.h> #include <stdlib.h> int main() { int c = 0, n, res = 0; // 初始化c为0 int i = 1; scanf("%d", &n); if (n < 0) // 写法更直观,不影响逻辑 printf("Wrong Input"); else { while (n >= i) { res = n % i; if (res == 0) { c++; i++; } else { i++; } } printf("%d", c); } return 0; }
额外优化建议
可以优化循环逻辑,只遍历到sqrt(n),大幅减少计算量,同时处理0的特殊情况:
#include <stdio.h> #include <math.h> int main() { int c = 0, n; scanf("%d", &n); if (n < 0) { printf("Wrong Input"); return 0; } if (n == 0) { // 0没有正约数 printf("0"); return 0; } int sqrt_n = sqrt(n); for (int i = 1; i <= sqrt_n; i++) { if (n % i == 0) { if (i == n / i) { c++; // 平方数的约数只算一次 } else { c += 2; // 非平方数对应一对约数 } } } printf("%d", c); return 0; }
内容的提问来源于stack exchange,提问作者Petra Kotrona
相关产品推荐
相关产品推荐

