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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:05:18