Delete a node from a linked list - c

I'm having trouble deleting a node from a linked list by inputting the telephone number of the record ... This is the code that is supposed to do this:
typedef struct record
{
char name[20];
char surname[20];
char telephone[20];
}Record;
typedef struct node
{
Record data;
struct node *next;
}Node;
Node *head = NULL;
void delete() {
Node *n = head;
Node* previous = NULL;
Node *next = n;
int length;
int valid;
char telNumber[20];
char confirm = 1;
do {
valid = 0;
printf(" TELEPHONE NO. (8 digits) : ");
gets();
gets(telNumber);
length = strlen(telNumber);
for (int i = 0; i < length; i++)
{
if (!isdigit(telNumber[i]) || (length != 8))
{
printf("You enterred an invalid number\n");
valid = 1; break;
}
}
} while (valid == 1);
while (n != NULL) {
if (strcmp(&n->data.telephone, telNumber) == 0) {
if (previous == NULL) {
n = n->next;
free(head);
}
else {
previous->next = n->next;
free(n);
n = previous->next;
}
}
else {
previous = n;
n = n->next;
}
}
printf("You have successfully deleted the telephone record");
.
.
.
The record still remains there. Also, when I have two records, if i try to delete the first record, the program doesn't find it

You are not moving the head forward when first node is deleted.
while (n != NULL) {
if (strcmp(&n->data.telephone, telNumber) == 0) {
if (previous == NULL) {
n = n->next;
free(head);
head = n; /* missing*/
}
...

Well there is no error in deletion part. Maybe the head is not initialized and passes the null value to 'n'. So, since 'n' has null value, deletion is not possible. Or updated value of n is not returned or passed properly to the main function.

Related

Reversing an array of linked list recursively isn't reversing all nodes in order

I have an array of linked list which I am trying to reverse recursively. When I call the function to reverse it will not reverse all of the nodes but rather a couple of the nodes.
The reverse function appears to be deleting the first node (base case) and filling its spot with the last node (end of sub case). I think that the problem lies in the calling of the for loop within the reverse_nodes function however that doesn't seem to fix it.
Here is some output..
pre-reverse function:
-----
group 0
alice, 2
-----
group 1
martin, 4
-----
group 2
keanu, 6
-----
group 3
miles, 8
post - reverse function
-----
group 0
miles, 8
-----
group 1
martin, 4
-----
group 2
keanu, 6
-----
group 3
miles, 8
I am trying to get it to reverse to that it reads: 8,6,4,2
Please note I have only included relevant code blocks such as the struct architecture, the head/tail construction, the deletion of all nodes prior to reading in the binary file, reading binary file to nodes, and the main function. Can I get some help figuring out what in the reverse function is causing it to not completely reverse? Thank for your time. See code below!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node
{
char name[20];
int size;
struct node *next;
}node;
node* head[4]={NULL,NULL,NULL,NULL};
node* tail[4]={NULL,NULL,NULL,NULL};
void wipe_nodes()
{
int i;
node *p=NULL;
for(i=4; i>0; i--)
{
p=head[i];
if(p == NULL)
{
printf("Nodes are clear!\n");
}
while(p != NULL)
{
delete_party(p->name, p->size); // cant call name and size
p = p -> next;
}
}
}
void bin_to_list(char *filename)
{
FILE *fp;
int ret;
fp = fopen(filename, "rb");
if (fp == NULL)
{
printf("Null file!\n");
return;
}
node temp;
//temp = (node *)malloc(sizeof(node));
while((ret = fread(&temp, sizeof(node), 1, fp) > 0))
{
printf("%s %d", temp.name, temp.size);
if(temp.size == 0)
{
printf("\nThat is not a valid command. Party not added!\n");
}
if(temp.size >= 1 && temp.size <= 2)
{
add_party(0, temp.name, temp.size);
}
else if(temp.size >= 3 && temp.size <= 4)
{
add_party(1, temp.name, temp.size);
}
else if(temp.size >= 5 && temp.size <= 6)
{
add_party(2, temp.name, temp.size);
}
else if(temp.size >= 7)
{
add_party(3, temp.name, temp.size);
}
}
fclose(fp);
return;
}
void reverse_nodes(node *p, node *q)
{
int i;
for(i=0; i<4; i++)
{
//node *p=head[i];
if(p == NULL)
{
printf("Error, no nodes!\n");
return;
}
if (p->next == NULL)
{
printf("LOL, only one node! Can't reverse!\n");
head[i] = p;
}
else
{
reverse_nodes(p->next, p);
}
p->next = q;
return;
int main(int argc, char *argv[])
{
int x, i;
read_to_list(argv[1]);
bin_to_list(argv[2]);
while (1)
{
fflush(stdin);
printf("\n\nEnter 1 to add a party\nEnter 2 to remove a party\nEnter 3 for the list of the party\nEnter 4 to change party size.\nEnter 5 to quit (write to .txt file).\nEnter 6 to read from bin file.\nEnter 7 to reverse the list.\n\n");
scanf("%d",&x);
char name[20];
int size;
switch(x)
{
case 1:
printf("\nParty Name: ");
scanf("%s", name);
printf("\nParty Size: ");
scanf("%d", &size);
if(size == 0)
{
printf("\nThat is not a valid command. Party not added!\n");
}
if(size >= 1 && size <= 2)
{
add_party(0, name, size);
}
else if(size >= 3 && size <= 4)
{
add_party(1, name, size);
}
else if(size >= 5 && size <= 6)
{
add_party(2, name, size);
}
else if(size >= 7)
{
add_party(3, name, size);
}
break;
case 2:
printf("\nSize of party to delete: ");
scanf("%i", &size);
delete_party(NULL, size);
break;
case 3:
list_parties();
break;
case 4:
change_partysize(name, size);
break;
case 5:
write_to_file(argv[1]);
write_to_bin(argv[2]);
exit(0);
break;
case 6:
wipe_nodes();
bin_to_list(argv[2]);
break;
case 7:
for(i=0; i<4; i++)
{
reverse_nodes(head[i], NULL);
}
break;
default:
continue;
}
}
}
#include<stdio.h>
#include<stdlib.h>
/* Link list node */
struct Node
{
int data;
struct Node* next;
};
/* Function to reverse the linked list */
static void reverse(struct Node** head_ref)
{
struct Node* prev = NULL;
struct Node* current = *head_ref;
struct Node* next;
while (current != NULL)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
}
/* Function to push a node */
void push(struct Node** head_ref, int new_data)
{
/* allocate node */
struct Node* new_node =
(struct Node*) malloc(sizeof(struct Node));
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
/* Function to print linked list */
void printList(struct Node *head)
{
struct Node *temp = head;
while(temp != NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
}
/* Driver program to test above function*/
int main()
{
/* Start with the empty list */
struct Node* head = NULL;
push(&head, 20);
push(&head, 4);
push(&head, 15);
push(&head, 85);
printf("Given linked list\n");
printList(head);
reverse(&head);
printf("\nReversed Linked list \n");
printList(head);
getchar();
}
Your reverse_nodes function is just setting the next member of the node, not the current node, so when it gets to the end of the list, it will set the next of the last member to the previous member in the linked list but leave the last member untouched.
This worked for me:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node
{
char name[20];
int size;
struct node *next;
}node;
node* head;
void reverse_nodes(node ** pphead)
{
node *prev = NULL;
node *current = *pphead;
node *next;
while (current != NULL)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*pphead = prev;
}
void main(void)
{
int i;
node * phead;
head = phead = (node *)malloc(sizeof(node));
phead->size = 0;
for (i = 0; i < 4; i++)
{
node * p;
phead->next = (node *)malloc(sizeof(node));
phead = phead->next;
phead->size = i + 1;
phead->next = NULL;
}
reverse_nodes(&head);
phead = head;
while (phead)
{
printf("%d\r\n", phead->size);
phead = phead->next;
}
}
Edit:
Recursion is usually a bad idea as you could end up blowing the stack - it's always best to try and do what you need to do in a single (or multiple if required) function(s) if possible, which in this case is easily possible.

Segmentation fault issue while reversing linked list in c

#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insert(struct node *link, int data) {
if (link == NULL) {
link = (struct node *)malloc(sizeof(struct node));
link->data = data;
link->next = NULL;
} else {
struct node *newlink = (struct node *)malloc(sizeof(struct node));
newlink->data = data;
newlink->next = link;
link = newlink;
}
return link;
}
void reverse(struct node *link) {
int i, j = 0;
int arr1[100], arr2[100];
struct node *current;
int count = 0;
current = link;
while (current != NULL) {
arr1[i] = current->data;
i = i + 1;
count = count + 1;
current = current->next;
}
printf("\n");
i = 0;
j = 0;
for (i = count - 1; i >= 0; i--) {
arr2[j] = arr1[i];
j = j + 1;
}
printf("The elements in the linked list are: ");
for (i = 0; i < count; i++) {
printf("%d ", arr1[i]);
}
printf("The elements in the reversed linked list are: ");
for (j = 0; j < count; i++) {
printf("%d ", arr2[j]);
}
}
void print(struct node *link) {
struct node *temp = link;
printf("The elements in the linked list are: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
}
void main() {
int value;
printf("Enter the value:\n");
scanf("%d", &value);
struct node *link = NULL;
link = insert(link, value);
char ans[3] = "yes";
while (ans[0] == 'y') {
printf("Do you want to add another node? Type Yes/No\n");
scanf("%s", ans);
if (ans[0] == 'y') {
printf("Enter the value:\n");
scanf("%d", &value);
link = insert(link, value);
} else {
reverse(link);
}
}
}
Here is the code I wrote to reverse a single linked list in C. I seem to try different combinations of the program but while doing it by array method, I am unable to get rid of the segmentation fault, and hence it doesn't give output.
There are some problems in your code:
i is uninitialized when used in the while loop in function reverse, causing undefined behavior which could explain the segmentation fault.
j is not modified in the loop at the end of the reverse function, causing an infinite loop:
for (j = 0; j < count; i++) {
printf("%d ", arr2[j]);
}
you are not reversing the list, you just print the list contents in reverse order, and assume its length is at most 100. This is probably not what you are expected to do.
in function main, the array ans should be made larger to accommodate at least the word yes, and you should prevent scanf() from storing more characters into it than would fit. Also reorganize the code to avoid duplication:
int main(void) {
struct node *link = NULL;
for (;;) {
char ans[80];
int value;
printf("Enter the value:\n");
if (scanf("%d", &value) != 1)
break;
link = insert(link, value);
printf("Do you want to add another node? Type Yes/No\n");
if (scanf("%79s", ans) != 1 || ans[0] != 'y') {
break;
}
}
reverse(link);
return 0;
}
Most of the above problems would have been spotted immediately by increasing the compiler warning level (for example gcc -Wall -Werror or clang -Weverything -Werror).
Here is a simpler version that reads numbers and allocates the list in the same order as you do, inserting each new element before the previous one, then reverses the list and finally prints it. As expected, the list is printed in the order of entry.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insert(struct node *head, int data) {
struct node *newlink = malloc(sizeof(*newlink));
newlink->data = data;
newlink->next = head;
return newlink;
}
struct node *reverse(struct node *link) {
struct node *prev = NULL;
while (link) {
struct node *temp = link->next;
link->next = prev;
prev = link;
link = temp;
}
return prev;
}
void print(struct node *link) {
printf("The elements in the linked list are: ");
for (struct node *n = link; n; n = n->next) {
printf("%d ", n->data);
}
printf("\n");
}
int main(void) {
struct node *link = NULL;
int value;
printf("Enter the values, end the list with 0:\n");
while (scanf("%d", &value) == 1 && value != 0) {
link = insert(link, value);
}
link = reverse(link);
print(link);
return 0;
}

Delete a node from a linked list after finding it

I'm having trouble deleting a node from a linked list by inputting the telephone number of the record. This is the code that is supposed to do this:
typedef struct record
{
char name[20];
char surname[20];
char telephone[20];
}Record;
typedef struct node
{
Record data;
struct node *next;
}Node;
Node *head = NULL;
void delete() {
Node *n = head;
Node* previous = NULL;
Node *next = n;
.
.
. (here i wrote the code to enter the number (stored in telNumber[20])and find the record containing the number
while (n != NULL) {
if (&n->data.telephone == telNumber) {
if (previous == NULL) {
n = n->next;
free(head);
}
else {
previous->next = n->next;
free(n);
n = previous->next;
}
}
else {
previous = n;
n = n->next;
}
}
printf("You have successfully deleted the telephone record");
The record still remains there.
This:
if (&n->data.telephone == telNumber)
is not how to compare strings for equality in C. That will compare the addresses, which will never match.
It should be:
if (strcmp(n->data.telephone, telNumber) == 0)

Linked list not adding node until second iteration

I'm working on a FIFO page replacement algorithm and have it almost working. My code uses scanf() to read in a page number then it adds that item to a linked list, up to 16 pages. However, if the page already exists in the lined list, it does not add the page to this list again. There are three page frames (slots). Everything works properly, but, it does not add that item to the list until scanf() reads another integer to add to the list. I am utterly confused.
#include<stdio.h>
#include<stdlib.h>
typedef struct node {
int num;
struct node * next;
} node_t;
void print_list(node_t * head) {
node_t * current = head;
while (current != NULL) {
printf("%d\n", current->num);
current = current->next;
}
}
int fault(node_t * head, int check) {
node_t * current = head;
while(current->next != NULL){
if(current->num == check)
return 0;
current = current->next;
}
return 1;
}
void addNode(node_t * head, int num) {
node_t * current = head;
while (current->next != NULL) {
current = current->next;
}
/* now we can add a new variable */
current->next = malloc(sizeof(node_t));
current->next->num = num;
current->next->next = NULL;
}
int pop(node_t ** head) {
int retnum = -1;
node_t * nextNode = NULL;
if (*head == NULL) {
return -1;
}
nextNode = (*head)->next;
retnum = (*head)->num;
free(*head);
*head = nextNode;
return retnum;
}
///////////////////////////////////////////////////////
int main(){
int num;
int faults = 0;
int n = 0;
int j = 0;
node_t * head = malloc(sizeof(node_t));
if (head == NULL) {
return 1;
}
head->num = -1;
printf("Input page number up to 16 pages. Enter 'q' to quit.\n");
for(j=0;j<16;j++){
if(scanf("%d\n",&num) == 1) {
if (fault(head, num) == 1 && n < 3) {
n++;
faults++;
addNode(head, num);
}
else if (fault(head, num) == 1 && n >= 3) {
pop(&head);
addNode(head,num);
faults++;
}
}
else{
int c = getchar();
if( c == 'q' ){
break;
}
}
if (n == 1 && faults == 1)
pop(&head);
printf("\nPage Table:\n");
print_list(head);
printf("\nInput page number: \n");
}
printf("Number of page faults: %d\n", faults);
}
I ran it through gdb and it doesn't even call the addNode function until the second integer has been scanned.
(And yes I know scanf is garbage, I just didn't want to bother learning how to do something else)
Thanks for the help!
Your code:
if(scanf("%d\n",&num) == 1) {
should be :
if(scanf("%d",&num) == 1) {
And head needs to be initialized.
node_t * head = malloc(sizeof(node_t));
if (head == NULL) {
return 1;
}
head->next = NULL;

Simplest Linked List Creation and Printing Data

The following is a simple code segment in C to create a linked list and print all elements contained in the list.
User is asked to input integer data till a zero is entered which marks the termination of user input; Once data is saved in the linked list, the program prints all elements stored in the list and then completes its execution.
I can't make it run, every time it gives a "Segmentation fault" error, please check and tell me where I'm wrong (using gcc 4.8.2)
Code :
struct node
{
int data;
struct node * next;
};
struct node * createLinkedList()
{
int x;
struct node * start;
start = NULL;
printf("Input 0 to end, Insert elements :\n");
for(scanf("%d", &x); x ;scanf("%d", &x))
{
struct node * temp = (struct node *) malloc(sizeof(struct node));
if (temp)
{
temp->data = x;
temp->next = NULL;
if(start == NULL) {
start = temp;
} else {
start->next = temp;
start = temp;
}
}
}
return start;
}
void printLinkedList(struct node * start)
{
if (start == NULL) {
printf("Linked List is empty!\n");
} else {
printf("\nPrinting Linked List : \n");
struct node * s;
s = start;
while(s != NULL)
{
printf("%d\n", s->data);
s = s->next;
}
}
}
int main(int argc, char const *argv[])
{
struct node * start;
start = NULL;
start = createLinkedList();
printLinkedList(start);
return 0;
}
This part of code
if(start == NULL) {
start = temp;
} else {
start->next = temp;
start = temp;
}
is invalid. There has to be
if(start == NULL) {
start = temp;
} else {
temp->next = start;
start = temp;
}
Also you need to have a function that deletes all nodes of the list.

Resources