Single linked list delete function with recursion in C - c

I am trying to make a students list for a project in c
the functions inside the program are 3
insert = inserts students to the list
print = prints out the students available
delete = deletes a student from the list
I have created the program and it works fine using all three functions
and now I would like to make the same list using recursion.
I have made the print function recursive and it is working
now I am trying to make the delete function work the same way
unfortunately I am failing to make it work
In the code below if you run it you will see that it works only if you do not attempt to delete the last node on the list and if you do not tell it to delete a node that it does not exists.
#include <stdio.h>
#include <stdlib.h>
typedef struct tf *tp;
struct tf{
int am;
double gr;
tp next;
};
tp head, tail, temp, aux;
void insert1 (tp *h, tp t);
void print1(tp h);
void delete1(tp *h,int da);
int main()
{
char fry, fry2;
int am;
fry = 'a';
head = NULL;
tail = NULL;
while (fry != 'q')
{
printf("\n character given is %c\n", fry);
if (fry != 'q')
{
printf("new choice\n");
fry = 'a';
fflush(stdin);
fry = getchar();
getchar();
if (fry == 'q')
printf("quit\n");
if (fry == 'i')
{
fry2 = fry;
printf(" insert new student number am\n");
insert1(&head,tail);
fry = fry2;
}
if (fry == 'd')
{printf(" delete \n");
printf(" am number of student to be deleted\n");
scanf("%d", &am);
delete1(&head,am);
}
if (fry == 'p')
{
printf("\n printing\n");
print1(head);
}
}
}
}
void insert1 (tp *h, tp t)
{
tp te, a;
int da;
te = (tp)malloc(sizeof(struct tf));
printf(" am number for the new insert\n");
scanf("%d", &da);
getchar();
te->am = da;
te->next = NULL;
printf("am number is %d",te->am);
if ((*h != NULL) && (te->am < (*h)->am))
{
te->next = *h;
*h = te;
}
if((*h != NULL) && ((*h)->next != NULL) && (te->am > (*h)->am))
{
a=*h;
while((a->next != NULL) && (a->next->am < te->am))
{
a= a->next;
}
te->next = a->next;
a->next = te;
}
if((*h != NULL) && ((*h)->next == NULL) && (te->am > (*h)->am))
{
(*h)->next = te;
}
if(*h == NULL)
{
printf("\n head is null");
*h = te;
t = te;
}
}
void print1(tp h)
{
tp a;
a=h;
if (a==NULL)
return;
printf("%d\n",a->am);
print1(a->next);
}
void delete1(tp *h,int da)
{
tp a= *h,t= *h,temp = NULL;
if ((*h) != NULL)
{
if ((*h)->am!=da)
{
if (a->next->am != da && a->next!=NULL)
{
delete1(a->next,da);
}
else
{
if (a->next==NULL)
{
printf("am not found\n");
return;
}
else
{
temp = a->next;
a->next = a->next->next;
free(temp);
}
}
}
else
{
a = (*h);
(*h)= (*h)->next;
free(a);
}
}
else
{
printf("empty list");
}
}
As you can see I want the delete function to delete the node by looking for the am number given,so it will first search the list to find if the am number is there or not.
If anyone can give me a tip on how to make the delete function to work I would be grateful.

There are several things going on. This line:
if (a->next->am != da && a->next!=NULL) ...
should have the conditions swapped, otherwise you might access a->next withot verifying that it isn't NULL first. The auxiliary variable a and the other temporaries are confusing rather than helpful.
You pass the head to the delete1 function as pointer to pointer, so that the head can be updated. But this doesn't affect only the head: This adds a level of indirection thoughout your iteration.
For your iterative calls, this means that you must pass the address of the pointer that stores the reference to the current node, (*h)->next. At the beginning, this is the address of the head. On subsequent iterations, this is the address of the next pointer of the previous node.
There's also no need to consider various cases. The code can be as simple as:
void delete1(tp *h, int da)
{
if (*h != NULL) {
if ((*h)->am == da) {
tp next = (*h)->next;
free(*h);
*h = next;
return;
}
delete1(&(*h)->next, da);
}
}
The recursive call happens at the end of the function or it doesn't happen at all. This means that you can rewrite the code as a loop:
void delete1(tp *h, int da)
{
while (*h != NULL) {
if ((*h)->am == da) {
tp next = (*h)->next;
free(*h);
*h = next;
return;
}
h = &(*h)->next;
}
}
This will save you some stack space on large lists. Your insert1 function could also be cleaned up and simplified.

