C语言链表故障:无法将head设为NULL且添加节点触发访问违规
C语言链表读取访问违规问题修复
核心错误分析与修复
1. 链表头指针传递错误
addLast函数需要修改链表的头指针(当链表为空时),因此必须传递头指针的地址(NODEPTR*类型)。原代码中main函数调用时直接传了head(NODEPTR类型),导致函数内部无法修改main中的head变量,链表始终处于空状态,后续操作访问NULL指针触发读取违规。
修复方式:
将main中的调用改为:
addLast(&head, "64 Impala", 1800.00, 12000); addLast(&head, "56 Ford", 500.00, 23000);
2. 函数声明与定义不匹配
printTotalMiles的声明是void printTotalMiles(NODEPTR);,但定义时参数写成了NODEPTR *list,类型不一致会导致编译警告或运行时异常。同时函数内部遍历逻辑错误,修改局部变量list无法完成链表遍历。
修复方式:
修正声明和定义的参数类型,并调整遍历逻辑:
// 修正声明 void printTotalMiles(NODEPTR list); // 修正定义 void printTotalMiles(NODEPTR list) { int total = 0; NODEPTR p = list; while (p) { printf("车型: %s\t价格: %.2f\t里程: %d\n", p->model, p->price, p->miles); total += p->miles; p = p->next; // 移动遍历指针 } printf("总里程: %d\n", total); }
3. 字符串清空长度错误
addLast中memset(p->model, '\0', sizeof(c))的sizeof(c)是指针的大小(不是字符串数组的大小),无法完整清空model数组,可能导致字符串残留垃圾数据。
修复方式:
使用MAX(数组定义的长度)或sizeof(p->model)来指定清空长度:
memset(p->model, '\0', MAX); // 或者 memset(p->model, '\0', sizeof(p->model));
修正后的完整代码
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX 100 typedef struct node { char model[MAX]; float price; int miles; struct node *next; } *NODEPTR; NODEPTR getNode(); void freeNode(NODEPTR p); void printTotalMiles(NODEPTR); void addLast(NODEPTR *list, char c[], float pri, int num); int main(void) { NODEPTR head = NULL; if (head == NULL) { printf("初始head为NULL\n"); } // 传递head的地址给addLast addLast(&head, "64 Impala", 1800.00, 12000); addLast(&head, "56 Ford", 500.00, 23000); printTotalMiles(head); return 0; } NODEPTR getNode(void) { NODEPTR p = (NODEPTR)malloc(sizeof(struct node)); if (p == NULL) { printf("List Overflow.\n"); exit(1); // 内存分配失败时退出程序 } return p; } void freeNode(NODEPTR p) { free(p); } void addFront(NODEPTR *list, char c[], float pri, int num) { NODEPTR p = getNode(); strcpy(p->model, c); p->price = pri; p->miles = num; p->next = *list; *list = p; printf("添加前置节点:%.2f\n", p->price); } void printTotalMiles(NODEPTR list) { int total = 0; NODEPTR p = list; while (p) { printf("车型: %s\t价格: %.2f\t里程: %d\n", p->model, p->price, p->miles); total += p->miles; p = p->next; } printf("总里程: %d\n", total); } void addLast(NODEPTR *list, char c[], float pri, int num) { NODEPTR p = getNode(); memset(p->model, '\0', MAX); strcpy(p->model, c); p->price = pri; p->miles = num; p->next = NULL; if (*list == NULL) { *list = p; } else { NODEPTR q = *list; while (q->next) { q = q->next; } q->next = p; } }
额外优化建议
- 在
getNode函数中,内存分配失败时直接调用exit(1)终止程序,避免后续使用NULL指针。 addFront函数补充了字符串复制的逻辑,使其能完整存储车型信息。- 输出信息中添加了车型字段,让打印结果更清晰。
内容的提问来源于stack exchange,提问作者The Elina
相关产品推荐
相关产品推荐

