The functions && Linked List - c

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.

Related

Linked list — deletion of nodes which contain prime numbers [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have written a code in the C language which will create a linked list. The linked list structre has two fields, namely data and next; data contains integer data, next is a structure pointer.
The program asks the user to input data into the list. Once the data has been entered, the program will go through the list and check which data in the node contains a prime number. If it finds one such node, it will delete it and link the next node to the previous node, but I am getting a segmentation fault error and I am unable to solve.
I am putting below the code. Can you please be kind enough to help me solve it as I do not know how to find the problem?
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
typedef struct node *nptr;
nptr H, h, n;
void deletetheprime(struct node**);
void display();
int prime(int);
int main() {
nptr temp1, temp;
int i, N, p;
printf("\n if list is completed enter 999\n");
for (;;) {
printf("\n enter the data \n");
scanf("%d", &i);
if (i == 999)
break;
else
if (H == NULL) {
H = h = (nptr)malloc(sizeof(struct node));
H->data = i;
H->next = NULL;
} else {
n = (nptr)malloc(sizeof(struct node));
n->data = i;
n->next = NULL;
h->next = n;
h = n;
}
}
printf("\n data before deletion\n");
display();
temp = H;
while (temp != NULL) {
N = temp->next->data;
p = prime(N);
if (p == 1) {
deletetheprime(&temp);
} else {
temp = temp->next;
}
}
printf("\n the data after deletion is\n");
display();
return 0;
}
void deletetheprime(struct node **temp2) {
nptr temp, temp1;
temp = *temp2;
temp1 = temp->next;
temp->next = temp->next->next;
free(temp1);
temp = temp->next;
}
int prime(int i) {
int j, p = 0;
for (j = 2; j <= i / 2; i++) {
if (i % j == 0) {
break;
}
}
if (j > i / 2) {
p = 1;
}
return p;
}
void display() {
nptr temp;
temp = H;
while (temp != NULL) {
printf("\n %d", temp->data);
temp = temp->next;
}
}
The problem is here:
while (temp != NULL) {
N = temp->next->data;
When you reach the last element of the list, temp is not NULL, but temp->next is so temp->next->data has undefined behavior.
There are other problems:
your prime() function is inefficient and will return 1 for 0 and 1.
you deletetheprime() function deletes the node and updates the pointer in the callers scope, but the caller does not update the link in the previous node nor the H pointer if the deleted node is the first.
you use global variables for no good reason, you should pass H to display() and make all variables local in main().
you never free the allocated objects, it is good style to free everything you allocate.
you should not hide pointers behind typedefs, make node a typedef for struct node but keep pointers visible, it is a good habit to avoid confusing both the reader and the programmer.
To delete the node, you should use the pointer to link trick:
for (struct node **p = &H; *p;) {
if (prime((*p)->data) {
nptr np = *p;
*p = np->next;
free(np);
} else {
p = &(*p)->next;
}
}
p initially points to the head pointer H and subsequently points to the next member of the previous node. It can be used to update the head pointer or the link in the previous node when a node to be deleted is found.
Here is a corrected and simplified version:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
int isprime(int n) {
if (n < 2)
return 0;
if (n % 2 == 0)
return n == 2;
for (int i = 3; i * i <= n; i += 2) {
if (n % i == 0) {
return 0;
}
}
return 1;
}
void display(const node *temp) {
while (temp != NULL) {
printf(" %d", temp->data);
temp = temp->next;
}
printf("\n");
}
int main(void) {
node *H = NULL;
node **lastp = &H;
node *n;
int i;
printf("Enter values, when list is completed enter 999\n");
for (;;) {
printf("\n enter the data: ");
if (scanf("%d", &i) != 1 || i == 999)
break;
n = malloc(sizeof(*n));
if (n == NULL)
break;
n->data = i;
n->next = NULL;
*lastp = n;
lastp = &n->next;
}
printf("\n data before deletion: ");
display(H);
for (node **p = &H; *p;) {
if (isprime((*p)->data)) {
n = *p;
*p = n->next;
free(n);
} else {
p = &(*p)->next;
}
}
printf("\n the data after deletion is: ");
display(H);
/* free the list */
while (H != NULL) {
n = H;
H = n->next;
free(n);
}
return 0;
}
I shall attribute your please solve it! stance to your poor command of the English language. Please learn to improve both your communications and your programming skills by carefully studying answers on this site.
The problem occurs here, in main
while(temp!=NULL)
{
N=temp->next->data;
...
You are checking if temp is not NULL, which is correct, but accessing data of next node, which can be NULL, and has to be NULL near the end of the list, which leads to undefined behavior.
Simply modify it to
while(temp!=NULL)
{
N=temp->data;
...
Where you are sure that temp isn't NULL and you won't get segmentation error here. And it'll work.
Or if you need to access data of temp->next->next node, you've got to check if next->next isn't NULL as well.
while(temp!=NULL)
{
if (temp->next->next != NULL)
{
N=temp->next->data;
}
else // temp->next->next is NULL so you can't access the data
...

How can I display the data I created in a linked list?

I think there is something wrong with my create.
void add(N *p) {
N *current, *start;
current = malloc(sizeof(p));
scanf("%d", &current->data);
current->next = NULL;
if (p == NULL) {
p = current;
start = current;
} else {
start->next = current;
start = current;
}
}
I think that my display() is correct.
void display(N *p) {
N *current;
current = p;
while (current != NULL) {
printf("\n%d", current->data);
current = current->next;
}
}
Your malloc(sizeof(p)) only returns enough space for a pointer. You instead want malloc(sizeof(N)).
Also, you need to return the new value of p instead of throwing it away at the end of add(). (Your start has a similar issue; pick one to be the head of your linked list.)
There are problems:
function add() does not allocate the correct amount of memory. Use this method:
current = malloc(sizeof(*current));
The way you are inserting the newly allocated object into the list does not work: you modify p, which is an argument with local scope, and you set start which also has local scope. No side effect is performed on the N pointer is the callers scope.
Your display function is correct, but I would favor adding the newline at the end of the output instead of at the beginning.
Here is an updated version with a better API:
int add(N **headp) {
N *current = calloc(sizeof(*current));
if (current == NULL) {
fprintf(stderr, "cannot allocate memory for new object\n");
return -1;
}
if (scanf("%d", &current->data) != 1) {
fprintf(stderr, "cannot read value for new object\n");
return -2;
}
current->next = *headp;
*headp = current;
return 0;
}
void display(const N *list) {
for (const N *p = list; p != NULL; p = p->next) {
printf("%d\n", p->data);
}
}
The add function is used this way from the caller:
#include <stdio.h>
#include <stdlib.h>
typedef struct N {
int data;
struct N *next;
} N;
int main(void) {
N *list = NULL;
for (i = 0; i < 10; i++) {
if (add(&list))
break;
}
display(list);
return 0;
}

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.

Single linked list delete function with recursion in 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.

Stack by pointers in C working except at stack underflow

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.

Resources