Original Q: I'm trying to create this calculator in C for a project. I got the math functions working, but not I am stuck on how to handle the push an pop. Can somebody help me get started? I know what push and pop are supposed to do from java, but I am not sure how to use them without using nodes or an array.
My includes and stack struct:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stack.h"
#include "debug.h"
#define DEFAULT_CAPACITY 16
struct stack {
size_t capacity;
size_t size;
stack_item *data;
};
My attempted push and pop:
UPDATED
void push_stack (stack *this, stack_item item) {
if (full_stack (this)) realloc_stack (this);
this->data[this->size++]=item;
}
stack_item pop_stack (stack *this) {
assert (! empty_stack (this));
if(this->data == NULL){
fprintf(stderr, "fail");}
else{
stack_item tempPop = this->data[this->size--];
return tempPop;}
}
Updated Q: This is now what I am doing for my push/pop method. I am getting no warnings and no errors, but when I run it, it seg faults after it should pop.
My new question is, does it appear that something I am doing in this block of code is causing my seg fault?
Use linked lists.
struct stack_element {
struct stack_element* next; // reserved for stack control
int data0; // whatever
int data1;
int data2;
};
void push_stack(struct stack_element** stack, struct stack_element* element)
{
element->next = *stack;
*stack = element;
}
struct stack_element* pop_stack(struct stack_element** stack)
{
struct stack_element* element = *stack;
if (element)
*stack = element->next;
return element;
}
struct stack_element* stack = NULL; // your stack. its empty
Creating new stack element and adding to stack:
struct stack_element* element = malloc(sizeof(struct stack_element)); // created new element
element->data0 = 123;
element->data1 = 456;
element->data2 = 789;
push_stack(&stack, element); // stored in stack
Fetching an element from stack:
struct stack_element* element = pop_stack(&stack);
if (element == NULL)
printf("Stack was empty, no elements to fetch.");
PS: The same element can never be pushed to the stack more than once.
You can also have the stack control separated from the data, in which case you will be able to store the same element more than once:
struct stack_control {
struct stack_control* next;
void* data;
};
void push_stack(struct stack_control** stack, void* data)
{
struct stack_control* temp = malloc(sizeof(struct stack_control));
temp->data = data;
temp->next = *stack;
*stack = temp;
}
void* pop_stack(struct stack_control** stack)
{
void* data = NULL;
struct stack_control* temp = *stack;
if (temp)
{
data = temp->data;
*stack = temp->next;
free(temp);
}
return data;
}
struct stack_control* stack = NULL; // empty stack
This code the way it is can be used to stack pointers of any type, because void* is generic.
//Validation sample code of behavior
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if 0
#include "stack.h"
#include "debug.h"
#else
typedef char* stack_item;
#endif
#define DEFAULT_CAPACITY 16
struct stack {
size_t capacity;
size_t size;
stack_item *data;
};
typedef struct stack stack;
stack *Stack(void){
stack *s = malloc(sizeof(stack));
s->capacity = DEFAULT_CAPACITY;
s->size = 0;
s->data = malloc(s->capacity * sizeof(stack_item));
return s;
}
int full_stack(stack *this){
return this->capacity == this->size;
}
int empty_stack(stack *this){
return this->size == 0;
}
void realloc_stack(stack *this){
this->capacity += DEFAULT_CAPACITY;
this->data = realloc(this->data, this->capacity*sizeof(stack_item));
}
void push_stack (stack *this, stack_item item) {
if (full_stack (this))
realloc_stack (this);
this->data[this->size++]=item;
}
stack_item pop_stack (stack *this) {
assert (!empty_stack (this));
if(this->data == NULL){
fprintf(stderr, "fail");
exit(1);//Maybe malloc or realloc
}
return this->data[--(this->size)];
}
int main(void){
stack *s = Stack();
push_stack(s, "sin");
push_stack(s, "+");
push_stack(s, "cos");
while(!empty_stack(s)){
puts(pop_stack(s));
}
//Stack_(s);//call destructor
return 0;
}
I understand what you mean when you say "I know what push and pop are supposed to do from java", but please bear in mind that push and pop are just operations that you can do to a data structure that is known as a stack. A stack is more of an idea and that concept can be implemented in any language.
To start of, I would advice you not to use a array. A stack imposes an order in the way you access elements and its perfectly fine with a nice linked list because you only need to remove from the head and add elements to the same head. You typically use an array when you want to access elements at any position in O(1) complexity. The effect of using a linked list is that you dont really have a bound in the number of elements you can add to the stack (unless you really want to).
If you decide to go for a linked list I would advice you to use two structures:
struct stack_node {
int data;
stack_node* next;
};
struct stack {
int current_size;
int max_size;
struct stack_node head;
};
The you can always do
void push(struct stack* s, int x){
if(s->max_size > s->current_size+1){
add to the stack
} else {
stack is full!!
}
}
int pop(struct stack* s) {
if(s->current_size == 0){
Ops! No data in stack, throw error or something
} else {
return head and remove item from stack
}
}
Note that this is only a template to give you an idea... Also, I dont really understand in your code what does "realloc_stack". I think the main problem in your code is that you might still be in a bit of a java minset and programming C requires you to think a bit more low level and do more thinks yourself...
Related
I made my own stack using linked list. But I think this is wrong.
my push method is linking Stack1 to other stacks.
So, I think it is like...
In my main function,
push(stack1, 10);
push(stack1, 20);
[Stack1] -> [nextStack]
[Stack1] -> [nextStack] (new address from first nextStack)
So, It's like... I am repeating to link stack1 to other stacks again and again...
this is my stack using linked list code below.
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int data;
struct stack *top;
}stack;
void push(stack *currentStack, int data){
if (currentStack->top == NULL)
fprintf(stderr, "Stack is emtpy");
else{
stack *nextStack = (stack*)malloc(sizeof(stack));
currentStack->data = data;
currentStack->top = nextStack;
printf("currentStack is %d\n", currentStack->data);
}
}
int main(){
stack* stack1;
stack1 = (stack*)malloc(sizeof(stack));
push(stack1, 10);
push(stack1, 20);
return 1;
}
and this is the result of my code.
currentStack is 10
currentStack is 20
#include <stdio.h>
#include <stdlib.h>
struct stack
{
int data;
struct stack *top;
} *head = NULL;
void push(int data)
{
if (head == NULL) //that means stack is empty
{
head =(struct node *)malloc(1*sizeof(struct node));
head->top = NULL;
head->data = data;
}
else
{
temp =(struct node *)malloc(1*sizeof(struct node));
temp->top = head;
temp->data = data;
head = temp;
}
}
Your push() function is incomplete.
It should consider two cases one when stack is empty and one when it is not.
Also there is no need to pass a pointer-to-stack in push() function because push() function by default pushes the new element on the topmost node and there is only one stack.
Also you have not initialised your stack pointer with NULL. This might give you undefined behaviour during program run.
This question already has answers here:
What is the reason for using a double pointer when adding a node in a linked list?
(15 answers)
Closed 7 years ago.
In the following program I need to pass an argument to a function using the &-operator although I expect it to be a pointer and the function is expecting a pointer. Why do I need to do this?
The program implements a simple stack using linked lists and incomplete types in C. Here are the three necessary files:
stack.h
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
struct Stack {
int number;
struct Stack *next;
};
/*
* We declare a pointer to a Stack structure thereby making use of incomplete
* types. Clients that pull in stack.h will be able to declare variables of type
* pstack which are pointers to Stack structures. */
typedef struct Stack *pstack;
bool is_empty(pstack *s);
void make_empty(pstack *s);
void push(pstack *s, int new_num);
int pop(pstack *s);
#endif /* STACK_H */
stack.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
bool is_empty(pstack *s)
{
return !s;
}
void make_empty(pstack *s)
{
if (!is_empty(s))
pop(s);
}
int pop(pstack *s)
{
struct Stack *tmp;
int i;
if (is_empty(s)) {
exit(EXIT_FAILURE);
}
tmp = *s;
i = (*s)->number;
*s = (*s)->next;
free(tmp);
return i;
}
void push(pstack *s, int new_num)
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = *s;
*s = new_node;
}
stackclient.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
int main(void)
{
pstack s1;
int n;
push(&s1, 1);
push(&s1, 2);
n = pop(&s1);
printf("Popped %d from s1\n", n);
n = pop(&s1);
printf("Popped %d from s1\n", n);
exit(EXIT_SUCCESS);
}
Again, I thought that by using
typedef struct Stack *pstack;
and later on in main()
pstack s1;
I'm declaring a pointer to the linked list Stack and hence it would be fine to simply pass s1 to say push() by just using
push(s1, 1);
but I actually need to use
push (&s1, 1);
Why?
Your functions are all declared to take pstack* as an argument, which is actually a pointer to a pointer to a Stack struct. Just use pstack. You'll also need to replace the instances of (*s) with just s in the implementations of those functions.
Edit: As was pointed out in the comments, you actually write to (*s) in the function implementations and rely on this behavior for correctness, so you need to keep the argument as pstack*. Conceptually, this is because the stack variable (s1) is literally the top of the stack itself, and so must be modified by push and pop.
You need to use pstack *s ( pointer to pstack ) in void push(pstack *s, int new_num), according to your implementation code,
if to use pstack s( pstack ), the new_node will not be returned correctly.
Two possible ways to insert a Node in push():
if insert to head, it should be *s = new_node
if insert to tail, it could be s->next = new_node
Back to the code, if to use push(s1, 1); such as,
//If only use pstack s, the new_node can not be pushed.
void push(pstack s, int new_num) //it is a wrong implementation for demo
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = s;
s = new_node;// WRONG! here, the new_node cannot be kept by s
// two typical node insert ways:
// 1)if insert to head, it should be *s = new_node
// 2)if insert to tail, it could be s->next = new_node
//Now, Your code applied the #1 way, so need *s
}
So, it should be inputed pstack *s, and call with push (&s1, 1);
void push(pstack *s, int new_num)//it is the correct version the same as your post
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = *s;
*s = new_node;//here, the new_node could be kept by *s
}
I have been doing excercises from a book. And I am stuck on the meaning of this qustion. Assuming that you store integer values on the stac and that using a static array to store data provide a createStack() deleteStack(stack) methods.
My interpretation is
typedef struct {
int values;
char data[50];
} StackData;
typedef struct n {
StackData d; // store some data in node
struct n *successor; // store successor of node
// as typedef is not yet completed
// name StackNode cannot be used
} SatckNode;
typedef struct {
StackNode *head;
StackNode *current;
} Stacklist;
I know these arent the methods. But i want to know if I am going about it the right way
If you're using a static array for the values, then you don't technically need createStack() and deleteStack() functions, because you can just create a struct stack or whatever on the stack (pun intended) and you're done.
If you do want to, though, (and you might legitimately want to, e.g. to avoid having to explicitly initialize top, or to hide the implementation behind an opaque type, or to be able to return one from a function without copying a potentially large array) this'll do it:
#include <stdio.h>
#include <stdlib.h>
#define STACKSIZE 50
typedef struct stack * Stack;
struct stack {
size_t top;
int values[STACKSIZE];
};
Stack createStack(void)
{
Stack new_stack = malloc(sizeof *new_stack);
if ( !new_stack ) {
perror("couldn't allocate memory");
exit(EXIT_FAILURE);
}
new_stack->top = 0;
return new_stack;
}
void deleteStack(Stack stack)
{
free(stack);
}
void push(Stack stack, const int n)
{
if ( stack->top < STACKSIZE ) {
stack->values[stack->top++] = n;
}
else {
fprintf(stderr, "Stack full - exiting.\n");
exit(EXIT_FAILURE);
}
}
int pop(Stack stack)
{
if ( stack->top > 0 ) {
return stack->values[--stack->top];
}
else {
fprintf(stderr, "Stack empty - exiting.\n");
exit(EXIT_FAILURE);
}
}
int main(void)
{
Stack mystack = createStack();
push(mystack, 3);
push(mystack, 1);
push(mystack, 4);
push(mystack, 1);
push(mystack, 5);
for ( size_t i = 0; i < 5; ++i ) {
printf("Popped %d from stack.\n", pop(mystack));
}
deleteStack(mystack);
return 0;
}
Right now you seem to want a stack with values in a static array, but then you start defining structs for nodes and lists, as if you want a linked list implementation. The two implementations are obviously pretty different.
I think you're on the right way - just a couple of comments.
In Stacklist, I don't get why you have pointers to two of the nodes in the stack.
Usually, stacks only keep a reference to the item on the top of the stack.
In addition, they either keep a counter of how big is the stack, or a pointer to the node on the bottom of the stack (which is what you probably mean by head, and reference the head node by current?).
And don't forget to initialize everything whenever you create any of those structures :P usually ends up in endless hours of headache.
Keep up the good work.
For a prelab (meaning it's not for a grade), I'm supposed to implement my first ever stack using linked lists. I wrote it adding only one thing to the stack just as practice, as to why it's so short. Anyway, I have no compile errors, besides it saying that "new" is uninitialized in my create_stack function. This is also where I'm getting a segmentation fault, as it's not printing out my first printf function. I am also guessing that the problem is bigger than just me initializing the stack, but this is my problem's start. Please go easy on me if it's something simple, as, like I said, it's my first time doing stacks, and thanks for your help.
#include <stdio.h>
#include <stdlib.h>
typedef struct node_{
char data;
struct node_ *next;
}node;
typedef struct stack_{
unsigned int size;
node* stack;
}stack;
stack* create_stack();
void push(stack* s, char val);
char top(stack* s);
void pop(stack*s);
int main(void) {
char value, val;
stack* new = create_stack();
printf("Enter a letter: ");
scanf("%c", &value);
push(new, value);
val = top(new);
printf("%c\n", val);
pop(new);
return 0;
}
stack* create_stack(){ //initializes the stack
stack* new;
new->size = 0;
new->stack = NULL;
return new;
}
void push(stack* s, char val) {
node* temp = (node*)malloc(sizeof(node)); //allocates
if ( temp == NULL ) {
printf("Unable to allocate memory\n");
}
else{
temp->next = s->stack;
temp->data = val;
s->stack = temp;
s->size = (s->size) + 1; //bumps the counter for how many elements are in the stack
}
}
void pop(stack* s) {
node* temp;
temp = s->stack;
s->stack = temp->next;
free(temp);
s->size = (s->size) - 1; //subtracts from counter
}
char top(stack* s) {
node* temp = s->stack;
char value = temp->data;
return value;
}
The reason it crashes is that you never allocate any memory when you create the stack. Do stack* new = malloc (sizeof(stack)); in the create_stack function.
For the future you might want to use better variable names. Using for instance using new as the name for the stack isn't that good - it isn't very descriptive plus it's a reserved keyword in several languages, C++ for example.
stack *new creates a local pointer, but it has nothing to point to yet. Since you want the stack to continue to exist after the function completes, you should allocate memory for it using malloc (and eventually free it using free).
So your create_stack function should start with:
stack* new = malloc(sizeof(stack));
An alternative would be to declare the stack as a local variable in your main function, and pass it as an argument into create_stack to initialize it:
stack new;
create_stack(&new);
I am new to C. I have implemented a simple stack with some structs and what not. I have posted the entire code below. The problem section is commented.
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
typedef struct Node{
int data;
struct Node *next;
} Node;
typedef struct Stack{
Node *top;
int size;
} Stack;
/* Function Prototypes */
void push(Stack *sPtr, int data);
int pop(Stack *sPtr);
void create(Stack *sPtr);
int main(void)
{
static Stack first;
create(&first);
push(&first,4);
push(&first,3);
push(&first,2);
printf("%d\n",pop(&first));
printf("%d\n",pop(&first));
printf("%d\n",pop(&first));
exit(1);
}
void push(Stack *sPtr, int data)
{
struct Node newNode;
newNode.data = data;
newNode.next = sPtr->top;
sPtr->top = &newNode;
sPtr->size++;
printf("%d\n",sPtr->top->data);
}
int pop(Stack *sPtr)
{
struct Node *returnNode = sPtr->top;
struct Node *topNode = sPtr->top;
if(sPtr->size != 0){
sPtr->top = topNode->next; /* =============PROBLEM?=============== */
return returnNode->data;
}
else{
printf("Error: Stack is Empty!\n");
return -1;
}
}
void create(Stack *sPtr)
{
sPtr->size = 0;
sPtr->top = NULL;
}
The output of this code is
4
3
2
2
8103136
680997
So obviously, it is pulling off the top node, and then printing the addresses of the next two nodes, instead of their data.
But why is it doing this? As far as I know (which is little) preforming this operation
sPtr->top = topNode->next;
should tell the program to make top now point to to topNode.next. But instead, it seems to be returning the address. What's going on here?
In your push() function, you're creating a new struct Node and adding it to your stack. However, the node is a local variable within the scope of push()--allocated on the stack (not your stack, the call stack), and will be gone when push() returns.
What you want to do is create the node on the heap, which means it will still be there after push() returns.
Since you're coding in C, you'll want to do something like:
struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
Since you're now dealing with heap-allocated memory, you'll need to make sure that at some point it gets freed (somewhere) using free().
You're also not decrementing size as Jonathan has pointed out.
One trouble is that pop() never decrements size, so size is really 'number of elements ever pushed onto stack', not 'the number of elements in the current stack'.
int pop(Stack *sPtr)
{
struct Node *returnNode = sPtr->top;
struct Node *topNode = sPtr->top;
if (sPtr->size != 0)
{
sPtr->top = topNode->next;
sPtr->size--;
return returnNode->data;
}
else
{
fprintf(stderr, "Error: Stack is Empty!\n");
return -1;
}
}
Another trouble, as pointed out by unluddite in his answer is that you are not pushing data correctly. You need both fixes to be safe. There might still be other problems (such as not freeing memory correctly — or at all), but these two will get you a long way.