我正在编写一个简单的堆栈程序(主函数只是确定用户要求你做什么)。
但是,它有一个“错误”,它只是继续“弹出”相同的值(实际上并没有弹出任何内容)。
我是否错误地使用了结构和指针?或者这是一个不太明显的编码错误?
#include <stdio.h>
struct node {
int data;
struct node *next;
struct node *prev;
} first;
void push(int);
void pop();
int main(void)
{
int command = 0;
while (command != 3)
{
printf("Enter your choice:\n1) Push integer\n2) Pop Integer\n3) Quit.\n");
scanf("%d",&command);
if (command == 1)
{
// push
int num;
scanf("%d",&num);
push(num);
}
else
{
if (command == 2)
{
pop();
}
else
{
if (command != 3)
{
printf("Command not understood.\n");
}
}
}
}
return 0;
}
void push (int x)
{
struct node newNode;
newNode.data = x;
newNode.prev = NULL;
newNode.next = &first;
first = newNode;
printf("%d was pushed onto the stack.\n", first.data);
}
void pop()
{
if (first.data == '\0')
{
printf("Error: Stack Empty.\n");
return;
}
printf("%d was popped off the stack.\n", first.data);
first = *(first.next);
first.prev = NULL;
}
first 应该是一个指针。将其更改为 struct node *first;
在主初始化中first=NULL;
更改您的推送/弹出操作,如下所示,
void push (int x)
{
struct node *newNode;// It should be a pointer
newNode = (struct node *)malloc(sizeof(struct node));
newNode->data = x;
//newNode.prev = NULL; // You don't need this
newNode->next = first;
first = newNode;
printf("%d was pushed onto the stack.\n", first->data);
}
void pop()
{
struct node *prevPtr;
//if (first.data == '\0')
if (first == NULL) // check if stack is empty
{
printf("Error: Stack Empty.\n");
return;
}
printf("%d was popped off the stack.\n", first->data);
prevPtr = first;
first = first->next;
free(prevPtr);
}
问题在于
first
是单个全局 node
,并且它是您拥有的唯一 node
(除了您对 node
的调用中的临时本地 push
)。
这一行:
first = newNode;
只需将
newNode
的内容复制到 first
中;由于 newNode.next
指向 first
,这意味着现在 first.next
指向 first
,所以你有一个单元素循环链表。
同样,这一行:
first = *(first.next);
只需将
*(first.next)
的内容复制到 first
中;这是一个无操作,因为(由于上述原因),*(first.next)
is first
。
要解决这个问题,您实际上需要使用
malloc
(和 free
)动态创建节点。你的全局 first
变量应该是一个指针 - node *
- 始终指向堆栈的顶部元素。 (更好的是,您的 push
和 pop
函数应该将 first
作为参数,而不是将其作为全局变量。这些函数不需要只允许单个堆栈存在。)
&first
有什么价值?提示,它总是相同的,因为 first
是静态分配的。即使改变结构体的内容,地址也不会改变。这可能会告诉您为什么 push
存在错误。如果您要拥有不同大小的结构,则需要使用 malloc
和 free
。
当您必须自己管理内存时(正如 C 要求您做的那样),您需要了解称为堆栈和堆的内存区域之间的区别。 (这个“堆栈”与您在程序中创建的数据结构略有不同。)
您的
push()
函数正在堆栈上创建一个新节点;当函数退出时,堆栈将被弹出,并且新节点占用的内存可供争夺。您看到输入的值是因为您的程序非常简单。如果它调用执行其他操作的其他函数,它们几乎肯定会覆盖堆栈的该部分,当您调用 pop()
时,您会看到垃圾。
正如其他人所指出的,您需要使用函数
malloc()
和 free()
,它们从堆而不是堆栈中为您提供内存。
如果要使用链表创建堆栈,请将
first
变量设置为指针。然后,当您将新节点推入堆栈时,通过 malloc() 在堆内存上分配来创建新节点。我知道你打算用它来指向堆栈的顶部。对吗?
在您的代码中,
first
变量被新节点覆盖,因为它不是指针变量而是值变量。这使得结果丢失了堆栈的顶部节点。
void pop()
{
struct node *prevPtr;
//if (first.data == '\0')
if (first == NULL)
{
printf("Error: Stack Empty.\n");
return;
}
printf("%d was popped off the stack.\n", first->data);
prevPtr = first;
first = first->next;
free(prevPtr);
}
#include <stdio.h>
#include <stdlib.h>
struct stack {
int size;
int top;
int *arr;
};
int isEmpty(struct stack* ptr){
if(ptr->top == -1){
return 1;
}
else{
return 0;
}
}
int isFull(struct stack* ptr){
if(ptr->top == ptr->size-1){
return 1;
}
else{
return 0;
}
}
int display(struct stack *s){
for(int i = s->top; i >= 0; i--){
printf("%d\n", s->arr[i]);
}
}
int main(){
struct stack *s = (struct stack*)malloc(sizeof(struct stack));
s->size = 80;
s->top = -1;
s->arr = (int *)malloc(s->size * sizeof(int));
s->top ++;
s->arr[s->top] = 1;
s->top ++;
s->arr[s->top] = 2;
s->top ++;
s->arr[s->top] = 3;
display(s);
// if(isEmpty(s)){
// printf("Stack Empty!");
// }
// else{
// printf("Stack not empty!");
// }
}
#include<stdio.h>
# define max 10
int stack[max],top=-1,size=0;
void push()
{
if(top==(max-1))
{
printf("stack full\n");
}
else
{
top++;
printf("enter the value which you want to insert\n");
scanf("%d",&stack[top]);
}
}
void pop()
{
int str;
if(top==-1)
{
printf("stack empty\n");
}
else
{
str=stack[top];
top--;
printf("the removed element is %d\n",str);
}
}
void display()
{
int i;
for(i=0;i<top;i++)
{
printf("%d\n",stack[i]);
}
}
void main()
{
int enter,x;
do
{
printf("enter 1 for push the element in the array\n");
printf("enter 2 for pop the element in the array\n");
printf("enter 3 for display the element in the array\n");
scanf("%d",&enter);
switch(enter)
{
case 1:push();
break;
case 2:pop();
break;
case 3:display();
break;
default:
printf("invalid syntax");
}
printf("for continue press 0\n");
scanf("%d",&x);
}
while(x==0);
}