dynamic stack with static array C - c

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.

Related

How to check if a list is empty? If I do "if (ptr!=NULL)" it doesn't work [duplicate]

Usually, when I use linked lists, I write:
struct node *startPtr = NULL;
so I check later if is it NULL, and if it is, it means that the list is empty.
But in this code:
struct card{
char face[3];
char suit[4];
};
typedef struct card Card;
struct stack{
Card cardd;
struct stack *nextPtr;
};
typedef struct stack Stack;
int main(){
/*
creation of *stacks also with calloc
*/
Stack *topstacks = calloc(4,sizeof(Stack)); // array of lists initialized by calloc
/*
scanf pos1, pos2 to switch
*/
move_card(stacks, topstacks, pos1, pos2);
}
int move_card(Stack *stacks, Stack *topstacks, unsigned int pos1, unsigned int pos2){
Stack *prevfromPtr;
Stack *fromPtr = &(stacks[pos1]);
Stack *toPtr = &(topstacks[pos2]);
while(fromPtr->nextPtr!=NULL){
prevfromPtr = fromPtr;
fromPtr = fromPtr->nextPtr;
}
Stack *newmovingcard = calloc(1,sizeof(Stack));
newmovingcard->cardd = fromPtr->cardd;
newmovingcard->nextPtr = NULL;
if (toPtr!=NULL){ // here I'd like to check if the list is empty and has not any item. This way it does not work because toPtr can't be NULL, it's a pointer
while(toPtr->nextPtr!=NULL){
toPtr = toPtr->nextPtr;
}
toPtr->nextPtr = newmovingcard;
free(fromPtr);
prevfromPtr->nextPtr = NULL;
return 0;
} else {
toPtr->cardd = newmovingcard->cardd;
toPtr->nextPtr = NULL;
free(fromPtr);
prevfromPtr->nextPtr = NULL;
return 0;
}
}
I have an array of lists (topstacks), initialized with calloc. And in the commented line inside move_card, I need to check if the single list of the array of lists is empty. But I don't know how to do that.
Here is the full code, but some parts with printf are in italian, so sorry for that: https://wtools.io/paste-code/b2gz
You can try to assign nextPtr to the same element or you can introduce a special global item which will mean an empty list.
If you use malloc with memset instead of calloc you can set your value as your own "void" value.
I mean this kind of thing :
int* example;
example=malloc(100*sizeof(int)); // allocate memory to store 100 int
if(example){
memset(example,1,100*sizeof(int)); // initialize it with value 1
}
Working with two linked lists simultaneously is kind of fussy and annoying, but it is doable:
int move_card(Stack **source, Stack **target, int source_pos, int target_pos) {
// Walk through the linked list, but in every case stop one short of the
// insertion point
// Walk through the source chain and identify which pointer needs
// to be manipulated.
for (int i = 0; i < source_pos; ++i) {
if (*source == NULL) {
return -1;
}
source = &((*source)->nextPtr);
}
// Walk through the target chain and identify the insertion point.
for (int i = 0; i < target_pos - 1; ++i) {
if (*target == NULL) {
return 1;
}
target = &((*target)->nextPtr);
}
// Capture the pointer we're actually moving
Stack* moving = *source;
// Skip this link in the chain by reassigning source
*source = moving->nextPtr;
// Capture the record that's being bumped
Stack* bumped = *target;
// Reassign the target
*target = moving;
// Re-link the bumped entry back in the chain
moving->nextPtr = bumped;
return 0;
}
Where I've taken the liberty of renaming a few things to make this easier to understand. Notice how it uses a double pointer so it can manipulate the original pointers if necessary. When removing the first card from a linked list, the pointer to the "head" entry must change.
Here's a more complete "demo" harness for that code:
#include <stdio.h>
#include <stdlib.h>
struct stack {
char card[2];
struct stack *nextPtr;
};
typedef struct stack Stack;
Stack* make_stack(char face, char suit, Stack* nextPtr) {
Stack* stack = calloc(1, sizeof(Stack));
stack->card[0] = face;
stack->card[1] = suit;
stack->nextPtr = nextPtr;
return stack;
}
void print_stack(Stack* stack) {
while (stack) {
printf("%c%c ", stack->card[0], stack->card[1]);
stack = stack->nextPtr;
}
printf("\n");
}
int main(int argc, char** argv) {
Stack* source = make_stack('A', 'S', make_stack('2', 'S', make_stack('3', 'S', NULL)));
Stack* target = NULL;
print_stack(source);
move_card(&source, &target, 2, 0);
print_stack(source);
print_stack(target);
return 0;
}
Where that uses a simplified Card model.

