Stack by pointers in C working except at stack underflow - c

I implemented stack by using pointers. It is compiling and working but it doesn't underflow when the stack is empty. It gives me some garbage value. I think the problem is something in the create_stack function. I am not getting segfaults no matter how much data is popped from the stack which is odd.
Can anyone help?
Here is my complete implementation of stack by pointers.
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
enum action {PUSH = 1, POP, TOP, QUIT};
typedef struct node
{
int data;
struct node *lower;
}stack_node;
void clear_screen(void)
{
system("cls");
}
static enum action get_user_action(void)
{
int choice = 0;
do
{
clear_screen();
printf("%d Push data\n"
"%d Pop Data\n"
"%d See the top of the stack\n"
"%d Exit\n\n"
"Enter your choice -> ", PUSH, POP, TOP, QUIT);
scanf("%d", &choice);
} while (choice != PUSH && choice != POP && choice != TOP && choice != QUIT);
return (enum action) choice;
}
void create_stack(stack_node **top, int *status)
{
*top = malloc(sizeof(stack_node));
*status = PUSH - 1;
if (*top == NULL){
*status = PUSH;
}
}
void push(stack_node **top_stack, int *status, int data)
{
*status = PUSH - 1;
stack_node *node = malloc(sizeof(node));
if (node == NULL)
{
*status = PUSH;
return;
}
node -> data = data;
if (*top_stack == NULL){
node -> lower = NULL;
}
else{
node -> lower = *top_stack;
}
*top_stack = node;
}
int pop(stack_node **top_stack, int *status)
{
*status = PUSH - 1;
if (*top_stack == NULL){
*status = POP;
return -1;
}
stack_node *node = *top_stack;
int data = node -> data;
*top_stack = node -> lower;
free(node);
return data;
}
int see_top(stack_node **top_stack, int *status)
{
*status = PUSH - 1;
if (*top_stack == NULL){
*status = POP;
return -1;
}
return (*top_stack) -> data;
}
int main(void)
{
enum action choice;
int status;
stack_node *top = NULL;
create_stack(&top, &status);
if (status == PUSH)
{
printf("Not enough memory\n");
return 1;
}
while ((choice = get_user_action()) != QUIT)
{
clear_screen();
int data;
switch (choice)
{
case PUSH:
printf("Enter data to be pushed -> ");
scanf("%d", &data);
push(&top, &status, data);
if (status == PUSH){
printf("Not enough memory\n");
}
break;
case POP:
data = pop(&top, &status);
if (status == POP){
printf("Stack underflow\n");
}
else{
printf("The data is %d\n", data);
}
break;
case TOP:
data = see_top(&top, &status);
switch (status)
{
case POP:
printf("Nothing in the stack\n");
break;
default:
printf("The data at top is %d\n", data);
}
break;
default:
assert(!"You should not have reached this.");
}
getchar();
getchar();
}
}

When you create the stack you allocate space for a node -- and don't fill it with anything. So after the call to create_stack() you have a blank node on your stack already. I guess you don't want that, doing just
void create_stack(stack_node **top, int *status)
{
*top = NULL;
*status = PUSH -1;
}
will work just fine. You allocate the memory during the push() call anyway any you check for top_stack == NULL during the functions. Alternatively you could have a flag in your stack node to indicate it's not used (then during push you'd not create a new one) but that's too complex for what you want here.

In create_stack() function you allocate memory and doesn't initialize it to any thing. Its data and lower part remain garbage.
When you pop elements if (*top_stack == NULL) condition never becomes true (becomes garbage value was not null) and so after remove all node it returns garbage value.

Related

Implementation of stack using linked list

