Remove items less than 10 from the stack - c

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 );

Related

Heap buffer overflow in stack function

So i created a program that makes a stack and all of its operations, using a structure called stack.
Structure:
typedef struct {
int *v; /* contents of the stack */
int cap; /* capacity of v, i.e. how many elements can fit in v */
int sz; /* number of elements currently stored in v */
} stack;
The program works fine but when i use fsantize it says that there is a buffer overflow on the heap in the Push function and i dont understand why because ive reallocated the bytes that i needed and freed the ones that i didnt need.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int *v; /* contents of the stack */
int cap; /* capacity of v, i.e. how many elements can fit in v */
int sz; /* number of elements currently stored in v */
} stack;
void init(stack * s)
{
s->v = (int*) calloc(4,sizeof(int));
s->cap = 4;
s->sz = -1;
}
int is_empty(stack * s)
{
if (s->sz == -1)
return 1;
else
return 0;
}
void push(stack * s, int e)
{
if (s->sz+1 <= s->cap)
{
s->sz++;
s->v[s->sz] = e;
}
else
{
int *nv;
s->cap++;
s->sz++;
nv = (int*) realloc(s->v, sizeof(int)*s->cap);
free(s->v);
s->v = nv;
s->v[s->sz] = e;
}
}
int pop(stack * s)
{
if (is_empty(s) == 0)
{
int top = s->v[s->sz];
s->sz--;
return top;
}
else
{
printf("Impossible the stack isn't empty\n");
return 0;
}
}
void destroy(stack * s)
{
//frees the stack bytes that were allocated
free(s->v);
free(s);
}
int main()
{
int i;
stack *pilha = (stack*) malloc(sizeof(stack));
init(pilha);
if (is_empty(pilha) == 1)
printf("The stack is empty\n");
pop(pilha);
for (i = 0; i<=4;i++)
push(pilha,i);
push(pilha,5);
printf("The top is:%d\n",pilha->v[pilha->sz]);
if (is_empty(pilha) == 0)
printf("The stack isn't empty\n");
destroy(pilha);
return 0;
}
This line:
if (s->sz+1 <= s->cap)
contains a logical error: if s->sz+1 == s->cap you need more space. For example, if s->cap is 4 you only have space for 4 elements (indexes from 0 to 3), but in the case of s->sz == 3 you enter the if and the result is:
s->sz++; // 4
s->v[s->sz] = e; // s->v[4] overflow!
The right way to check would be if (s->sz+1 < s->cap), or even incrementing the value first:
s->sz++;
if (s->sz < s->cap) {
// ...
This:
nv = (int*) realloc(s->v, sizeof(int)*s->cap);
free(s->v);
s->v = nv;
Is also wrong. First, you are assuming that realloc() allocates new memory and that you need to free() the old buffer: you don't, realloc() does that for you if needed. Secondly, you are assuming that realloc() does not fail (as you are doing anywhere else in your code, malloc(), calloc(), etc). Third, you are casting the return value (again as you are doing anywhere else in your code), which you shouldn't (see Do I cast the result of malloc?).
What you should do instead is:
nv = realloc(s->v, sizeof(int)*s->cap);
if (nv == NULL) {
// Handle error, abort execution.
}
s->v = nv;
The check if (nv == NULL) should be done after every single call of malloc(), realloc() or calloc().
The function push is invalid.
This condition in the if statement
if (s->sz+1 <= s->cap)
can be a reason of undefined behavior. Let's assume for simplicity that s->cap is equal to 1. So you may push only one element without resizing the dynamically allocated array. So after pushing a new value s->sz will be equal to 0. And you may not push one more a new value without resizing the array. However the condition in the if statement will evaluate to true and you will write to memory outside the allocated array.
Also this code snippet
nv = (int*) realloc(s->v, sizeof(int)*s->cap);
free(s->v);
is invalid. In the case when the call of realloc was successful the memory pointed to by s->v was freed (or rreused). So the call of free again will invoke undefined behavior. That is whether there will be an attempt to free the already reallocated memory or the new allocated memory will be freed.
The function push can be defined for example the following way
int push( stack *s, int e )
{
int success = 0;
if ( ( success = s->sz+1 < s->cap ) )
{
s->v[++s->sz] = e;
}
else
{
int *nv = realloc( s->v, sizeof( int ) * ( s->cap + 1 ) );
success = nv != NULL;
if ( success )
{
s->v = nv;
++s->cap;
s->v[++s->sz] = e;
}
}
return success;
}
But in any case it would be better to set the initial value to the data member sz to 0. In this case the data member would reflect the current size of the stack.
The return value of the function pop is ambiguous. The returned value 0 can be a valid value stored in the stack. Also the function shall shall not issue any message. It is the caller of the function that will decide whether to issue a message if any or not.
Also there is no need to allocate the object itself of the type stack dynamically. It can have the automatic storage duration and be a local variable.
And it is much better when the function that initialize the stack also has a second parameter that allows to specify the capacity of the created stack instead of using the magic number 4.
Below there is a demonstrative program that shows how the stack and its functions can be defined.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int *v; /* contents of the stack */
size_t cap; /* capacity of v, i.e. how many elements can fit in v */
size_t sz; /* number of elements currently stored in v */
} stack;
int init( stack * s, size_t capacity )
{
s->sz = 0;
s->cap = 0;
s->v = calloc( capacity, sizeof( int ) );
int success = s->v != NULL;
if ( success )
{
s->cap = capacity;;
}
return success;
}
int is_empty( const stack *s )
{
return s->sz == 0;
}
int push( stack *s, int e )
{
int success = 0;
if ( ( success = s->sz < s->cap ) )
{
s->v[s->sz++] = e;
}
else
{
int *nv = realloc( s->v, sizeof( int ) * ( s->cap + 1 ) );
success = nv != NULL;
if ( success )
{
s->v = nv;
++s->cap;
s->v[s->sz++] = e;
}
}
return success;
}
int pop( stack *s, int *value )
{
int success = !is_empty( s );
if ( success )
{
*value = s->v[--s->sz];
}
return success;
}
void destroy( stack *s )
{
free( s->v );
s->v = NULL;
s->cap = 0;
s->sz = 0;
}
int main( void )
{
stack pilha;
init( &pilha, 4 );
if ( is_empty( &pilha ) )
{
printf( "The stack is empty\n" );
}
const int N = 5;
for ( int i = 0; i < 5; i++ )
{
push( &pilha, i );
}
push( &pilha, N );
while ( ! is_empty( &pilha ) )
{
int value;
pop( &pilha, &value );
printf( "the current top value is %d\n", value );
}
destroy( &pilha );
if ( is_empty( &pilha ) )
{
printf("The stack isn't empty\n");
}
return 0;
}
The program output is
The stack is empty
the current top value is 5
the current top value is 4
the current top value is 3
the current top value is 2
the current top value is 1
the current top value is 0
The stack isn't empty