Stack and push() function

I'm doing an exercise, and want support about it. The problem is this: I have two structures (1 for the nodes of the stack, 1 for the stack). In the node structure, there is a void* data field.
I've tried to push a value on the stack but, because of void* data instead of simple data, I failed.
This is the code about the structures and the push() function.
struct upo_stack_node_s
{
void *data;
struct upo_stack_node_s *next;
};
typedef struct upo_stack_node_s upo_stack_node_t;
struct upo_stack_s
{
upo_stack_node_t *top;
size_t size;
};
/*Function for create the stack*/
upo_stack_t upo_stack_create()
{
upo_stack_t stack = malloc(sizeof(struct upo_stack_s));
if (stack == NULL)
{
fprintf(stderr, "Unable to create a stack!\n");
abort();
}
stack->top = NULL;
stack->size = 0;
return stack;
}
/*Push() function:*/
void upo_stack_push(upo_stack_t stack, void *data)
{
/* TO STUDENTS:
* Remove the following two lines and put here your implementation
*/
upo_stack_node_t *node = malloc(sizeof(struct upo_stack_node_s));
node->data = data; /*<-- Here's the problem */
node->next = stack->top;
stack->top = node;
++stack->size;
}
/*Top() function*/
void* upo_stack_top(const upo_stack_t stack)
{
/* TO STUDENTS:
* Remove the following two lines and put here your implementation
*/
return (void *)(stack->top); //<---
}
/*Function for testing (there are other functions in the code)*/
void test_top()
{
int value1 = 1;
int value2 = 2;
upo_stack_t stack;
stack = upo_stack_create();
upo_stack_push(stack, &value1); //<----
upo_stack_push(stack, &value2); //<----
assert( upo_stack_top(stack) != NULL );
assert( *((int*) upo_stack_top(stack)) == value2 ); <-- Here's the error
upo_stack_pop(stack, 0);
assert( upo_stack_top(stack) != NULL );
assert( *((int*) upo_stack_top(stack)) == value1 );
upo_stack_pop(stack, 0);
assert( upo_stack_top(stack) == NULL );
upo_stack_destroy(stack, 0);
}
You always have to pass a void pointer. That means if you want to pass a simple value, like 1, what you need to do is, is to allocate an integer value, and pass the pointer to it (as a void pointer).
Thus something like:
int x = 4;
upo_stack_push(upo_stack, &x);
Of course you have to make sure the int variable x does not go out of scope, otherwise the pointer will point to freed memory, which results in nasty memory problems.
Update
It is assumed above, that the void pointer you pass is stored already in memory for the scope of the stack. In case, you want the stack itself to copy the data, you have also to malloc space for that, thus not only mallocing the node, but also mallocing and copy the data type passed. Also to know the size of the data (since it is a void pointer, which is unaware of its type), you have to add an int size parameter to the push function.
For an integer value to be stored, pass it as a pointer, with size: sizeof(int). Than for copying the data structure, use memcpy. This only works for simple types and structures without pointers. If you have to copy structures with pointers (thus you need so called deep-copying), than it is more tricky.

passing top pointer of stack as argument

