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
相关产品推荐
相关产品推荐