Related

Unable to delete an element from a list connected to hashtable

I have a hashtable that implement chaining collision. I have this function void elimina that should be used to eliminate an element from a list but the function doesn't eliminate the first element. For the other elements it works fine. How can I solve it?
void elimina() {
int chiave, a;
printf("\nQuale elemento vuoi elimiare?\n");
scanf("%d", &chiave);
a = chiave % DIM_TABELLA;
c = head[a];
struct nodo *newnodo = (struct nodo *)malloc(sizeof(struct nodo));
newnodo->next = c;
if (head[a] == NULL)
printf("\nL'elemento non esiste");
else {
if (c->next->info == chiave) {
c = c->next;
free(c);
} else
if (c->next != NULL) {
while (c->info != chiave) {
b = c;
c = c->next;
}
}
if (c) {
b->next = c->next;
free(c);
}
}
}
Multiple problems:
There is no need to allocate a new node in this function.
You do not link the next node before you free c
You never test if the first node matches the key.
You should use an unsigned number so the % operation always returns a positive number.
Here is a modified version:
void elimina(void) {
printf("\nQuale elemento vuoi eliminare?\n");
unsigned int chiave;
if (scanf("%u", &chiave) != 1)
return;
unsigned int a = chiave % DIM_TABELLA;
struct node *c = head[a];
if (c == NULL) {
printf("L'elemento non esiste\n");
return;
}
if (c->info == chiave) {
/* free the first node */
head[a] = c->next;
free(c);
} else {
while (c->next && c->next->info != chiave) {
c = c->next;
}
if (c->next) {
struct node *p = c->next;
c->next = p->next;
free(p);
} else {
printf("L'elemento non esiste\n");
}
}
}

Cannot store elements in a linked list