I am getting a "Function should return a value" error at the 91st line of the code in Turbo C++, please help me as I have to submit my project, I know that Turbo C++ is a very old compiler but that's what our University Teacher recommends so I cant do nothing in that
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#include <stdio.h>
#include <conio.h>
struct stack
{
int element;
struct stack *next;
} * top;
void push(int);
int pop();
void display();
void main()
{
int num1, num2, choice;
while (1)
{
clrscr();
printf("Select a choice from the following:");
printf("\n[1] Push an element into the stack");
printf("\n[2] Pop out an element from the stack");
printf("\n[3] Display the stack elements");
printf("\n[4] Exit\n");
printf("\n\tYour choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
{
printf("\n\tEnter the element to be pushed into the stack: ");
scanf("%d", &num1);
push(num1);
break;
}
case 2:
{
num2 = pop();
printf("\n\t%d element popped out of the stack\n\t", num2);
getch();
break;
}
case 3:
{
display();
getch();
break;
}
case 4:
exit(1);
break;
default:
printf("\nInvalid choice !\n");
break;
}
}
}
void push(int value)
{
struct stack *ptr;
ptr = (struct stack *)malloc(sizeof(struct stack));
ptr->element = value;
ptr->next = top;
top = ptr;
return;
}
int pop()
{
if (top == NULL)
{
printf("\n\STACK is Empty.");
getch();
exit(1);
}
else
{
int temp = top->element;
top = top->next;
return (temp);
}
}
void display()
{
struct stack *ptr1 = NULL;
ptr1 = top;
printf("\nThe various stack elements are:\n");
while (ptr1 != NULL)
{
printf("%d\t", ptr1->element);
ptr1 = ptr1->next;
}
}
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
The compiler is complaining because you don’t have a return statement outside of the if statement. Even though you call exit in the if branch, syntactically speaking that’s just another function call; structurally, the compiler sees a pathway where you reach the closing } of the function body without a return statement.
You want to make sure the return is reachable outside the body of the if-else statement, and the best way to do it is take the else branch out of the statement entirely:
int pop( void )
{
int temp;
if ( !top )
{
fputs( "Stack is empty", stderr );
exit( 1 );
}
temp = top->element;
top = top->next;
return temp;
}
you can change your pop function as below ( assuming you are not storing -1 as an element in the stack)
int pop()
{
if (top == NULL)
{
printf("\n\STACK is Empty.");
getch();
return -1;// or other invalid value which indicates stack empty
}
else
{
int temp = top->element;
top = top->next;
return (temp);
}
}
and at the place you are calling modify as following
case 2:
{
num2 = pop();
if(num2 != -1) {
printf("\n\t%d element popped out of the stack\n\t", num2);
getch();
}else{
printf("Stack is Empty\n");
exit(1);
}
break;
}

Printing and Deleting queue in C

