使用列表进行堆栈操作

时间:2016-02-25 22:12:43

标签: c stack

我正在尝试使用链接列表在C上编写堆栈。我有CreateStack功能的问题。当我创建一个堆栈但是当我尝试创建另一个堆栈时,一切似乎都很好,程序就崩溃了。这是我的代码的一部分

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

struct StackData{
    int data;
    struct StackData* prev;
    struct StackPoint* point;
};

struct StackPoint{
    struct StackData* basePointer;
    struct StackData* stackPointer;
    char exists;
};

int CreateNewStack(struct StackData** newPointer){
    if((*newPointer)->point->exists=='Y') //i'm trying to check whether the list with the same adress has been already created and i think this is the part which causes error
        return 1; //if error
    else{
        (*newPointer)=(struct StackData*)malloc(sizeof(struct StackData));
        (*newPointer)->data=NULL;
        (*newPointer)->prev=NULL;
        (*newPointer)->point=(struct StackPoint*)malloc(sizeof(struct StackPoint));
        (*newPointer)->point->basePointer=newPointer;
        (*newPointer)->point->stackPointer=newPointer;
        (*newPointer)->point->exists='Y';
        return 0;
    }
}

int main()
{
    struct StackData *pointeris, *temp;
    int state;
    state=CreateNewStack(&pointeris);  //state 0

    state=CreateNewStack(&pointeris);  //state 1


    CreateNewStack(&temp);            //crash
    return 0;
}

1 个答案:

答案 0 :(得分:0)

此代码包含编译器警告。

test.c:21:28: warning: incompatible pointer to integer conversion assigning to 'int' from 'void *'
      [-Wint-conversion]
        (*newPointer)->data=NULL;
                           ^~~~~
test.c:24:42: warning: incompatible pointer types assigning to 'struct StackData *' from
      'struct StackData **'; dereference with * [-Wincompatible-pointer-types]
        (*newPointer)->point->basePointer=newPointer;
                                         ^~~~~~~~~~~
                                          *
test.c:25:43: warning: incompatible pointer types assigning to 'struct StackData *' from
      'struct StackData **'; dereference with * [-Wincompatible-pointer-types]
        (*newPointer)->point->stackPointer=newPointer;
                                          ^~~~~~~~~~~
                                           *

解决了这些问题后,立即解决了这个问题:

if((*newPointer)->point->exists=='Y')

*newPointer可能为null。 *newPointer->point可能是垃圾。 *newPointer->point->exists可能是垃圾。

部分问题是CreateNewStack实际上“如果堆栈尚不存在,可能会创建一个新堆栈”。如果将“创建新堆栈”与“创建新堆栈(如果它尚不存在”)分开,则代码将更加简单。实际上,每个结构都应该有自己的创建和销毁功能。

我也冒昧地为你的结构添加typedef。我已经从malloc切换到calloc以确保在创建时分配的结构为零。这意味着即使您忘记初始化每个成员,结构成员中也不会有任何垃圾。

typedef struct StackData {
    int data;
    struct StackData* prev;
    struct StackPoint* point;
} StackData;

typedef struct StackPoint {
    struct StackData* basePointer;
    struct StackData* stackPointer;
    char exists;
} StackPoint;

StackPoint *CreateStackPoint() {
    StackPoint *point = calloc(1, sizeof(StackPoint));

    point->exists = 'Y';

    return point;
}

StackData *CreateStackData() {
    StackData *data = calloc(1, sizeof(StackData));

    data->point = CreateStackPoint();
    data->point->basePointer  = data;
    data->point->stackPointer = data;

    return data;
}

现在CreateNewStack变为MaybeCreateStackData并且更加简单。

int MaybeCreateStackData(StackData **maybeStack_p) {
    if( maybeStack_p == NULL ) {
        fprintf(stderr, "The stack double pointer cannot be null");
        exit(1);
    }

    StackData *maybeStack = *maybeStack_p;

    if( maybeStack && maybeStack->point && maybeStack->point->exists == 'Y' ) {
        return 1;
    }
    else {
        *maybeStack_p = CreateStackData();
        return 0;
    }
}

老实说,这个计划过于复杂。在C中,很难知道指针何时被正确初始化而不是指向随机存储器。您的exists成员尝试解决此问题,但垃圾仍然可能会出现Y

相反,我放弃了整个想法,让调用者决定他们是否有一个有效的结构。现在您已经拥有了可靠的初始化函数,但是很少有人会初始化指针。