C语言打印反序杨辉三角报Floating point exception错误如何排查?
问题原因分析
1 触发Floating point exception的直接原因
该错误本质是整数除0错误(Linux下整数除0会统一抛出该信号,并非只有浮点数运算会触发),问题完全出在calculate函数中:
- 函数内
n、r、n_r三个局部变量未初始化,默认是内存随机垃圾值,阶乘计算后大概率得到0或者非法值,执行n / (r * n_r)时分母为0直接触发崩溃。 - 杨辉三角元素对应的组合数公式写错:正确公式为
C(Row-1, Col-1) = (Row-1)! / [(Col-1)! * (Row-Col)!],你的代码中分母第二项的阶乘上限写为Row-Col-2,完全不符合公式,也会导致分母计算错误。 - 阶乘计算的初始值必须为1,你未初始化变量,计算出的乘积完全无效。
2 其他逻辑问题
main函数未判断参数数量,用户运行时不传参数直接访问argv[1]会触发段错误。- 打印循环边界错误:
Row > 1的循环条件会少打印最顶部的行,Col < num的循环条件会导致每行少打最后一个元素。 - 缩进逻辑写在
Col循环内部,每打印一个元素就会缩进一次,最终格式完全混乱,应该放在每行元素打印之前执行。
修复后参考代码
#include <stdio.h> #include <stdlib.h> int calculate(int Col, int Row); int main(int argc, char *argv[]) { // 先判断入参数量 if (argc < 2) { printf("请传入行数作为运行参数\n"); return 1; } int num; int Row; int Col; char *pEnd; num = strtol(argv[1], &pEnd, 10); // 校验输入合法性 if (*pEnd != '\0' || num > 20 || num < 1) { printf("请输入1-20之间的正整数\n"); return 1; } for (Row = num; Row >= 1; Row--) { // 每行统一缩进,放在元素打印前 int indent = num - Row; for (int i = 0; i < indent; i++) { printf(" "); } // 每行有Row个元素 for (Col = 1; Col <= Row; Col++) { printf("%4d", calculate(Col, Row)); } printf("\n"); } return 0; } int calculate(int Col, int Row) { int n = 1; // 阶乘初始值必须为1 int r = 1; int n_r = 1; int i; // 计算(Row-1)! for (i = Row - 1; i > 1; i--) { n *= i; } // 计算(Col-1)! for (i = Col - 1; i > 1; i--) { r *= i; } // 计算(Row-Col)! for (i = Row - Col; i > 1; i--) { n_r *= i; } return n / (r * n_r); }
小提示:int类型最大值为2^31-1,行数超过13时阶乘会溢出,可把calculate函数内的变量替换为long long类型支持更大行数。
C程序单步调试方法(gcc+gdb为例)
- 编译时加
-g参数保留调试信息:gcc -g 你的代码文件名.c -o yanghui - 启动调试:
gdb ./yanghui - 常用调试命令:
run 传入的参数:运行程序,比如测试5行就输入run 5break 行号/函数名:设置断点,比如break calculate就在calculate函数入口打断点next:单步执行一行,不进入函数内部step:单步执行一行,遇到函数会进入内部print 变量名:查看变量当前值,比如print n可查看n的实时值continue:继续运行到下一个断点quit:退出调试
内容的提问来源于stack exchange,提问作者ConnorWilliams
相关产品推荐
相关产品推荐