I'm trying to write a program that enqueue, dequeue, delete a chosen number and print the list. I have problems with the dequeue that i think is because of the menu part when you write a number, I've tried to fix it but the it removes the last number and not the first. The print shows the wrong number and when I tried to solve that problem I got the same problem as I had in dequeue. It's sometinhg wrong in delete but i cant figure it out.
I appreciate all the help i can get
edit:
I've changed it a lot and now everything else works except delete. I want delete to find the number i enter and delete it.
queue.c
#include <stdio.h>
#include <stdlib.h>
#include<conio.h>
struct node
{
int info;
struct node *ptr;
int next;
}*first, *last, *temp, *first1;
void enq(int data);
void deq();
void empty();
void display();
void create();
void delete_queue();
int count = 0;
void main()
{
int no, ch;
printf("\n 1 - Enqueue");
printf("\n 2 - Dequeue");
printf("\n 3 - Delete");
printf("\n 4 - Display");
printf("\n 5 - Exit");
create();
while (1)
{
printf("\n Enter choice : ");
scanf_s("%d", &ch);
switch (ch)
{
case 1:
printf("Enter data : ");
scanf_s("%d", &no);
enq(no);
break;
case 2:
deq();
break;
case 3:
printf("Enter data : ");
scanf_s("%d", &no);
delete_queue(no);
case 4:
display();
break;
case 5:
exit(0);
default:
printf("Wrong choice, Please enter correct choice ");
break;
}
}
}
void create()
{
first = last = NULL;
}
void enq(int data)
{
if (last == NULL)
{
last = (struct node *)malloc(1 * sizeof(struct node));
last->ptr = NULL;
last->info = data;
first = last;
}
else
{
temp = (struct node *)malloc(1 * sizeof(struct node));
last->ptr = temp;
temp->info = data;
temp->ptr = NULL;
last = temp;
}
count++;
}
void display()
{
first1 = first;
if ((first1 == NULL) && (last == NULL))
{
printf("Queue is empty");
return;
}
while (first1 != last)
{
printf("%d ", first1->info);
first1 = first1->ptr;
}
if (first1 == last)
printf("%d", first1->info);
}
void deq()
{
first1 = first;
if (first1 == NULL)
{
printf("\n Error: Trying to display elements from empty queue");
return;
}
else
if (first1->ptr != NULL)
{
first1 = first1->ptr;
printf("\n Dequed value : %d", first->info);
free(first);
first = first1;
}
else
{
printf("\n Dequed value : %d", first->info);
free(first);
first = NULL;
last = NULL;
}
count--;
}
void delete_queue()
{
int retval = -1;
if (first)
{
struct node *temp = first;
first = first->next;
if (!first) { last = first; }
retval = temp->next;
free(temp);
}
return retval;
}
void empty()
{
if ((first == NULL) && (last == NULL))
printf("\n Queue empty");
else
printf("Queue not empty");
}
Let me start with a few points of advice about design and style:
I do not recommend this:
typedef struct node {
int data;
struct node *next;
} node;
you are typedefing struct node to node. while it is not illegal, it is confusing. I would recommend
typedef struct _node {
int data;
struct _node *next;
} node;
Additionally, I do not recommend use of global variable with static storage class to keep track of your queue, instead you should create a queue in your main. Use global variables only when you have compelling reasons to do so.
Do remember that when you get rid of your global variable, you will need to rewrite your enqueue dequeue delete etc... functions to take in a queue_c * as parameter (because it wont have access to queueref any more)
Now for the reason that your code is not working properly and #Weather Vane alluded to:
you have a big problem in your delete function.
int delete(int data)
{
int result = 0;
node *curr_ptr; //pointer just created and not initialized
node *prev_ptr; //not initialized
node *temp_ptr; //not initialized
while (curr_ptr != NULL)
//curr_ptr was just created, where is it pointing? fatal error here
{
//inside this block lets imagine curr_ptr is pointing to a valid
//node in the global queue
if (curr_ptr->data == data)
{
result = 1;
if (curr_ptr->next != NULL)
{
temp_ptr = curr_ptr;
//both pointers point to the same thing
destroy_node(temp_ptr);
//now you just destroyed both nodes
prev_ptr->next = curr_ptr->next;
//the first time this block runs prev_ptr is uninitialized
//so prev_ptr->next will most likely seg fault
//this happens for example if you call this function
//for the first time with a long queue
}
else
{
temp_ptr = curr_ptr;
queueref.last = prev_ptr;
prev_ptr->next = NULL;
destroy_node(temp_ptr);
//again you are destroying both curr_ptr and temp_ptr
}
}
curr_ptr = curr_ptr->next;
prev_ptr = prev_ptr->next;
return result;
}
}
Perhaps it would be better if you think edge cases very carefully and rethink some of the logic from scratch. (test edge cases as you go)

Incorrect data is being pushed into stack implemented using pointers

