【问题标题】:Push pop stack operation in C [closed]在C中推送弹出堆栈操作[关闭]
【发布时间】:2018-06-12 17:44:48
【问题描述】:

我尝试通过将 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;
}

【问题讨论】:

  • 你的前 2 个问题太笼统了:初学者如何定义“好”?此外,您在一个问题中提出了 3 个不同的问题。只有最后一个问题有一些优点,但如果您将代码和问题集中在这一点上会更好:将您的代码限制为产生该错误的最小示例,并让我们知道您已经为调试问题所做的工作.
  • @Sebivor 只是为了让您知道pipe 不是标准C,而是POSIX。此外,每次都去操作系统做一个简单的堆栈听起来很浪费资源。
  • @Sebivor:我相信管道会提供 FIFO(先进先出)规则,而不是堆栈(LIFO — 后进先出)规则。 mkfifo() 用于创建“命名管道”是有原因的。

标签: c arrays struct strcmp


【解决方案1】:

这里又出现了一些问题。在创建新线程之前 类似的内容,坚持一个线程。

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

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

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

够了。

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

  • 对于push:检查您是否还有空间进行操作
  • 对于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。


编辑: 来自 cmets 的 Sebivor 的话:

不要在typedef后面隐藏指针间接级别

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

typedef struct stack Stack;

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

【讨论】:

    猜你喜欢
    • 2020-12-19
    • 2018-06-12
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多