You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用结构体及结构体函数比较有理数的程序出现段错误问题咨询

排查你的有理数比较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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:27:12