C, Global Variable change isn't kept outside the function

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.

Loss of values in array in struct after function execution

I am working on a c code that holds a structure that hosts some values which I call range.
My purpose is to use this so called range dynamically (holding different amount of data at every execution). I am now provisionally using the # define comp instead. This so called range gets updated every time I call my update_range though the use of s1 structure (and memory allocations).
What I found weird is that when I introduced a "show_range" function to output the actual values inside/outside the update function I realized that I loose the first two values.
Here is the code.
Any suggestions on that?
Thanks in advance!
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
#include <string.h>
#include <complex.h>
#define comp 1024
// struct holding a complex-valued range
struct range {
int dimensions; /* number of dimensions */
int* size; /* array holding number of points per dimension */
complex double* values; /* array holding complex valued */
int components; /* number of components that will change on any execution*/
};
// parameters to use in function
struct s1 {
int tag;
struct range* range;
};
int update_range(struct s1* arg);
int show_range(struct range* argrange, char* message);
int copy_range(struct range* in, struct range* out);
int main(void) {
int ret = 0;
struct s1 s1;
s1.tag = 0;
s1.range = malloc(sizeof(struct range));
update_range(&s1);
show_range(s1.range, "s1.range inside main function");
return ret;
}
////////////////////////////////////////////
int update_range(struct s1* arg) {
int ret = 0;
int i;
struct range range;
range.dimensions = 1;
range.size = malloc(range.dimensions * sizeof(int));
range.components = comp;
range.size[0] = range.components; // unidimensional case
range.values = malloc(range.components * sizeof(complex double));
for (i = 0; i < range.components; i++) {
range.values[i] = (i + 1) + I * (i + 1);
}
show_range(&range, "range inside update_range function");
arg->range->size =
malloc(range.dimensions * sizeof(int)); // size was unknown before
arg->range->values =
malloc(comp * sizeof(complex double)); // amount of values was unknown
copy_range(&range, arg->range);
show_range(arg->range, "arg->range inside update_range function");
if (range.size)
free(range.size);
range.size = NULL;
if (range.values)
free(range.values);
range.values = NULL;
return ret;
}
////////////////////////////////////////////
// Show parameters (10 first values)
int show_range(struct range* argrange, char* message) {
int ret = 0;
vint i;
printf(" ******************************\n");
printf(" range in %s \n", message);
printf(" arg.dimensions=%d \n", argrange->dimensions);
printf(" arg.size[0]=%d \n", argrange->size[0]);
printf(" argrange.components=%d \n", argrange->components);
printf(" first 10 {Re} values: \n");
for (i = 0; i < 10; i++) {
printf(" argrange.values[%d]=%f\n", i, creal(argrange->values[i]));
}
printf("\n");
return ret;
}
////////////////////////////////////////////
// copy range
int copy_range(struct range* in, struct range* out) {
int ret = 0;
if (in == NULL) {
fprintf(stderr, "error: in points to NULL (%s:%d)\n", __FILE__,
__LINE__);
ret = -1;
goto cleanup;
}
if (out == NULL) {
fprintf(stderr, "error: out points to NULL (%s:%d)\n", __FILE__,
__LINE__);
ret = -1;
goto cleanup;
}
out->dimensions = in->dimensions;
out->size = in->size;
out->values = in->values;
out->components = in->components;
cleanup:
return ret;
}
Your copy_range function is broken, because it copy only pointer to size and values and not the memory. After you call free(range.size); and free(range.values); you are deleting mamory also from original object but without setting its pointers back to NULL.
After calling update_range, s1.range has non NULL pointers in size and values, but they are pointing to deleted memory.
You are experiencing undefined behaviour (UB) due to accessing freed memory. Your copy_range() function only does a shallow copy of the two pointer fields so when you run free(range->size) you make arg->range->size invalid.
You should make copy_range() a deep copy by allocating and copying the pointer contents like:
out->size = malloc(in->dimensions * sizeof(int));
memcpy(out->size, in->size, in->dimensions * sizeof(int));
out->values = malloc(in->components * sizeof(complex double));
memcpy(out->values , in->values, in->components * sizeof(complex double));
There are not 10 items to print, so the lines:
printf(" first 10 {Re} values: \n");
for (i = 0; i < 10; i++) {
printf(" argrange.values[%d]=%f\n", i, creal(argrange->values[i]));
}
Will be printing from random memory.
a much better method would be:
printf(" first %d {Re} values: \n", min(argrange.components,10));
for (i = 0; i < argrange.components; i++) {
printf(" argrange.values[%d]=%f\n", i, creal(argrange->values[i]));
}
The above is just one of many problems with the code.
I would suggest executing the code using a debugger to get the full story.
as it is, the code has some massive memory leaks due mostly
to overlaying malloc'd memory pointers.
for instance as in the following:
arg->range->size =
malloc(range.dimensions * sizeof(int)); // size was unknown before
arg->range->values =
malloc(comp * sizeof(complex double)); // amount of values was unknown

Implementation of a stack using a linked list C

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.

Freeing C Stack & Removing Dangling Pointers

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.

Resources