My goal is to create a linked list and store elements inside that list.
struct node
{
int a;
struct node *b;
} p,*temp,*head;
void create ( struct node *temp)
{
char c;
temp = malloc (sizeof(struct node));
printf("enter data\n");
scanf(" %d",&temp->a);
printf("do you want to insert another node y/n\n");
scanf("%s", &c);
if (c=='y')
{
create(temp->b);
}
else if ( c=='n')
{
temp->b= NULL;
temp=&p;
return;
}
}
void traverse ( struct node *head)
{
while(head != NULL)
{
printf("%d ",head->a);
head=head->b;
}
}
int main ()
{
int i,j,k,l,m,n;
do{
if(i==1)
{
printf("enter data\n");
scanf("%d",&p.a);
create (p.b);
}
else if ( i==2)
traverse(temp);
}
while(i!=3);
printf("%d",temp->a);
}
I can't recover the elements once i've stored them. When I try to traverse the list, it only gives me the first element of the list and nothing else.
In main
do {
if(i==1)
{
...
}
else if ( i==2)
traverse(temp);
}
while(i!=3);
must be something like
do {
if (scanf("%d", &i) != 1)
break;
if(i==1)
{
...
}
else if ( i==2)
traverse(temp);
}
while(i!=3);
to know what the user want (i not initialized in your code)
in create
scanf("%s", &c);
is wrong because c is a char rather than a string
Do not mix read of int and char because you will read newline and space when reading a character, so read a string for c, for instance
char c[2];
...
scanf("%1s", &c);
if (*c == 'y')
...
else if (c == 'n')
...
the return in else branch is useless, and in case the answer is not 'y' or 'n' you do nothing so you do not set temps, probably you have to just check if 'y' and all other answers must be considered to be 'n', or you need to ask again for the choice
in create you assign the local variable temps, that has no effect on p.b in main, you need to get a node** for instance
in main temp is used but never set elsewhere, and the variables j,k,l,m,n are useless. You also ask for the data in main while you also do in create, must not be done in main. The way you manage your variables do not allow you to modify/print the list
I encourage you to not use global variables the must you can, and to not use the same name for a global and local variable like you do for temp and head because that do not help the reader of your code
A proposal solving the problems :
#include <stdlib.h>
#include <stdio.h>
struct node
{
int a;
struct node * b;
};
/* flush input up to the end of the line */
void flush()
{
int c;
while ((c = getchar()) != '\n') {
if (c == EOF)
exit(-1);
}
}
void create (struct node ** l)
{
/* go to the end of the list */
while (*l != NULL)
l = &(*l)->b;
for (;;) {
char c[2];
int v;
printf("enter data\n");
if (scanf("%d", &v) != 1) {
puts("invalid value");
flush();
}
else {
*l = malloc (sizeof(struct node));
(*l)->a = v;
(*l)->b = NULL;
l = &(*l)->b;
for (;;) {
printf("do you want to insert another node y/n\n");
scanf("%1s", c);
if (*c == 'y')
break;
else if (*c == 'n')
return;
}
}
}
}
void traverse ( struct node *head)
{
while(head != NULL)
{
printf("%d ",head->a);
head = head->b;
}
putchar('\n');
}
int main ()
{
int i;
struct node *head = NULL;
for (;;) {
puts("enter choice : 1 to create new node, 2 to print list, 3 to exit");
if (scanf("%d", &i) != 1)
flush();
switch(i) {
case 1:
create(&head);
break;
case 2:
traverse(head);
break;
case 3:
return 0;
default:
break;
}
}
}
Compilation and execution :
/tmp % gcc -pedantic -Wextra -Wall t.c
/tmp % ./a.out
enter choice : 1 to create new node, 2 to print list, 3 to exit
2
enter choice : 1 to create new node, 2 to print list, 3 to exit
1
enter data
11
do you want to insert another node y/n
y
enter data
22
do you want to insert another node y/n
n
enter choice : 1 to create new node, 2 to print list, 3 to exit
2
11 22
enter choice : 1 to create new node, 2 to print list, 3 to exit
1
enter data
3
do you want to insert another node y/n
n
enter choice : 1 to create new node, 2 to print list, 3 to exit
2
11 22 3
enter choice : 1 to create new node, 2 to print list, 3 to exit
4
enter choice : 1 to create new node, 2 to print list, 3 to exit
3
I encourage you to add the free of the list
There are several issues here:
struct node
{
int a;
struct node *b;
} p,*temp,*head;
Why do you declare global variables and use it as function parameters ? Global variables are available globally, there is no need to pass them into functions. On the other hand, global variables should be avoided and used with care, so it would be better to create local variables (e.g. in main function) and pass them as parameters into next functions.
void create ( struct node *temp)
{
char c;
temp = malloc (sizeof(struct node));
printf("enter data\n");
scanf(" %d",&temp->a);
printf("do you want to insert another node y/n\n");
scanf("%s", &c);
if (c=='y')
{
create(temp->b);
}
else if ( c=='n')
{
temp->b= NULL;
temp=&p;
return;
}
}
This function looks wrong. temp function parameter is actually an internal function's variable, that is not an in/out parameter. In that case you can assign to the temp variable, but it will not for a list. Also temp function parameter shadows temp global variable. It is also a good think to return status of operation, usually '0' means no error, any other error value.
Another thing is to keep things as simple as possible. This will allow for more reuseability and goes with single responsibility principle. If function actually performs two tasks it should be split into two functions.
One more thing, you allocate memory dynamically but never free the memory. This will lead into memory losses.
A possible implementation of your list could be:
#include <stdio.h>
#include <stdlib.h>
typedef struct _node_t
{
int a;
struct _node_t * next;
} node_t;
static node_t * head = NULL;
static node_t * tail = NULL;
node_t * create(void)
{
node_t * temp = malloc(sizeof(node_t));
if (NULL == temp)
{
return NULL;
}
printf("Enter data\n");
scanf("%d", & temp->a);
return temp;
}
void append(node_t * data)
{
if (NULL == head)
{
head = tail = data;
}
else
{
tail->next = data;
tail = tail->next;
}
tail->next = NULL;
return;
}
int add_data(void)
{
node_t * data = NULL;
char answer = 'y';
data = create();
if (NULL == data)
{
return 1;
}
append(data);
return 0;
}
void traverse(void)
{
node_t * current = NULL;
for (current = head; current != NULL; current = current->next)
{
printf("%d ", current->a);
}
printf("\n");
return;
}
void cleanup(void)
{
node_t * current = head;
while (NULL != current)
{
head = head->next;
free(current);
current = head;
}
return;
}
int main(int argc, char ** argv)
{
int option = 3;
do
{
printf("Enter option:\n 1 - add data\n 2 - traverse list\n 3 - exit\n\n");
scanf("%i", & option);
switch (option)
{
case 1:
if (0 != add_data())
{
printf("ERROR:: Cannot allocate memory.\n");
cleanup();
return 1;
}
break;
case 2:
traverse();
break;
default:
if (option > 3)
{
printf("ERROR:: Improper option, try again.\n");
}
break;
}
}
while (option != 3);
cleanup();
return 0;
}
I tried making it as simple as possible and keeping your logic there.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
// create a new node
struct node* create(int data)
{
struct node *n = malloc(sizeof(struct node));
n->data = data;
n->next = NULL; // by default its not NULL, so we must set it
return n;
}
void traverse(struct node *head)
{
struct node *tmp = head;
while(tmp != NULL)
{
printf("%d\t",tmp->data);
tmp = tmp->next;
}
}
void cleanup(struct node *head)
{
struct node *cur = head;
struct node *next;
while(cur != NULL)
{
next = cur->next;
free(cur);
cur = next;
}
}
int main ()
{
int data;
struct node *head, *tmp;
// head node is always created
printf("enter data\n");
scanf("%d",&data);
head = tmp = create(data);
if(head == NULL) return -1;
// now we loop until we don't want to create any more nodes
while(1)
{
char another;
printf("do you want to insert another node y/n\n");
scanf(" %c", &another); // ignore all the previous whitespace
if(another == 'y')
{
printf("enter data\n");
scanf("%d",&data);
tmp->next = create(data);
tmp = tmp->next;
}
else break;
/*
// anything but 'y' breaks the loop, but it can be set to continue if neither 'y' nor 'n' was read:
else if(another == 'n') break;
else continue;
*/
}
traverse(head);
cleanup(head);
}
EDIT: as #Diodacus stated, i added cleanup and checking if malloc returned NULL

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)