My problem is based on pointers, I want to know how can i pass top of stack in function printStack() so that i can access all nodes of stack.I am storing elements in array and same time pushing into stack.
here in this code when i execute it does not print anything.
here my code
#include<stdio.h>
struct stack
{
int data;
struct stack *next;
};
typedef struct stack s;
s *top=NULL,*neu;
//push data into stack
void push(int data)
{
neu = (s *)malloc(sizeof(s));
neu->data= data;
neu->next = NULL;
if(!top)
{
neu=top;
}
else
{
neu->next = top;
top = neu;
}
}
//pop data and move top to top->next
void pop()
{
s *temp = top;
top = top->next;
free(top);
}
//print data present in stack
void printStack(s *top)
{
while(top)
{
printf("%d ",top->data);
pop();
}
}
int main()
{
int i=0,A[3],d;
for(i=0;i<3;i++)
{
scanf("%d",&A[i]);
push(A[i]);
}
printStack(top);
return 0;
}
So there are 3 problems:-
You are freeing top rather than temp in pop().
You are changing to the local variable passed in printStack.
Simply call this printSack(); having function signature void printStack().
Also when creating the nodes
if(!top)
{
neu=top;
^^^^
}
This will be top=neu;
Some things that you should learn to do:-
Use debugger. Learn how to use it.
Don't cast the return value of malloc.
Check the return value of malloc and scanf.
You have used too many global variables - code that involves lots of global variables are tend to be difficult to debug. You could easily avoid it here.
For example:-
if( scanf("%d",&A[i])!= 1){
fprintf(stderr,"Error in input");
exit(EXIT_FAILURE);
}
In case of malloc
neu = malloc(sizeof(s));
if(neu == NULL ){
perror("Malloc failed");
exit(EXIT_FAILURE);
}
The main thing is - your code is doing nothing basically. It is even useless to create those methods which are so closely couped with each other with data. We use functions so that code becomes modular and each of the function should be reusable.( Atleast to some extent). Here you have missed that part.
You have a simple error here:
void pop()
{
s *temp = top;
top = top->next;
free(top);
}
Rather than freeing Top, you likely meant to free(temp);
Additionally, consider developing good habits early. Don't cast the return of malloc() in C. Also, don't assume that malloc() worked; check to see if it returns something other than NULL.

Pass by reference for structure in C

I want to pass a node by reference to a function and expect the variable in main() to be updated by the function
struct stack
{
int item;
struct stack *link;
};
void push(int item, struct stack *top)
{
/* allocate memory and insert item*/
}
int main(void)
{
struct stack *top;
push(10,top);
printf("%d\n",top->item);
return 0;
}
Here it displays 'segmentation fault', as if top did not get updated at all!
You need to pass the pointer top in main() by reference to the function push(). So give the address of top not its value.
So use
push(10,&top);
instead of
push(10,top);
if the changes made to top in push() are to reflected back in main().
This necessitates the modification of the function prototype. Use
void push(int item,struct stack **top)
instead of
void push(int item,struct stack *top)
And use *top in places where you used top in the push().
There are two options for what you need to do, depending on whether your function allocates the stack or the main() function allocates the stack element.
Option 1 — main() allocates top
void push(int item, struct stack *top)
{
top->link = 0;
top->item = item;
}
int main(void)
{
struct stack top; // Plain structure, not a pointer
push(10, &top); // Pass address of structure to function
printf("%d\n", top.item);
return 0;
}
This doesn't work particularly well in the context of a stack, but can often be the correct way to process structures — the calling code allocates the structure and the called code uses the allocated structure. Here is a dynamic allocation in the calling code, passed to the function to be initialized:
int main(void)
{
struct stack *top = malloc(sizeof(*top));
if (top != 0)
{
push(10, top);
printf("%d\n", top->item);
free(top);
}
return 0;
}
Option 2 — push() allocates top
void push(int item, struct stack **top)
{
struct stack *node = malloc(sizeof(*node));
node->link = *top;
node->item = item;
*top = node;
}
int main(void)
{
struct stack *top = 0; // Initialization is crucial
push(10, &top);
printf("%d\n", top->item);
push(20, &top);
printf("%d %d\n", top->item, top->link->item);
free(top->link);
free(top);
return 0;
}
This code is weird because it uses fixed operations instead of loops, but is otherwise kosher. All the code shown using malloc() has been tested with Valgrind and gets a clean bill of health.

Writing a push and pop in c

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...

Resources