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

C语言大整数运算代码二次动态分配触发断点问题求助

C语言大整数运算代码内存错误修复

我是一名韩国学生,英语不太好,使用翻译器沟通。我想要编写C语言的大整数运算代码,现有代码如下,但在第二次动态分配(temp = (Node*)malloc(sizeof(Node));)时触发断点。更新Visual Studio 2019后曾正常运行,但在free(ch)处触发断点后,问题再次出现,恳请帮忙解决。

原代码:

#define <stdio.h>
#define <stdlib.h>
#define <string.h>

typedef struct _Node{

    struct _Node* head;
    struct _Node* tail;
    char ch;

} Node;

/* 此部分为分配Node*并接收存储值的代码 */

int getLargeInt(Node** head) {
    Node* temp = NULL;
    char ch;
    int len = 0;

    while (1) {
        ch = getc(stdin);

        if (ch == '\n') break;
        if (*head == NULL) {

            *head = (Node*)malloc(sizeof(Node));
            (*head)->head = NULL;
            (*head)->tail = NULL;

            (*head)->ch = &ch;
            len++;

        } else {

            temp = (Node*)malloc(sizeof(Node)); // 或任何第二次malloc

            (*head)->tail = temp;
            temp->head = *head;
            *head = temp;
            (*head)->tail = NULL;

            (*head)->ch = &ch;
            len++;
        }
    }
    return len;
}

/* 此为实现两个输入字符串(整数)相加的函数 */

void addLarge(Node* n1, Node* n2, int n1_len, int n2_len) {
    int i = 0;
    int res = 0;
    char* ch = (char*)malloc(sizeof(char) * ((n1_len > n2_len)? n1_len + 1 : n2_len + 1));

    for (i = 0; i < strlen(ch); i++) {
        if (i < n1_len)
            res += n1->ch - '0';
        if (i < n2_len)
            res += n2->ch - '0';
        if (n1 != NULL)
            n1 = n1->head;
        if (n2 != NULL)
            n2 = n2->head;

        ch[i] = res % 10 + '0';
        res /= 10;
    }

    for (i = 0; i < strlen(ch); i++) {
        printf("%d", ch[strlen(ch) - i - 1] - '0');
    }
    free(ch);

}

int main() {

    Node* temp = NULL;
    Node* num1 = NULL;
    Node* num2 = NULL;
    int i, j, len = 0;
    int n1_len = 0, n2_len = 0;
    char ch;
    char* res;

    printf("first integer >> ");
    n1_len = getLargeInt(&num1);

    printf("second integer >> ");
    n2_len = getLargeInt(&num2);

    printf("select arithmetic symbol >> ");
    ch = getc(stdin);

    switch (ch) {
    case '+':
        //addLarge(num1, num2, n1_len, n2_len);
        break;
    }



    while (num1 != NULL) {
        if (num1->tail != NULL)
            while (num1->tail != NULL)
                num1 = num1->tail;

        temp = num1;
        num1 = num1->head;
        free(temp);
    }

    while (num2 != NULL) {
        if (num2->tail != NULL)
            while (num2->tail != NULL)
                num2 = num2->tail;

        temp = num2;
        num2 = num2->head;
        free(temp);
    }

    return 0;
}

错误分析与修复要点

1. 头文件引入错误

原代码用#define引入头文件是完全错误的,C语言中必须用#include引入标准头文件:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

2. Node结构体成员赋值错误

Node中的ch是char类型,但原代码中赋值为&ch(局部变量的地址),类型不匹配会导致内存访问异常,应直接赋值字符值:

// 错误写法
(*head)->ch = &ch;
// 正确写法
(*head)->ch = ch;

3. 链表构建逻辑错误

原代码链表连接逻辑混乱,且存储的数字顺序与加法运算需求不符。修改为链表头部存储数字最低位,方便逐位相加:

int getLargeInt(Node** head) {
    Node* temp = NULL;
    Node* current = NULL;
    char ch;
    int len = 0;

    while (1) {
        ch = getc(stdin);
        if (ch == '\n') break;

        temp = (Node*)malloc(sizeof(Node));
        if (temp == NULL) {
            printf("内存分配失败\n");
            exit(1);
        }
        temp->ch = ch;
        temp->head = NULL; // 作为前向指针
        temp->tail = NULL; // 作为后向指针

        if (*head == NULL) {
            *head = temp;
            current = temp;
        } else {
            current->tail = temp;
            temp->head = current;
            current = temp;
        }
        len++;
    }
    // 反转链表,让头部指向数字最低位
    current = NULL;
    while (*head != NULL) {
        temp = (*head)->tail;
        (*head)->tail = current;
        current = *head;
        (*head)->head = temp;
        *head = temp;
    }
    *head = current;
    return len;
}

4. addLarge函数逻辑错误

  • 不能用strlen(ch)判断循环次数:malloc的内存未初始化,strlen会读取随机内存直到遇到'\0',导致循环次数错误,应直接使用max(n1_len, n2_len) + 1作为循环次数。
  • 访问节点成员前必须判断是否为NULL,避免空指针访问。
  • 需处理加法最后的进位。

