使用结构体及结构体函数比较有理数的程序出现段错误问题咨询
排查你的有理数比较C程序段错误问题
咱先梳理下你代码里的问题,导致段错误的核心原因和解决方法都给你列出来:
1. 最直接的原因:传递了无效的结构体指针
你的equal和reduce函数都需要接收struct rational*类型的指针参数,但在main函数里,你只定义了几个int变量,完全没创建任何struct rational类型的实例,也没给指针分配合法内存。要是你后续直接把未初始化的野指针(或者空指针)传给这两个函数,函数内部去访问rational_number1->numerator这类成员时,肯定会访问非法内存,直接触发段错误。
另外你输入部分还有个小问题:把分子存在q、分母存在p,但后续没把这些值赋值给结构体变量,等于白输入了,这也是逻辑上的漏洞。
修复方案(附完整可运行代码)
方案一:用栈上的结构体变量(简单省心,推荐新手用)
直接在main里创建两个struct rational的实例,把输入的值赋值给它们的成员,再把变量的地址传给函数就行:
#include<stdio.h> #include<stdbool.h> struct rational{ int numerator; // 分子 int denominator; // 分母 }; bool equal(struct rational *rational_number1,struct rational *rational_number2); void reduce(struct rational *inputrational,struct rational *outputrational); // 补充最大公约数函数,用于约分 int gcd(int a, int b) { while(b != 0) { int temp = b; b = a % b; a = temp; } return a; } // 实现约分函数 void reduce(struct rational *inputrational,struct rational *outputrational) { // 先判断分母是否为0,避免非法运算 if(inputrational->denominator == 0) { fprintf(stderr, "Error: 分母不能为0!\n"); return; } int common_div = gcd(inputrational->numerator, inputrational->denominator); // 处理符号,保证分母为正,避免-3/-4和3/4被误判为不等 if(inputrational->denominator < 0) { outputrational->numerator = -inputrational->numerator / common_div; outputrational->denominator = -inputrational->denominator / common_div; } else { outputrational->numerator = inputrational->numerator / common_div; outputrational->denominator = inputrational->denominator / common_div; } } // 实现相等判断函数 bool equal(struct rational *rational_number1,struct rational *rational_number2) { struct rational r1_reduced, r2_reduced; // 先约分再比较 reduce(rational_number1, &r1_reduced); reduce(rational_number2, &r2_reduced); return (r1_reduced.numerator == r2_reduced.numerator) && (r1_reduced.denominator == r2_reduced.denominator); } int main() { struct rational num1, num2; // 在栈上创建结构体实例 // 输入第一个有理数 printf("请输入第一个有理数的信息:\n"); printf("分子:"); scanf("%d", &num1.numerator); printf("分母:"); // 循环判断,拒绝输入0作为分母 while(1) { scanf("%d", &num1.denominator); if(num1.denominator == 0) { printf("分母不能为0!请重新输入:"); } else { break; } } // 输入第二个有理数 printf("\n请输入第二个有理数的信息:\n"); printf("分子:"); scanf("%d", &num2.numerator); printf("分母:"); while(1) { scanf("%d", &num2.denominator); if(num2.denominator == 0) { printf("分母不能为0!请重新输入:"); } else { break; } } // 调用判断函数并输出结果 if(equal(&num1, &num2)) { printf("\n这两个有理数相等!\n"); } else { printf("\n这两个有理数不相等!\n"); } return 0; }
方案二:用动态内存分配(适合需要灵活管理内存的场景)
如果需要动态创建结构体,可以用malloc分配内存,记得用完后用free释放:
// 在main函数里替换结构体创建的部分 struct rational *num1 = malloc(sizeof(struct rational)); struct rational *num2 = malloc(sizeof(struct rational)); // 检查内存分配是否成功 if(num1 == NULL || num2 == NULL) { fprintf(stderr, "内存分配失败!\n"); return 1; } // 后续输入赋值给num1->numerator、num1->denominator等 // 使用完后一定要释放内存 free(num1); free(num2);
额外提醒
- 一定要处理分母为0的情况,不然不仅逻辑错,还可能触发除零异常
- 约分的时候要统一符号,保证分母为正,避免符号问题导致的判断错误
- 传递指针给函数前,务必确保指针指向合法有效的内存(要么是栈上变量的地址,要么是堆上分配的内存)
内容的提问来源于stack exchange,提问作者rocking
相关产品推荐
相关产品推荐

