我在OS类中,我必须编写一个简单的堆栈程序(main函数只是确定用户要求你做什么)。如果这不是必须在C中,我会在很久以前完成这个,但因为我不擅长C编码,它有“一个错误”......到目前为止的错误是它只是继续“流行“相同的价值。 (它实际上并没有弹出任何东西)。我认为这是因为我不明白结构和指针是如何工作的。或者这是一个不那么明显的编码错误?
#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;
}
答案 0 :(得分:5)
首先应该是一个指针。将其更改为 struct node * first ;
在main initialize 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);
}
答案 1 :(得分:3)
问题在于first
是一个全局node
,而且它是您所拥有的唯一node
(除了内部的临时本地node
您致电push
)。
这一行:
first = newNode;
只需将newNode
的内容复制到first
;由于newNode.next
指向first
,这意味着现在first.next
指向first
,因此您有一个单元素循环链接列表。
同样,这一行:
first = *(first.next);
只需将*(first.next)
的内容复制到first
;这是一个无操作,因为(由于上述原因),*(first.next)
是 first
。
要解决此问题,您实际需要使用malloc
(和free
)动态创建节点。并且您的全局first
变量应该是一个指针 - node *
- 它总是指向堆栈的顶部元素。 (更好的是,您的push
和pop
函数应该将first
作为参数,而不是将其作为全局变量。这些函数不需要仅允许存在一个堆栈。)
答案 2 :(得分:2)
&first
的价值是什么?提示,它始终是相同的,因为first
是静态分配的。即使您更改了结构的内容,地址也不会发生变化。这可能会告诉您为什么push
中存在错误。如果您要使用不同大小的结构,则需要使用malloc
和free
。
答案 3 :(得分:1)
当你必须自己管理内存时,正如C要求你做的那样,你需要知道被称为堆栈的内存区域与堆之间的区别。 (此“堆栈”与您在程序中创建的数据结构略有不同。)
您的push()
函数正在堆栈中创建一个新节点;当函数退出堆栈时会弹出,并且新节点占用的内存可用于获取。您看到输入的值的事实是由于您的程序非常简单。如果它正在调用执行其他操作的其他函数,那么它们几乎肯定会覆盖堆栈的那一部分,当你调用pop()
时,你会看到垃圾。
正如其他人所指出的那样,你需要使用函数malloc()
和free()
,这些函数可以从堆而不是堆栈中获取内存。
答案 4 :(得分:1)
如果要使用链表创建堆栈,请将first
变量作为指针。然后,当您将新节点推送到堆栈时,通过malloc()分配堆内存来创建一个新节点。我知道你打算用它来指向堆栈的顶部。正确?
在您的代码中,first
变量被新节点覆盖,因为它不是指针变量而是值变量。这会导致丢失堆栈的顶级节点。
答案 5 :(得分:1)
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);
}
答案 6 :(得分:-2)
#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);
}