修改后的addLarge函数:

void addLarge(Node* n1, Node* n2, int n1_len, int n2_len) {
    int max_len = (n1_len > n2_len) ? n1_len : n2_len;
    int i = 0;
    int res = 0;
    // 分配足够内存,+2用于处理进位和字符串结束符
    char* ch = (char*)malloc(sizeof(char) * (max_len + 2));
    if (ch == NULL) {
        printf("内存分配失败\n");
        return;
    }

    for (i = 0; i < max_len; i++) {
        if (n1 != NULL) {
            res += n1->ch - '0';
            n1 = n1->tail;
        }
        if (n2 != NULL) {
            res += n2->ch - '0';
            n2 = n2->tail;
        }

        ch[i] = res % 10 + '0';
        res /= 10;
    }
    // 处理最后的进位
    if (res > 0) {
        ch[i] = res + '0';
        i++;
    }
    ch[i] = '\0'; // 添加字符串结束符

    // 反向输出结果
    for (i = strlen(ch) - 1; i >= 0; i--) {
        printf("%c", ch[i]);
    }
    printf("\n");
    free(ch);
}

5. 链表释放逻辑错误

原代码嵌套while循环会导致死循环,修改为正确的遍历释放逻辑:

// 释放num1链表
while (num1 != NULL) {
    temp = num1;
    num1 = num1->tail;
    free(temp);
}
// 释放num2链表
while (num2 != NULL) {
    temp = num2;
    num2 = num2->tail;
    free(temp);
}

6. 输入缓冲区问题

原代码中getc(stdin)会读取之前输入整数后的换行符,导致无法正确获取运算符,需先清空输入缓冲区:

printf("select arithmetic symbol >> ");
// 清空缓冲区的换行符
while ((getc(stdin)) != '\n');
ch = getc(stdin);

修复后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct _Node{
    struct _Node* head; // 指向前一个节点
    struct _Node* tail; // 指向后一个节点
    char ch;
} Node;

int getLargeInt(Node** head) {
    Node* temp = NULL;
    Node* current = NULL;
    char ch;
    int len = 0;

    while (1) {
        ch = getc(stdin);
        if (ch == '\n') break;

        temp = (Node*)malloc(sizeof(Node));
        if (temp == NULL) {
            printf("内存分配失败\n");
            exit(1);
        }
        temp->ch = ch;
        temp->head = NULL;
        temp->tail = NULL;

        if (*head == NULL) {
            *head = temp;
            current = temp;
        } else {
            current->tail = temp;
            temp->head = current;
            current = temp;
        }
        len++;
    }
    // 反转链表,让头部指向数字最低位
    current = NULL;
    while (*head != NULL) {
        temp = (*head)->tail;
        (*head)->tail = current;
        current = *head;
        (*head)->head = temp;
        *head = temp;
    }
    *head = current;
    return len;
}

void addLarge(Node* n1, Node* n2, int n1_len, int n2_len) {
    int max_len = (n1_len > n2_len) ? n1_len : n2_len;
    int i = 0;
    int res = 0;
    char* ch = (char*)malloc(sizeof(char) * (max_len + 2));
    if (ch == NULL) {
        printf("内存分配失败\n");
        return;
    }

    for (i = 0; i < max_len; i++) {
        if (n1 != NULL) {
            res += n1->ch - '0';
            n1 = n1->tail;
        }
        if (n2 != NULL) {
            res += n2->ch - '0';
            n2 = n2->tail;
        }

        ch[i] = res % 10 + '0';
        res /= 10;
    }
    if (res > 0) {
        ch[i] = res + '0';
        i++;
    }
    ch[i] = '\0';

    for (i = strlen(ch) - 1; i >= 0; i--) {
        printf("%c", ch[i]);
    }
    printf("\n");
    free(ch);
}

int main() {
    Node* temp = NULL;
    Node* num1 = NULL;
    Node* num2 = NULL;
    int n1_len = 0, n2_len = 0;
    char ch;

    printf("first integer >> ");
    n1_len = getLargeInt(&num1);

    printf("second integer >> ");
    n2_len = getLargeInt(&num2);

    printf("select arithmetic symbol >> ");
    while ((getc(stdin)) != '\n'); // 清空缓冲区的换行符
    ch = getc(stdin);

    switch (ch) {
    case '+':
        addLarge(num1, num2, n1_len, n2_len);
        break;
    default:
        printf("仅支持加法运算\n");
        break;
    }

    // 释放num1链表
    while (num1 != NULL) {
        temp = num1;
        num1 = num1->tail;
        free(temp);
    }
    // 释放num2链表
    while (num2 != NULL) {
        temp = num2;
        num2 = num2->tail;
        free(temp);
    }

    return 0;
}

内容的提问来源于stack exchange,提问作者mincho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 23:25:25