Hey I am writing a stack function and I am having trouble with popping values off the top of my stack. My push functions seems to be working though. This is the code for my push and pop.
void push(int num, int ** sp)
{
if (++(*sp) == NULL)
printf("Stack Overflow");
else{
printf("sp for push = %p \n", *sp);
**sp++ = num;
}
}
int pop(int **sp)
{
printf("sp for pop = %p\n", *sp);
num = (**sp)--;
printf("sp = %d\n",num);
printf("sp for pop = %p\n", *sp);
return num;
}
I was also having trouble checking for the null condition to prevent popping elements that are not even on the stack, but one problem at a time.
Anyway, the output of the function looks like this when I push 15 then 5
sp for push = 0x1761014
sp for push = 0x1761018
sp for pop = 0x1761018
sp = 5
sp for pop = 0x1761018
5
Where sp is the stack pointer. Notice how the stack pointer increments by the sizeof int. I am passing both pointers by reference, so they should both change the position in memory they are pointing too, but for the pop function when I am post-decrementing the pointer the value is not changing for some reason. Can someone help explain this to me? Any help is appreciated.
Basic mistake, I needed to change the address of the pointer pointing to the data, not the pointer pointing to the pointer. The new code is:
int pop(int **sp)
{
printf("sp for pop = %p\n", *sp);
num = (**sp);
(*sp)--;
printf("sp = %d\n",num);
printf("sp for pop = %p\n", *sp);
return num;
}
In pop, you are decrementing the value in stack rather than the pointer to it. Remember, *sp is the stack pointer, NOT **sp. So, you need to decrement *sp and not **sp.
int pop(int **sp)
{
printf("sp for pop = %p\n", *sp);
/* num = (**sp)--; */ // ISSUE: Decrementing value instead of pointer
num = *(*sp)--;
printf("sp = %d\n",num);
printf("sp for pop = %p\n", *sp);
return num;
}
There is also an issue in push function. Althouh it does not create issue now, it is best to fix it.
void push(int num, int ** sp)
{
if (++(*sp) == NULL)
printf("Stack Overflow");
else{
printf("sp for push = %p \n", *sp);
// **sp++ = num; // ISSUE: increment not needed.
// Once incremented, it will NOT point
// to stack pointer anymore
**sp = num;
}
}
To check if you have space in the stack while pushing, and to check if any elements are there while popping, you can use an index variable to keep track of number of elements in stack.
Suppose Max capacity of stack is say N. Initialize the index to 0.
Now whenever you push, first check if index < N, then only push ( and increment the index by 1). If index is not smaller than N, then you have stackoverflow.
Whenever you pop, first check if index > 0, then only pop (and decrement the index by 1). If index is not greater than 0, then you have no element to pop.
Also, worth mentionning, is that it is more natural if this index is named stack pointer - sp - which points to the top of stack. You can can pass the pointer to base of stack and call it base or something else. Your functions would then be:
void push(int num, int *base, int sp) { ... } // base: start address of stack,
int pop(int *base, int sp) { ... } // sp: index of top of stack
Related
Numbers are pushed onto the stack, you need to pop the full stack, after which, the stack in which elements less than 10 are removed. Example code when all elements of the stack are removed:
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <stdio.h>
#include <math.h>
#include <malloc.h>
struct kkk
{
float elem[15];
int top; // index of the top rlrment
};
struct kkk* st, * element; // pointers
void Init(struct kkk* st) // initialization
{
st->top = NULL;
}
void Push(struct kkk* st, float f) // push an item onto the stack
{
if (st->top < 15)
{
st->elem[st->top] = f;
st->top++;
}
else
printf("Stack full\n");
}
float Pop(struct kkk* st) // pop an item from the stack
{
float el;
if ((st->top) > 0)
{
st->top--;
el = st->elem[st->top];
return el;
}
else
{
printf("Stack is empty \n");
return 0;
}
}
float Vulychtop(struct kkk* st) // deleting the top of the stack
{
if ((st->top) > 0) {
return(st->elem[st->top - 1]);
}
else {
printf("Stack is empty!\n");
return 0;
}
}
int Gettop(struct kkk* st) // top element of the stack without delting
{
return(st->top);
}
int Isempty(struct kkk* st) // check
{
if ((st->top) == 0)
return 1;
else return 0;
}
void Vuvid(struct kkk* st) // Output of all elements
{
int i;
i = st->top;
if (Isempty(st) == 1) return;
do {
i--;
printf("%f\n", st->elem[i]);
} while (i > 0);
}
int main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
int i, n, k;
float znach;
element = (struct kkk*)malloc(sizeof(struct kkk));
Init(element);
printf("Enter the number of items in the stack \n");
scanf("%d", &n);
for (i = 0; i < n; i++) {
printf("Enter the number %d: ", i);
scanf("%f", &znach);
Push(element, znach);
}
printf("In stack %d elements \n", Gettop(element));
printf("\n");
Vuvid(element);
printf("Top element %f\n", Vulychtop(element));
do {
printf("The element to be removed %f, ", Pop(element));
printf("Items left in the stack %d \n", Gettop(element));
} while (Isempty(element) == 0);
return 0;
}
Result: https://i.stack.imgur.com/wLczr.png
I create a stack, after which I start entering numbers into it. With that, I'm fine. Next, I find the top element of the stack and pop it out. After that, I need to remove those numbers from the stack, the value of which is less than 10, and I manage to completely clear the stack one by one. Can't make a condition for this.
One approach would be to use another stack as temporary storage. In pseudo-code something like:
* create tmp-stack
* while org-stack isn't empty
* data = pop org-stack
* if (data >= 10) push data to tmp-stack
* while tmp_stack isn't empty
* data = pop tmp_stack
* push data to org-stack
* free tmp-stack
This can be implemented using the already existing function.
Better performance can be achieved by operating directly on the array holding the stacks data. Based on ideas from #SergeBallesta it may look like:
* write-index = 0;
* read-index = 0;
* while read-index < top
* if array[read-index] >= 10
* array[write-index] = array[read-index]
* write-index = write-index + 1
* read-index = read-index + 1
* top = write-index
It seems you are using an old MS compiler. For example the header <malloc.h> is not a standard C header. Instead you should use the header <stdlib.h>. Also neither declaration from the header <math.h> is used. So you may remove the inclusion of the header.
The function Gettop does not do what is written in the comment for the function
// top element of the stack without delting
Actually it returns the current value of the data member st->top that is how many elements are present in the stack.
On the other hand, the comment for the function Vulychtop
// deleting the top of the stack
is incorrect. The function does not delete an element from the stack because the value of the data member st->top is not decreased. Also such a function should not output any message. It is the function Pop that removes an element from the stack.
The function Vulychtop could be defined the following way
int Vulychtop( struct kkk *st, float *value )
{
if ( st->top != 0 ) *value = st->elem[st->top - 1];
return st->top != 0;
}
The function Pop also should not issue any message and return an element of the stack.
Also there is no great sense to declare the pointer element in the file scope. It could be declared in main.
The pointer st declared in the file scope
struct kkk* st, * element; // pointers
^^
is not used in the program.
Also there is no need to allocate an object of the type struct kkk dynamically.
You could just write in main
struct kkk element;
Init( &element );
To remove elements that are less than 10 from the original stack using the open interface of the stack you need an auxiliary stack.
For example
struct kkk st;
Init( &st );
while( !Isempty( element ) )
{
float value;
Vulychtop( element, &value ); // here I am using the function definition I showed above
if ( !( value < 10.0f ) ) Push( &st, value );
Pop( element );
}
while( !Isempty( &st ) )
{
float value;
Vulychtop( &st, &value ); // here I am using the function definition I showed above
Push( element, value );
Pop( &st );
}
You can yourself add messages in the while loops about what elements are popped, pushed or removed.
Pay attention that as you allocated an object of the type struct kkk dynamically you should free it before exiting the program
free( element );
In the pop() function i am trying to change the value of the Last global variable. It works fine in the push(n) function, while in the pop() one it changes it inside the function (verifying it with prints) but then it resets to the previous value just after leaving the method. Can't get my head around it.
#include "stack.h"
#include <stdio.h>
#include <stdlib.h>
int *Stack;
int Last = -1;
void make_empty( void ){
free(Stack);
Last = -1;
Stack = NULL;
//Stack = malloc(4);
return;
}
int is_empty( void ){
if (Last == -1)
return 1;
return 0;
}
int top( void ){
if (is_empty()) {
printf("La pila è vuota");
}
return Stack[Last];
}
int pop( void ){
if (is_empty()) {
printf("La pila è vuota");
return 0;
}
int temp = Stack[Last];
printf("last: %d\n", Last);
Stack = realloc(Stack, (--Last+1)*sizeof(int));
printf("last: %d\n", Last);
return temp;
}
void push( int n ){
Stack = realloc(Stack, (++Last+1)*sizeof(int));
Stack[Last] = n;
return;
}
void print_stack( void ){
printf("last: %d\n", Last);
for (int c=0; c<=Last; c++)
printf("%d ", Stack[c]);
printf("\n");
}
You're not allocating enough space for your stack.
At the start Last is -1. Then you push an element to the stack and allocate space:
Stack = realloc(Stack, ++Last*sizeof(int));
After the increment, Last is 0. So you're allocating 0*sizeof(int) == 0 bytes. You then write to Stack[Last] which doesn't exist. This invokes undefined behavior, which in your case manifests by causing a variable to change when you don't expect.
Since Last contains the last valid index, you want to add 1 to this to get the proper number of elements to allocate:
Stack = realloc(Stack, (++Last + 1)*sizeof(int));
You make a similar mistake when popping:
Stack = realloc(Stack, --Last*sizeof(int));
You also need to add 1 here:
Stack = realloc(Stack, (--Last + 1)*sizeof(int));
The implementation of the stack contains undefined behavior.
For example initially Last is equal to -1.
int Last = -1;
then in the push operation
void push( int n ){
Stack = realloc(Stack, ++Last*sizeof(int));
Stack[Last] = n;
return;
}
there is allocated memory of the size equal to 0 because ++Last is equal to 0. You may not change the memory allocated with the size equal to 0.
A similar problem exists for the method pop. When Last is equal to 0 then in this statement
Stack = realloc(Stack, --Last*sizeof(int));
the expression --Last is equal -1 that is converted to the maximum value of the type size_t due to the type of the operand sizeof(int).
You could write for example the method push the following way
void push( int n ){
Stack = realloc(Stack, ( ++Last + 1 ) *sizeof(int));
Stack[Last] = n;
return;
}
And in the pop method you could use
if ( Last == 0 )
{
free( Stack );
Stack = NULL;
}
else
{
Stack = realloc(Stack, ( Last *sizeof(int));
}
--Last;
Pat attention to this if statement
if ( Last == 0 )
{
free( Stack );
Stack = NULL;
}
when the stack is empty all allocated memory must be freed and Stack must be set to NULL.
I am asked to implement a stack using a linked list. The program declares two "stacks" and uses them in order to sort some integers stored inside a file. I have the following program that crashed at the beginning. I think the it crashes in the first while of the else. (for the file, the user enters its name)
/************************************************************************************************************************
Input File: A text file named: "Numbers.txt" that contains integers in random order. These integers are seperated
by either a space or a new line. This file is very essencial for the program to work, because from it the
program gets the integers. below is an example of the file format: (Note that there is a new line after
the last integer in order for the file to be read correctly).
2 1 3 5 4
7 6 8 9
Output File: None
Description: This program reads integers in random order. These integers are sorted by the end of the program's execution.
The sorting operations, using Push and Pop functions are managed by two structures of type stack_t.
The first structure is the main one that will be shown to the user, the second one is the one that holds the
unsorted integers while sorting. By the end stack2 will be empty and stack 1 will be sorted.
*************************************************************************************************************************/
#include <stdio.h>
#define MAXSTACK 10 // Defining the size of the stack as being 10 elements
typedef struct node s_Node;
struct node {
int element;
s_Node*next;
}; // Define the node_t structure with the element of the node and the pointer to the next node
typedef struct{
s_Node *top_stack;
}stack_t; // Define the stack_t structure with a pointer to s_Node (the first element of the linked list)
/*-------------------------- NEEDED PROTOTYPES --------------------------*/
// Initializes a new stack and returns it
stack_t NewStack();
// Returns 1 if the stack is empty, 0 otherwise
int Empty(stack_t q);
// Returns 1 if the stack is full, 0 otherwise
int Full(stack_t q);
// Pushes the element e in the stack. Returns 1 if it could Push.
int Push(int e, stack_t *q);
// Pops an element, placing it in e. Returns 1 if it could Pop.
int Pop(int *e, stack_t *q);
// Search for the top element in the stack and returns it.
int Peek (stack_t s);
// Displays the content of the stack.
void Printstack(const stack_t );
/*============================ MAIN PROGRAM ============================*/
main () {
char filename [20];
int newint, val1, val2;
FILE *file;
stack_t stack1;
stack_t stack2;
stack1=NewStack(); //Initializing the stack
stack2=NewStack();
printf ("\n\tPlease Enter the name of the file that contains your integers: ");
scanf ("%s", &filename);
file = fopen (filename, "r");
if (file!=NULL) {
fscanf (file, "%d", &newint);
while (!feof (file)&&!Full (stack1))
{
if ( Empty (stack1)) // Putting the first integer read from the file into the first stack.
{
Push (newint, &stack1);
}
else if (newint <= Peek(stack1)) //If the integer read from the file is less or equal to the integer in the top of the stack
{
Push(newint, &stack1); // Push the integer into stack1.
}
else
{
while ( newint > Peek (stack1) )
{ //Repeat poping from stack1 and pushing into stack2
// until it the integer read from the file is bigger than the top element of stack1
printf ("gOT into THE WHILE LOOP\n");
Pop (&val1,&stack1);
Push (val1, &stack2);
Printstack (stack2);
}
printf ("gOT OUT OF THE WHILE LOOP\n");
Push (newint, &stack1); //Pushing the integer read from the file into the first stack.
Printstack (stack1);
while (!Empty(stack2))
{ // Keep poping elements from stack2 and pushing them into stack1 until stack2 is empty
Pop (&val2,&stack2);
Push (val2, &stack1);
}
}
fscanf (file, "%d", &newint);
} // End while
if (feof(file)) printf ("\n\tYou have reached the end of the file: %s.\n\tThere are no more elements to read.",filename);
else printf ("\n\n\tYour stack is full.\n\tYou can not enstack more elemeents");
fclose (file);
printf ("\nThe final result");
Printstack (stack1);
}else printf ("Error!!! Your file did not open successefully!\n"); // Error checking in reading the file
} // End main
/*-------------------------- FUNCTION DEFINITIONS --------------------------*/
// Initializes a new stack and returns it
stack_t NewStack()
{
stack_t *n_stack;
n_stack=(stack_t*)malloc(sizeof(stack_t));
n_stack->top_stack=NULL;
return (*n_stack);
}
// Returns 1 if the stack is empty, 0 otherwise
int Empty(stack_t q)
{
if(q.top_stack==NULL)
return 1;
else
return 0;
}
// Returns 1 if the stack is full, 0 otherwise
int Full(stack_t q)
{
return 0;
}
// Pushes the element e in the stack. Returns 1 if it could Push.
int Push(int e, stack_t *q)
{
s_Node *nn;
nn= (s_Node*)malloc(sizeof(s_Node));
if(Full(*q))
{
printf("\n\t Stack is Full !! \n\n");
return 0; // return 0 if enstack NOT successful
}
else
{
nn->element=e;
nn->next=q->top_stack;
q->top_stack=nn;
return 1;
}
}
// Pops an element, placing it in e. Returns 1 if it could Pop.
int Pop(int *e, stack_t *q)
{
s_Node *temp;
if(Empty(*q)) // Check if the stack is empty
{
return 0; // popping Failed
}
else
{
temp=q->top_stack; // store the top in a temp ptr Node to free it after
*e=q->top_stack->element; // Store the popped element in e
q->top_stack=q->top_stack->next; // Point the top to the next element
free(temp); // Free the popped Node
return 1;
}
}
void Printstack(const stack_t q)
{
if(Empty(q))
printf("\n\tStack is empty!!\n");
else{
s_Node *walker;
walker = q.top_stack;
printf("\n\t This is the content of the stack:\n");
while(walker!=NULL)
{
printf("\t%d ",walker->element);
walker=walker->next;
}
printf("\n");
}
}
int Peek (stack_t s)
{ printf ("%d\n",s.top_stack->element);
return s.top_stack->element; // Returning the top element of the stack
}
Thank you in advance.
You're deferencing a NULL here:
int Peek (stack_t s)
{ printf ("%d\n",s.top_stack->element);
During this sequence:
else
{
while ( newint > Peek (stack1) )
{ //Repeat poping from stack1 and pushing into stack2
// until it the integer read from the file is bigger than the top element of stack1
printf ("gOT into THE WHILE LOOP\n");
Pop (&val1,&stack1);
Push (val1, &stack2);
Printstack (stack2);
}
Because of your input list:
2 1 3
3 is larger than everything on your stack so you pop everything off while looking for an element larger than 3, that leaves your stack1.top_stack as NULL. Your check should be:
while (!Empty(stack1) && (newint > Peek (stack1)))
Change
while ( newint > Peek (stack1) )
to
while ( !Empty(stack1) && newint > Peek (stack1) )
Since your peek function doesn't handle Empty stacks, you have to check for it explicitly.
So for some reason this function appears to be pushing all of the same value onto the stack (or just printing the same value; i suppose it could actually be something to do with the printAll function which i also included.)? The thing is, for the element array (which is an array of integers), printAll appropriately cycles through the values. But anything concerning the charElement array, the printAll function ONLY prints the most recent value for each and every value in the charElements function. Any idea why this is happening?
void pushString(Stack *S, char element[])
{
/* If the stack is full, we cannot push an element into it as there is no space for it.*/
if(S->size == S->capacity)
{
printf("Stack is Full\n");
}
else
{
/* Push an element on the top of it and increase its size by one*/
S->charElements[S->size++] = element;
S->elements[S->size-1] = '\n';
}
return;
}
void printAll(Stack *S)
// NOTE: Called w/ user input 'f'
// PRE: Stack S is initialized
// POST: Print all values from the stack
// Do NOT alter anything
{
int i;
for(i = 0; i < S->size; i++)
{
printf("%d \n", i);
if(S->charElements[i] == "\n")
{
printf("%.2f \n", (float)S->elements[i]);
}
else if(S->elements[i] == '\n')
{
printf("%s \n", S->charElements[i]);
}
}
}
S->charElements[S->size++] = element;
merely copies the pointer to the passed-in char* element.
If you are using the same buffer to read the input and then pass it to the pushString function repeatedly, all stack elements end up pointing to the same buffer, and its contents is the last entered value.
You need to copy the contents, using strdup or malloc and strcpy.
S->charElements[S->size++] = strdup(element);
resp.
S->charElements[S->size] = malloc(strlen(element) + 1);
// check for NULL
strcpy(S->charElements[S->size++], element);
The code is very strange. Elements are represented by char [] in the push function, but printed using %f in printAll(). This doesn't make a lot of sense, to me.
Without the declaration of the Stack structure, it's hard to follow the code's intentions.
I've implemented a stack in C, using a stackADT struct and a set of functions:
#ifndef _stack_h
#define _stack_h
// Macros
#define MaxStackSize 100
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// The type of element that may
// be stored in the stack
typedef int stackElementT;
// The stackADT represents the abstract type used to store
// the elements that have been pushed
typedef struct stackCDT
{
// A pointer to an array of elements
stackElementT* elements;
// Number of elements on the stack
int count;
// Number of elements we can push onto
// the stack before having to resize
int size;
}* stackADT;
// This function allocates and returns a new stack, which is
// initially empty... AKA - The Constructor
stackADT NewStack(void)
{
// The stack to return
stackADT stack;
// Instanitate a new stack
stack = (stackCDT*)(malloc(sizeof(stackCDT)));
// Start with 0 elements of course
stack->count = 0;
// Allocate memory for 50 integers
stack->elements = (stackElementT*)(malloc(50*sizeof(stackElementT)));
// Establish the size of the stack
stack->size = 50;
return stack;
}
/********* GETTER FUNCTIONS *********/
// Returns the number of elements currently pushed
// onto the stack
int StackDepth(stackADT stack)
{
return (stack->count);
}
// This function returns the element a the specified index in
// the stack, where the top is defined as index 0
stackElementT GetStackElement(stackADT stack, int index);
// Function to print contents of stack
void PrintStack(stackADT stack)
{
int i = 0;
printf("count = %d\nsize = %d\n",stack->count,stack->size);
for(i = (stack->count - 1); i >= 0; i--)
{
if((i%10 == 0) && (i != 0))
printf("\n");
printf("%d\t",*(stack->elements + i));
}
}
// Functions to determine if stack is empty or full
int StackIsEmpty(stackADT stack)
{
if(stack->count == 0)
return 1;
else
return 0;
}
int StackIsFull(stackADT stack)
{
if(stack->count == stack->size)
return 1;
else
return 0;
}
// This function pushes the specified element onto the stack
void Push(stackADT stack, stackElementT element)
{
// A temporary array that we may use later on
stackElementT* temp = NULL;
int oldCount = stack->count;
int i = 0;
// If the stack if full we need to do a
// a transfer, resize, and retransfer, then push
if(StackIsFull(stack))
{
// temp will be the same size as the old stack
temp = (stackElementT*)(malloc((oldCount)*sizeof(stackElementT)));
// Now we perform the transfer
for(i = 0; i < oldCount; i++)
{
*(temp + i) = *((stack->elements) + i);
}
// Free the old memory
free(stack->elements);
stack->elements = NULL;
// Recreate the stack with a 50% increase in size/capacity
stack->elements = (stackElementT*)(malloc((3*oldCount/2)*sizeof(stackElementT)));
// Re-establish the size
stack->size = 3*oldCount/2;
// Now we perform the transfer back
for(i = 0; i < oldCount; i++)
{
*((stack->elements) + i) = *(temp + i);
}
// Free the temp array and
// remove dangling pointer
free(temp);
temp = NULL;
// Now we push the element onto the stack
*((stack->elements) + oldCount) = element;
// Increase the count
stack->count = oldCount + 1;
}
// If the stack isn't full
else
{
*((stack->elements) + oldCount) = element;
stack->count = oldCount + 1;
}
}
// This function pops the top element from the stack and returns
// that value
stackElementT Pop(stackADT stack);
// This function frees the storage associated with the stack
void FreeStack(stackADT stack)
{
// Start by freeing the elements on the stack
// and remove dangling pointers
free(stack->elements);
stack->elements = NULL;
// Finally free the stack
free(stack);
stack = NULL;
}
#endif
Obviously I'm not completely finished (needs a pop function). My concern is with the bottom function (FreeStack). I tested the code below as such:
#include <stdio.h>
#include <stdlib.h>
#include "Stack.h"
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
int main(void)
{
stackADT stack;
int i = 0;
stack = NewStack();
PrintStack(stack);
for(i = 0; i < 60; i++)
{
Push(stack,i);
}
PrintStack(stack);
FreeStack(stack);
_CrtDumpMemoryLeaks();
return 0;
}
The _CrtDumpMemoryLeaks() function is for Visual Studio and it indicates if there is a memory leak. Apparently I've sealed off any leaks when calling the FreeStack(stackADT stack) function. However, the stack pointer still holds a memory address, which is the issue because the FreeStack function is supposed to free the memory pointed to by the stack variable and set it equal to NULL. This occurs within the function, but when I return to the main function during debugging, I see the memory address still there. What is it I'm missing here? If I'm able to release the memory, why can't I remove the dangling pointer?
You pass the stack to the function by value, instead of by address, modify the function to receive (stackADT *) and you'll be good to go.
Clarification: as Christian commented, the function call, and the use of stack will have to be changed as well of course (since now it's a pointer to pointer...)
You're passing that stackADT object (pointer) by value in your pop method:
void FreeStack(stackADT stack)
So stack refers to the local copy of that pointer. When you set that pointer = NULL, you modify it only within FreeStack. The main method has its own copy of said pointer, not pointing to NULL.