对C的指针还是一知半解,望解惑?

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

#define TRUE 1
#define False 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef int Status, ElemType;

typedef struct LNode {
    ElemType data;
    struct LNode *next;
} LNode, *LinkList;

Status InitList_L(LinkList *L);

Status ListInsert_L(LinkList *L, int i, ElemType e);

Status ListDelete_L(LinkList *L, int i, ElemType *e);

Status PrintList_L(LinkList L);

Status main() {
    LinkList L;
    InitList_L(&L);         // 初始化线性表L
    ListInsert_L(&L, 1, 1); // 在L位置1插入1
    ListInsert_L(&L, 2, 2); // 在L位置2插入2
    ListInsert_L(&L, 3, 3); // 在L位置3插入3
    ElemType e;
    ListDelete_L(&L, 2, &e);
    printf("%d\n",e);
    PrintList_L(L);
    return OK;
}


// 初始化带头结点的链式线性表
Status InitList_L(LinkList *L) {
    *L = (LNode *) malloc(sizeof(LNode));
    if (!(*L))
        exit(OVERFLOW);
    (*L)->next = NULL;
    return OK;
}

// 向链式线性表指定位置i插入元素
Status ListInsert_L(LinkList *L, int i, ElemType e) {
    LinkList *p = L;
    int j = 0;
    while (*p && j < i - 1) {
        (*p) = (*p)->next;
        j++;
    }
    if (!(*p) || j > i - 1) // i大于表长了或是i小于1了
        return ERROR;
    LNode *s = (LNode *) malloc(sizeof(LNode));
    s->data = e;
    s->next = (*p)->next;
    (*p)->next = s;
    return OK;
}

Status ListDelete_L(LinkList *L, int i, ElemType *e) {
    LinkList *p = L;
    int j = 0;
    while (((*p)->next) && j < i - 1) {
        (*p) = (*p)->next;
        j++;
    }
    if (!(*p)->next || j > i - 1)
        return ERROR;
    LNode *q = (*p)->next;
    *e = q->data;
    (*p)->next = q->next;
    free(q);
    return OK;
}

// 在控制台打印链式线性表
Status PrintList_L(LinkList L) {
    while (!L->next) {
        printf("%d ", L->next->data);
        L->next = L->next->next;
    }
    printf("\n");
    return OK;
}

分布调试,看到这样的线性表L变化过程:

InitList_L(&L);         // 初始化线性表L

image.png

ListInsert_L(&L, 1, 1); // 在L位置1插入1

image.png

ListInsert_L(&L, 2, 2); // 在L位置2插入2

image.png

......
感觉是我操作指针不当造成的,望解惑

补充:
上述程序我是根据严蔚敏版的数据结构写的
原书ADT表示如下:

阅读 1.7k
1 个回答

你的程序有很严重的结构性问题,这不是哪个局部的问题,而是整体的问题,你的 LinkList 实际上是 LNode 的指针,那么你传递的 &L 就是 LNode** 就是指针的指针,在

    while (*p && j < i - 1) {
        (*p) = (*p)->next;

这句,你的 p 貌似是局部变量,但其实是 LNode*,所以在修改 p 的值的时候,也同时修改了 LNode* 所指向的内容,这种错误很难解决,也很难排查,根据我的经验,除非迫不得已,尽量不要使用指针的指针,很容易出问题。
我把你的程序改了一下,完全不需要 LinkList 就可以实现

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

#define TRUE 1
#define False 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef int Status, ElemType;

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
} LNode;

// 初始化带头结点的链式线性表
LNode* InitList_L()
{
    LNode *L = (LNode *)malloc(sizeof(LNode));
    if (!L)
        exit(OVERFLOW);
    L->next = NULL;
    return L;
}

// 向链式线性表指定位置i插入元素
Status ListInsert_L(LNode *L, int i, ElemType e)
{
    LNode *p = L;
    int j = 0;
    while (p && j < i - 1)
    {
        p = p->next;
        j++;
    }
    if (!p || j > i - 1) // i大于表长了或是i小于1了
        return ERROR;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;
    return OK;
}

Status ListDelete_L(LNode *L, int i, ElemType *e)
{
    LNode *p = L;
    int j = 0;
    while ((p->next) && j < i - 1)
    {
        p = p->next;
        j++;
    }
    if (!p->next || j > i - 1)
        return ERROR;
    LNode *q = p->next;
    *e = q->data;
    p->next = q->next;
    free(q);
    return OK;
}

// 在控制台打印链式线性表
Status PrintList_L(LNode* L)
{
    while (L->next)
    {
        printf("%d ", L->next->data);
        L->next = L->next->next;
    }
    printf("\n");
    return OK;
}

Status main()
{
    LNode *L = InitList_L();    // 初始化线性表L
    ListInsert_L(L, 1, 1);        // 在L位置1插入1
    ListInsert_L(L, 2, 2);        // 在L位置2插入2
    ListInsert_L(L, 3, 3);        // 在L位置3插入3

    ElemType e;
    ListDelete_L(L, 2, &e);
    printf("%d\n", e);
    PrintList_L(L);
    return OK;
}

BTW,你原来的程序在 ListDelete_L 时会崩溃。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