C中压栈出栈操作

Push pop stack operation in C

我试图通过将 pop 中的值存储在数组中来进行堆栈推送弹出操作。我对这段代码有几个问题。
1. 初始化部分工作正常吗?编译的时候好像没有问题,但是还是很好奇
2.删除部分是否也有效?虽然,我输入了 !,但它似乎没有转到 else if(strcmp (str[i], "!")==0) 部分。 3. pop操作后如何存储值?我想将其存储为数组格式,但是当我将它们存储在数组中后打印出来时,发生了运行时错误。
代码如下:

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

typedef struct stack *Stack;

struct stack {
    char *array;
    int size;
    int top;
};//making stack


Stack create(int c);
Stack makeEmpty(void);//initialization
int isEmpty(Stack S)
{
    if(S->top==-1)
        return 0;
    else
        return 1;
};
void push(char X, Stack S)
{
    S->array[++S->top]=X;
};
char pop(Stack S)
{
    return S->array[S->top--];
};
void deleteStack(Stack S)
{
    while (S->top>=0)
    {
        free(S->array[S->top]);
        S->top--;
    }

};

int main (void)
{
    Stack S1=makeEmpty();
    char input[100], result[30], result1;
    char *word;
    int cnt=0,cnt2=0, temp=0, k=0, i,j,l;
    word=strtok(input, " ");
    char *str[20];

    while(1){
        if(fgets(input,100,stdin)){
            word=strtok(input, " ");//get input and tokenize
            cnt=0;
            while (word!=NULL)
            {
                str[cnt]=strdup(word);
                cnt++;
                word=strtok(NULL," ");  
            }       
        }

        for (i=0; i<cnt; i++)
        {
            if (strcmp(str[i],"(")==0 && (isEmpty(S1)==0))
            {
                push(str[i],S1);
                l++;
            }
            else if(strcmp(str[i],")")==0)
            {
                temp++;
                for(j=0; j<cnt2; j++)
                {
                    char result1=pop(S1);
                    result[k] =result1;
                    printf("%s ", result[k]);//This the place where I got runtime error
                    k++;
                }
                pop(S1);
                cnt2=0;     
            }
            else if(strcmp (str[i], "!")==0)
            {
                printf("in\n");
                deleteStack(S1);
                return 0;
            }

            else 
            {
                if  (isEmpty(S1)==1)
                {

                    if (l!=0)
                    {
                        push(str[i],S1);

                        if (strcmp(str[i],"(")!=0)
                        {
                            cnt2++;
                        }
                    }
                }
            }
        }
    }

    return 0;
}


Stack create(int c)
{
Stack S=(Stack)malloc(sizeof(struct stack));

    S->size=c;
    S->top=-1;
    S->array=(char *)malloc(sizeof(char)*c);

    return S;
}

Stack makeEmpty(void)
{
    Stack S1=create(100);
    S1[0].top=-1;
    return S1;
}

这里你又犯了一些错误。在你创建新线程之前 相似内容,一贴。

在您的代码中,您也从不检查 malloc 是否失败。这样做总是更好。为简单起见,我在建议中省略了这些检查。

1。 你为什么在 makeEmpty 中做 S1[0].top=-1;create 已经这样做了,并且以这种方式编写(而不是 S1->top = -1)会使代码难以解释,因为这可能意味着您将 create 的结果视为 Stacks。没错,这让我们更难理解你的意图。

Stack makeEmpty(void)
{
    Stack S1=create(100);
    return S1;
}

够了。

2。 在 pushpop 中,您必须首先检查操作是否有效。那 意思是:

  • for push:检查您是否还有 space 来执行操作
  • for pop: 检查堆栈中是否至少有一个元素。

代码可以是:

int isFull(Stack S)
{
    return (S->size - 1 == S->top);
}

int push(char X, Stack S)
{
    if(isFull(S))
        return 0;

    S->array[++S->top]=X;
    return 1;
}

int pop(Stack S, char *val)
{
    if(isEmpty(S))
        return 0;

    *val = S->array[S->top--];
    return 1;
}

我更改了这些函数的签名以使用户知道如果 操作成功。否则你不知道,你最终会得到 未定义的值。主要是您还应该更改 pop 调用:

char el;
pop(S1, &el);

3。 你想要 deleteStack 做什么:重置堆栈或释放内存?你 正在以一种糟糕的方式混合它们。

如果你想重置(意思是一次弹出所有元素),那么你有 要做的是设置top = -1。您不必释放 array。如果你这样做,那么你 需要再次为 array 重新分配内存。

使用 free 时,您只能将相同的指针传递给 free 你从 malloc/calloc/realloc 得到了。在你的代码中你传递了一个 8 位整数作为指针地址并释放它,这将使您 100% 的时间程序崩溃。

void deleteStack(Stack S)
{
    S->top = -1;
}

如果你想释放内存

void freeStack(Stack S)
{
    free(S->array);
    free(S);
}

但是 这也意味着您无法再访问堆栈。请注意,我 更改了函数的名称以使其更清楚其意图。

如果您使用我的建议,您也必须在 main 中进行更改, 特别是 pops.


编辑: Sebivor 引自评论:

Don't hide levels of pointer indirection behind typedef

是的,这也使代码难以阅读。在我的建议中我没有改变它,但我肯定会改变

typedef struct stack Stack;

并在每个以 Stack S 作为参数的函数中将其更改为 Stack *S。 (另请参阅 Is it a good idea to typedef pointers — 简短的回答是 'No'。)