I have implemented stack using pointers. I have been trying to generalize it for use with arbitrary data type. I have tried but cannot figure out the reason incorrect data is being pushed onto the stack.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum action {START, PUSH, POP, TOP, LENGTH, QUIT, END};
enum status {SUCCESS, FAILURE};
typedef struct node {
void *data;
struct node *lower;
} stack_node;
typedef struct stack {
size_t elem_size;
size_t stack_size;
stack_node *top;
} stack_struct;
void clear_screen(void)
{
system("cls");
}
static enum action get_user_action(void)
{
int choice = START;
do {
clear_screen();
printf("%d Push data\n"
"%d Pop Data\n"
"%d See the top of the stack\n"
"%d See the length of the stack\n"
"%d Exit\n\n"
"Enter your choice -> ", PUSH, POP, TOP, LENGTH, QUIT);
scanf("%d", &choice);
} while (!(START < choice && choice < END));
return (enum action) choice;
}
enum status stack_create(stack_struct **stack, size_t elem_size)
{
(**stack).elem_size = elem_size;
(**stack).stack_size = 0;
(**stack).top = NULL;
return SUCCESS;
}
enum status push(stack_struct **stack, void *data)
{
stack_node *node = malloc(sizeof(node));
if (node == NULL) {
return FAILURE;
}
node->data = malloc(sizeof((**stack).elem_size));
if (node->data == NULL) {
return FAILURE;
}
memcpy(node->data, data, (**stack).elem_size);
if ((**stack).top == NULL) {
node->lower = NULL;
} else {
node->lower = (**stack).top;
}
(**stack).top = node;
(**stack).stack_size += 1;
return SUCCESS;
}
enum status pop(stack_struct *stack, void *data)
{
if (stack->top == NULL) {
return FAILURE;
}
stack_node *node = stack->top;
memcpy(data, node->data, stack->elem_size);
stack->top = node->lower;
free(node->data);
free(node);
stack->stack_size -= 1;
return SUCCESS;
}
enum status peek(stack_struct *stack, void *data)
{
if (stack->top == NULL) {
return FAILURE;
}
memcpy(data, stack->top->data, stack->elem_size);
return SUCCESS;
}
void stack_delete(stack_struct *stack)
{
while (stack->top != NULL)
{
stack_node *node = stack->top;
stack->top = stack->top->lower;
free(node->data);
free(node);
}
}
int main(void)
{
enum action choice;
stack_struct *stack = malloc(sizeof(stack_struct));
if (stack == NULL)
{
printf("Not enough memory\n");
return 1;
}
stack_create(&stack, sizeof(int));
while ((choice = get_user_action()) != QUIT) {
clear_screen();
int data;
switch (choice) {
case PUSH:
printf("Enter data to be pushed -> ");
scanf("%d", &data);
if (push(&stack, &data) == SUCCESS){
printf("%d pushed onto the stack", (int)stack->top->data);
} else {
printf("Not enough memory\n");
}
break;
case POP:
if (pop(stack, &data) == SUCCESS){
printf("The data is %d\n", data);
} else {
printf("Stack underflow\n");
}
break;
case TOP:
if (peek(stack, &data) == SUCCESS){
printf("The data at top is %d\n", data);
} else {
printf("Nothing in the stack\n");
}
break;
case LENGTH:
printf("Length is %d\n", stack->stack_size);
break;
default:
assert(!"You should not have reached this.\n");
}
stack_delete(stack);
getchar();
getchar();
}
}
I push 234 and get a garbage value.
Update 1
I have a working copy of stack using pointers. It isn't for arbitrary data types but only for int. It can be viewed on codereview where I got the idea to make it for arbitrary data.
Update 2
After p0w pointed out that the printf in the main was incorrect I correct that. I also changed the pop, peek and stack_delete function so that pointer to pointer to struct is passed.
printf shows that correct data is being passed but pop and peek don't think so.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum action {START, PUSH, POP, TOP, LENGTH, QUIT, END};
enum status {SUCCESS, FAILURE};
typedef struct node {
void *data;
struct node *lower;
} stack_node;
typedef struct stack {
size_t elem_size;
size_t stack_size;
stack_node *top;
} stack_struct;
void clear_screen(void)
{
system("cls");
}
static enum action get_user_action(void)
{
int choice = START;
do {
clear_screen();
printf("%d Push data\n"
"%d Pop Data\n"
"%d See the top of the stack\n"
"%d See the length of the stack\n"
"%d Exit\n\n"
"Enter your choice -> ", PUSH, POP, TOP, LENGTH, QUIT);
scanf("%d", &choice);
} while (!(START < choice && choice < END));
return (enum action) choice;
}
enum status stack_create(stack_struct **stack, size_t elem_size)
{
(**stack).elem_size = elem_size;
(**stack).stack_size = 0;
(**stack).top = NULL;
return SUCCESS;
}
enum status push(stack_struct **stack, void *data)
{
stack_node *node = malloc(sizeof(node));
if (node == NULL) {
return FAILURE;
}
node->data = malloc(sizeof((**stack).elem_size));
if (node->data == NULL) {
return FAILURE;
}
memcpy(node->data, data, (**stack).elem_size);
if ((**stack).top == NULL) {
node->lower = NULL;
} else {
node->lower = (**stack).top;
}
(**stack).top = node;
(**stack).stack_size += 1;
return SUCCESS;
}
enum status pop(stack_struct **stack, void *data)
{
if ((**stack).top == NULL) {
return FAILURE;
}
stack_node *node = (**stack).top;
memcpy(data, node->data, (**stack).elem_size);
(**stack).top = node->lower;
node->lower = NULL;
free(node->data);
free(node);
(**stack).stack_size -= 1;
return SUCCESS;
}
enum status peek(stack_struct **stack, void *data)
{
if ((**stack).top == NULL) {
return FAILURE;
}
memcpy(data, (**stack).top->data, (**stack).elem_size);
return SUCCESS;
}
void stack_delete(stack_struct **stack)
{
while ((**stack).top != NULL)
{
stack_node *node = (**stack).top;
(**stack).top = (**stack).top->lower;
free(node->data);
free(node);
}
}
int main(void)
{
enum action choice;
stack_struct *stack = malloc(sizeof(stack_struct));
if (stack == NULL)
{
printf("Not enough memory\n");
return 1;
}
stack_create(&stack, sizeof(int));
while ((choice = get_user_action()) != QUIT) {
clear_screen();
int data;
switch (choice) {
case PUSH:
printf("Enter data to be pushed -> ");
scanf("%d", &data);
if (push(&stack, &data) == SUCCESS){
printf("%d pushed onto the stack\n", *(int *)stack->top->data);
printf("%u is top of stack", stack->top);
} else {
printf("Not enough memory\n");
}
break;
case POP:
if (pop(&stack, &data) == SUCCESS){
printf("The data is %d\n", data);
} else {
printf("Stack underflow\n");
}
break;
case TOP:
if (peek(&stack, &data) == SUCCESS){
printf("The data at top is %d\n", data);
} else {
printf("Nothing in the stack\n");
}
break;
case LENGTH:
printf("Length is %d\n", stack->stack_size);
break;
default:
assert(!"You should not have reached this.\n");
}
stack_delete(&stack);
getchar();
getchar();
}
}
Your struture data is void * so fix printf
printf("%d pushed onto the stack", *(int *)stack->top->data);
However, there seems to be other problems too for other stack operations.
Also if you're planning for making it as a generic Stack, why %d in printf ?
This you might need to re-visit.
In addtion to the points mentioned by P0W and me, there is bug in your code which is leading to a crash on VS2010 but not in GCC.
While creating the stack_node object in push function dynamically you're passing the sizeof(node) where node is a pointer of stack_node instead you should've passed sizeof(stack_node).
The amount of memory malloc allocates in both the cases is different.
In the first one you get 4 bytes(beacuse of size of pointer) and in the second one you get 8 bytes (because of size of stack_node).
In this case you don't get to access the second member of stack_node object which is struct node *lower. Also, this might need to undefined behavior as you're accessing the memory which is not allocated.
Finally at the statement free(node) it crashes.
I don't know the exact reason as to why this is happening and also i don't know how free works behind the scenes.
I would like to know the reason in this case.

