C语言递归实现链表添加元素时出现段错误问题求助
问题分析与修复方案
你的代码存在多个触发段错误和异常行为的问题,逐一拆解并给出修复方案:
1. 野指针引发内存非法访问
main函数中char* name;仅声明了指针但未分配内存,直接用scanf("%10s", name);会向随机内存地址写入数据,这是段错误的核心诱因之一。
修复:为name分配足够内存,比如:
char name[11]; // 适配%10s的输入长度,额外1位存字符串终止符
2. 输入格式错误导致数据读取异常
- 读取
symbol时,scanf("%2c", &symbol);会读取前一次输入残留的换行符,导致symbol被错误赋值。需在格式符前加空格跳过空白字符:scanf(" %c", &symbol);(单个字符无需长度限制) weight是double类型,scanf需用%lf格式符,而非%f(%f用于float类型),否则会导致数据读取错误。
3. 函数逻辑与命名不符
add_to_front实际是向链表尾部添加元素,而非头部,函数名易造成误解。若需尾部添加,建议重命名为add_to_tail;若要实现头部添加,逻辑需调整(头部添加无需递归,直接创建新节点指向原头节点即可)。
4. 链表节点name的浅拷贝问题
create_list中head->name = name;是直接赋值指针,所有节点的name会指向同一块内存(main中的name数组),后续输入会覆盖之前节点的name值。若要每个节点保存独立的name,需分配内存并拷贝字符串:
head->name = malloc(strlen(name) + 1); strcpy(head->name, name);
注意:销毁链表时需释放name的内存,避免内存泄漏。
5. 冗余的内存分配
create_list中malloc(sizeof(list) + 1000);完全多余,sizeof(list)已包含结构体所有成员的内存大小,改为malloc(sizeof(list));即可。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct list { char* name; char symbol; double weight; struct list *next; } list; list* create_list(char* name, char symbol, double weight) { list* node = malloc(sizeof(list)); if (!node) { // 检查内存分配是否成功 perror("malloc failed"); exit(EXIT_FAILURE); } // 为name分配独立内存并拷贝内容 node->name = malloc(strlen(name) + 1); if (!node->name) { perror("malloc for name failed"); free(node); exit(EXIT_FAILURE); } strcpy(node->name, name); node->symbol = symbol; node->weight = weight; node->next = NULL; return node; } // 重命名为add_to_tail,明确功能 void add_to_tail(char* name, char symbol, double weight, list* h) { if (h->next == NULL) { h->next = create_list(name, symbol, weight); } else { add_to_tail(name, symbol, weight, h->next); } } // 销毁链表,避免内存泄漏 void destroy_list(list* head) { list* temp; while (head) { temp = head; head = head->next; free(temp->name); free(temp); } } int main(void) { char name[11]; char symbol; double weight; printf("Enter element's name: "); scanf("%10s", name); printf("Enter element's symbol: "); scanf(" %c", &symbol); // 跳过空白字符 printf("Enter element's weight: "); scanf("%lf", &weight); // 用%lf读取double类型 list* head = create_list(name, symbol, weight); for (int i = 0; i < 3; i++) { printf("Enter element's name: "); scanf("%10s", name); printf("Enter element's symbol: "); scanf(" %c", &symbol); printf("Enter element's weight: "); scanf("%lf", &weight); add_to_tail(name, symbol, weight, head); } // 打印链表验证结果 list* current = head; while (current) { printf("Name: %s, Symbol: %c, Weight: %.2lf\n", current->name, current->symbol, current->weight); current = current->next; } destroy_list(head); // 释放所有内存 return 0; }
内容的提问来源于stack exchange,提问作者AleksandrZhukovin
相关产品推荐
相关产品推荐