Having issues allocating a new struct

I've read half a dozen answers with regards to this here and am relatively loathe to ask such a question, but I'm attempting to create a linked list using a struct in C, and was having some issues in passing pointers to the linked list. I think it's mostly sorted, but honestly am having acute issues trying to get the linked list working.
#include <stdio.h>
#include <stdlib.h>
typedef struct cell
{
int value;
struct cell *next;
} cell;
int inputplace = 0;
cell * createlist()
{
cell curElement = (cell *) malloc(sizeof(cell));
cell *head = &curElement;
cell *curEl = &curElement;
curEl->value = 900;
FILE *fp;
char *mode = "r";
fp = fopen("input",mode);
if(fp==NULL)
{
fprintf(stderr, "Unable to open input file 'input'");
exit(1);
}
int val;
int tempplace = 0;
while(tempplace < inputplace)
{
if(fscanf(fp, "%d", &val) != EOF)
{
tempplace++;
printf("%d", &val);
}
else
break;
}
while(fscanf(fp, "%d", &val)!=EOF)
{
inputplace++;
printf("%d\n", curEl);
if(val < 0)
{
curEl->value = -1;
curEl->next = -1;
break;
}
printf("%d\n", val);
curEl->value = val;
curEl->next = malloc(sizeof(struct cell));
curEl= curEl->next;
}
return head;
}
cell* reverse(cell* p)
{
cell * prev = -1;
cell * current = p;
cell * next;
while(current->value != -1)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
return prev;
}
cell* append(cell* p, cell* q)
{
cell * current = p;
cell * r = p;
while(1)
{
if(current->value == -1)
{
current->value = q->value;
current->next = q->next;
}
}
return r;
}
int last(cell *p)
{
cell q = *p;
int last = -1;
while(1)
{
if(q.value == -1)
{
return last;
}
else
{
last = q.value;
q = *q.next;
}
}
}
cell * delete(int n, cell *p)
{
cell * head = p;
cell * prev = -1;
cell * current = p;
if(current-> value == n)
{
return current->next;
}
else
{
while(current->value != -1)
{
if(current->value==n)
{
prev->next = current->next;
break;
}
prev = current;
current = current->next;
}
}
return head;
}
int member(int n, cell *p)
{
cell q = *p;
while(1)
{
if(q.value == n)
{
return 1;
}
if(q.value == -1)
{
return 0;
}
q = *q.next;
}
}
int display(cell *p)
{
printf(" %c", '[');
cell q = *p;
while(1)
{
if(q.value == -1)
{
printf("%c ",']');
return 1;
}
if(q.next != p->next)
printf("%c ",',');
printf("%d", q.value);
q = *q.next;
}
printf("\n\n");
}
int main()
{
cell *head = createlist();
cell *headk = createlist();
cell *head3 = delete(5, head);
printf("%d, %d\n", head->value, head->next->value);
printf("Last head: %d\n", last(head));
display(headk);
display(head);
display(head3);
cell *head4 = delete(6, head);
display(head4);
cell *head5 = delete(7, head);
display(head5);
printf("Member2 6, head: %d\n", member(6,head));
printf("Member2 3, head: %d\n", member(3, head));
cell *head2 = reverse(head);
//print(head2);
printf("%d, %d\n", head2->value, head2->next->value);
}
So the input file contains numerical data with a negative one terminating the list:
Example input I'm using:
5
6
7
-1
1
2
3
-1
The issue I'm having is the second list is apparently overriding the first or some such, and my pointer-fu is weak, what do I need to do to successfully allocate the new structs?
Charles B.
You return a pointer to a local variable, and local variables goes out of scope once the function returns and that leaves you with a stray pointer. Using that stray pointer will lead to undefined behavior.
The problem starts with the declaration of curElement, and the compiler should really have screamed at you for that:
cell curElement = (cell *) malloc(sizeof(cell));
Here you declare curElement to be an actual structure, and not a pointer to the structure.
There's also the problem that you don't really have an end to the list. You allocate the next pointer of the last node you add, regardless if there's going to be a next node or not, and you don't initialize that node so the memory you allocate will be uninitialized, and trying to access it will lead to yet another undefined behavior.
I suggest something like the following abbreviated code:
cell *head = NULL;
cell *tail = NULL;
...
while (fscanf(fp, "%d", &val) == 1)
{
...
cell *current = malloc(sizeof(*current));
current->val = val;
current->next = NULL; // Very important!
// Check if this is the first node in the list
if (head == NULL)
head = tail = current;
else
{
// List is not empty, append node to end of list
tail->next = current;
tail = current;
}
}
Beside the change in how the list is handled and added to, there are also two other changes: The first is that the return value from the fscanf function is compared against 1, because fscanf (and family) will return the number of successfully parsed items, and this allows you to find format errors in the input file.
The second change is to not cast the return of malloc. In C you should never cast from or to void *, cast like that can hide subtle bugs.

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