Passing pointers between functions in an implementation of linked list

The problem was solved. A guy gave it in comments. The problem was that I was using %d to read in a short int. I should have used %hd or I should have used an `int'.
I tried to create a program of singly-linked list using only local variables. I was able to make a working program by using global variables.
The program with local variables compiles but it crashes when I try to traverse the linked list.
I have absolutely no idea what is wrong with the implementation with local variables. What is the problem present in the Implementation with local variables?
ABOUT THE STRUCTURE OF THE PROGRAMS:
I understand that the programs are big so I'll put in something about structure of the program.
The program is structured as a menu driven program. So the initial calls to functions are in main() function
There are 3 options in main() menu - exit, traverse and insertion
Exit returns 0 to exit program while other 2 do function calls
Insertion function itself is arranged as menu-driven program.
It has 3 options - return , insert_begin and insert_end. The last 2 are function calls.
I know there are memory leaks as I haven't freed any memory but I will take care of that after I can understand the problem in the current program.
//WORKING IMPLEMENTATION USING GLOBAL VARIABLE
#include<stdio.h>
#include<stdlib.h>
#define MIN 0
#define MAX 2
#define INS_MIN 0
#define INS_MAX 2
typedef struct node
{
int data;
struct node *next;
}sll_node;
sll_node *start = NULL;
void intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Exit");
printf("\n\t01 Traverse the list");
printf("\n\t02 Insertion into the list");
}
void insert_begin()
{
sll_node *node = malloc(sizeof(sll_node));
if(node == NULL)
{
printf("\n\tNot enough menory");
exit(-1);
}
int data;
printf("\n\tData to be entered: ");
scanf("%d", &data);
node->data = data;
node-> next = start;
start = node;
}
void insert_end()
{
sll_node *node = malloc(sizeof(sll_node));
if(node == NULL)
{
printf("\n\tNot enough menory");
exit(-2);
}
if(start == NULL)
insert_begin();
else
{
printf("\n\tData to be entered: ");
scanf("%d", &(node->data));
node-> next = NULL;
sll_node *node2;
for(node2 = start; node2->next != NULL; node2 = node2->next)
;
node2->next = node;
}
}
void insert_intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Insertion Done");
printf("\n\t01 Insert at beginning");
printf("\n\t02 Insert at end");
}
void insertion()
{
short choice;
while(1)
{
choice = -1;
while(choice < INS_MIN || choice > INS_MAX)
{
insert_intro();
printf("\n\n\tEnter your chocie: ");
scanf("%d", &choice);
}
switch(choice)
{
case 0:
return;
case 1:
insert_begin();
break;
case 2:
insert_end();
break;
}
}
}
void traverse()
{
if(start == NULL)
printf("\n\n\tLinked list is empty");
else
{
printf("\n\n\t");
for(sll_node *node = start; node != NULL; node = node->next)
printf("%d ", node->data);
}
getch();
}
int main()
{
short choice;
while(1)
{
choice = -1;
while(choice < MIN || choice > MAX)
{
intro();
printf("\n\n\tEnter your choice: ");
scanf("%d", &choice);
}
switch(choice)
{
case 0:
return 0;
case 1:
traverse();
break;
case 2:
insertion();
break;
}
}
return 0;
}
//COMPILES BUT CRASHES - Same program but with local variable start and variable passing between functions
#include<stdio.h>
#include<stdlib.h>
#define MIN 0
#define MAX 2
#define INS_MIN 0
#define INS_MAX 2
typedef struct node
{
int data;
struct node *next;
}sll_node;
void intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Exit");
printf("\n\t01 Traverse the list");
printf("\n\t02 Insertion into the list");
}
sll_node* insert_begin(sll_node *start)
{
sll_node *node = malloc(sizeof(sll_node));
if(node == NULL)
{
printf("\n\tNot enough menory");
exit(-1);
}
int data;
printf("\n\tData to be entered: ");
scanf("%d", &data);
node->data = data;
node-> next = start;
return node;
}
sll_node* insert_end(sll_node *start)
{
sll_node *node = malloc(sizeof(sll_node));
if(node == NULL)
{
printf("\n\tNot enough menory");
exit(-2);
}
if(start == NULL)
start = insert_begin(start);
else
{
printf("\n\tData to be entered: ");
scanf("%d", &(node->data));
node-> next = NULL;
sll_node *node2;
for(node2 = start; node2->next != NULL; node2 = node2->next)
;
node2->next = node;
}
return start;
}
void insert_intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Insertion Done");
printf("\n\t01 Insert at beginning");
printf("\n\t02 Insert at end");
}
sll_node* insertion(sll_node *start)
{
short choice;
while(1)
{
choice = -1;
while(choice < INS_MIN || choice > INS_MAX)
{
insert_intro();
printf("\n\n\tEnter your chocie: ");
scanf("%d", &choice);
}
switch(choice)
{
case 0:
return start;
case 1:
start = insert_begin(start);
break;
case 2:
start = insert_end(start);
break;
}
}
}
void traverse(sll_node *start)
{
if(start == NULL)
printf("\n\n\tLinked list is empty");
else
{
printf("\n\n\t");
for(sll_node *node = start; node != NULL; node = node->next)
printf("%d ", node->data);
}
getch();
}
int main()
{
sll_node *start = NULL;
short choice;
while(1)
{
choice = -1;
while(choice < MIN || choice > MAX)
{
intro();
printf("\n\n\tEnter your choice: ");
scanf("%d", &choice);
}
switch(choice)
{
case 0:
return 0;
case 1:
traverse(start);
break;
case 2:
start = insertion(start);
break;
}
}
return 0;
}
You are not returning anything from insertion() function when item is added to a list. So linked list may not get constructed properly.
Probably, you should return start only when its added at the beginning, otherwise start in main() will not point to head of the list.
sll_node* insertion(sll_node *start)
{
...
switch(choice)
{
case 0:
return start;
case 1:
start = insert_begin(start);
return start; //<----- return node
break;
case 2:
start = insert_end(start);
break;
}
...
}
Change short choice to int choice.
Why does this make a difference?
Short answer is that printf("%d") expects an integer.
The long answer is "%d" describes the data type you are passing to printf as an integer (which is commonly 4 to 8 bytes), and you're giving it a datatype of short - which is commonly 2 bytes long. When your program reads the input and stores it at the pointer, &choice, it writes 4 bytes starting at that address (but only 2 were reserved). This causes a segmentation fault and will crash your program.
Here's a list to some printf documentation. You'll notice that to pass a short to printf you would write %hd instead of %d
When i compile your code on my computer, it works, but i changed "short choice" to "int choice", because scanf("%d", &choice) takes 4 bytes to write on, and when choice is short it crashes, because short has only 2 bytes, therefore stack corruption will occur, my be on your computer this corruption damage the "start" pointer.
About the crash. Change the argument start in both functions insert_begin and insert_end to sll_node ** start, and when assigning new value, use the expression *start = your-new-value. It is because you have to pass a pointer to the local variable start which is also pointer. You do not need to change function traverse.
About memory leaks, let me to point-out that when you call insert_begin from inside insert_end, the node created from insert_end is left unused. before exit() and the return in main() you should free the list.
Yes, sorry. There was another bug hard to see. It was at 2 lines where you read (choice).
short choice;
...
// It is ERROR to use "%d" with (short choice), because the stack will
// be overwritten with unsuspected results. The format specifier "%hd"
// say to compiler that (&choice) point to a short 16-bit integer,
// not 32-bit
scanf("%hd", &choice);
This is slightly different version, tested, without memory leaks.
//
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define MIN 0
#define MAX 2
#define INS_MIN 0
#define INS_MAX 2
typedef struct node
{
int data;
struct node *next;
} sll_node;
void clear_list(sll_node** start)
{
assert(start != NULL);
sll_node* node = *start;
while (node != NULL)
{
sll_node* element = node;
node = element->next;
free(element);
}
*start = NULL;
}
void intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Exit");
printf("\n\t01 Traverse the list");
printf("\n\t02 Insertion into the list");
}
void insert_begin(sll_node** pstart)
{
sll_node* node = (sll_node*)malloc(sizeof(sll_node));
if (node == NULL)
{
printf("\n\tNot enough menory");
clear_list(pstart);
exit(-1);
}
int data;
printf("\n\tData to be entered: ");
scanf_s("%d", &data);//scanf
node->data = data;
node->next = *pstart;
// update the local variable start passed from main to point just inserted node
*pstart = node;
}
void insert_end(sll_node** start)
{
assert(start != NULL);
if (*start == NULL)
{
insert_begin(start);
}
else
{
sll_node* node = (sll_node*)malloc(sizeof(sll_node));
if (node == NULL)
{
printf("\n\tNot enough menory");
clear_list(start);
exit(-2);
}
printf("\n\tData to be entered: ");
scanf("%d", &(node->data));
node->next = NULL;
sll_node* node2;
for(node2 = *start; node2->next != NULL; node2 = node2->next)
;
node2->next = node;
}
}
void insert_intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Insertion Done");
printf("\n\t01 Insert at beginning");
printf("\n\t02 Insert at end");
}
void insertion(sll_node** start)
{
short choice;
while(1)
{
choice = -1;
while(choice < INS_MIN || choice > INS_MAX)
{
insert_intro();
printf("\n\n\tEnter your chocie: ");
scanf("%hd", &choice);
}
switch(choice)
{
case 0:
return;
case 1:
insert_begin(start);
break;
case 2:
insert_end(start);
break;
}
}
}
void traverse(sll_node *start)
{
if (start == NULL)
printf("\n\n\tLinked list is empty");
else
{
printf("\n\n\t");
for(sll_node *node = start; node != NULL; node = node->next)
printf("%d ", node->data);
}
getch();
}
int main()
{
sll_node *start = NULL;
short choice;
while(1)
{
choice = -1;
while(choice < MIN || choice > MAX)
{
intro();
printf("\n\n\tEnter your choice: ");
scanf("%hd", &choice);
}
switch(choice)
{
case 0:
clear_list(&start);
return 0;
case 1:
traverse(start);
break;
case 2:
insertion(&start);
break;
}
}
return 0;
}
P.S. Very hard to edit! I'm new here and do not have enough experience. Wasted a lot of time to edit!

The functions && Linked List

I did my best with this program but I could not know where is the error?? I'll explain the program. In this program I should implement a stack of integers as linked list, using a global variable to point to the top of the stack by using these methods:
int push(int i);
push i on the stack, return 1 if successful else return 0.
int pop();
pop number from stack. if stack empty return 0;
I did create new method call int stackEmpty(); and the two method above.
Every time I run my program it's push the numbers into the stack but the pop doesn't work. Here my code:::
#include <stdio.h>
#include <stdlib.h>
typedef struct stack Stack;
struct stack
{
int number;
Stack *next;
};
Stack *top = NULL;
int push(int i);
int count();
int stackEmpty();
int pop();
int main()
{
char op;
int i, x;
printf("Welcome to my stack\n");
printf("p to pop, s to push, c to count, q to quit\n");
while (op != 'q')
{
scanf("%c", &op);
if (op == 'p')
{
x = pop();
if (x == 0)
{
printf("Stack is empty\n");
}
else
{
printf("%d popped\n", pop());
}
}
else if (op == 'c')
{
i = count();
printf("%d numbers on stack\n", i);
}
else if (op == 's')
{
printf("Enter number: ");
scanf("%d", &i);
x = push(i);
if (x == 1 || x == 2)
{
printf("%d puched :: state%d\n", i, x);
}
else
{
printf("faill %d\n", x);
}
}
else if (op == 'q')
{
return 0;
}
}
return 0;
}
int stackEmpty()
{
if (top == NULL)
{
return 1;
}
else
{
return 0;
}
}
int count()
{
int counter = 0;
if (top == NULL)
{
return counter;
}
else
{
while (top != NULL)
{
top = top->next;
counter++;
}
return counter;
}
}
int push(int i)
{
Stack *head;
Stack *next;
Stack *new;
int state;
int m;
head = top;
new = (Stack *) malloc(sizeof(Stack));
if (new == NULL)
{
state = 0;
} new->number = i;
m = stackEmpty();
if (m == 1)
{
head = new;
top = head;
head->next = NULL;
state = 1;
}
else
{
while (head != NULL)
{
if ((next = head->next) == NULL)
next = new;
next->next = NULL;
state = 2;
break;
head = top->next;
next = head->next;
}
top = head;
}
return state;
}
int pop()
{
Stack *head;
int state;
int m;
head = top;
if (head == NULL)
{
state = 0;
}
m = stackEmpty();
if (m == 1)
{
state = 0;
}
else
{
state = head->number;
top = head->next;
free(head);
}
return state;
}
Several problems:
top is your supposed head of the stack I assume. In count you advance top until it is NULL - thus once you called count you have "lost" your stack.
A stack is a LIFO queue (last in first out). Your push would implement a FIFO (first in first out) by appending new elements at the end.
Your push is not actually adding anything to the list. You are just assiging new to next but you are not pointing to next from anywhere in your list.
When using pop you are calling it twice (once for removing the element and once for printing). Therefore you remove two elements whenever you go down that code path. A better implementation would be to write a peek function which returns the top element without removing it and the pop function simply removes it (indicating success with 1 and fail with 0)
A push for a stack goes like this:
Create a new element
Point to your current head as the next element
Make your new element the new head of the stack
No loop needed. It's an O(1) operation.
You are not pushing correctly. You are changing next which is a local variable. you are not changing the "next" value in you list tail.
One problem is that you pop(), then check result, then pop() again while printing. You're popping twice for each time you try to print.
Another error:
while (head != NULL)
{
if ((next = head->next) == NULL)
next = new;
next->next = NULL;
state = 2;
break;
head = top->next;
next = head->next;
}
Should be:
while (head != NULL)
{
if ((next = head->next) == NULL)
{
next = new;
next->next = NULL;
state = 2;
break;
}
head = top->next;
next = head->next;
}
At least, that's what your original indentation seems to indicate.

Resources