#include <stdio.h>
#include <stdlib.h>
/*EVERYTHING WORKS EXCEPT FOR INITIAL -1*/
// Implementing a Node Structure - This represents a node of data
typedef struct _listnode
{
int item; // Data
struct _listnode *next; // Linkage
} ListNode;
// Core Functions of a Linked List
void printList(ListNode *head);
ListNode* findNode(ListNode *head, int index);
int insertNode(ListNode **ptrHead, int index, int value);
void removeNode(ListNode **ptrHead, int index);
int main()
{
// Instantiate a Linked List
ListNode *head = NULL, *temp;
/*
head is a pointer variable that will eventually point to the firstNode.
temp is a pointer variable that points to the lastNode. This is used in from Linked List functions.
*/
int num_to_store;
printf("Enter an Integer to Store (-1 to end):\n");
scanf("%d", &num_to_store);
while (num_to_store != -1)
{
// Initialize a Linked List
if (head == NULL)
{
head = malloc(sizeof(ListNode));
temp = head;
}
else
{
temp->next = malloc(sizeof(ListNode));
temp = temp->next;
}
temp->item = num_to_store;
printf("Enter an Integer to Store (-1 to end):\n");
scanf("%d", &num_to_store);
}
temp->next = NULL;
// Menu-Driven Application
int user_choice, index, value, *p, option_3;
puts("");
printf("----------------\n 1: printList()\n 2: findNode()\n 3: insertNode()\n 4: removeNode()\n-1: End\n----------------\n");
scanf("%d", &user_choice);
while (user_choice != -1)
{
switch(user_choice)
{
case 1:
printList(head);
break;
case 2:
printf("Enter index to search:\n");
scanf("%d", &index);
p = findNode(head, index);
if (p != NULL) printf("Node Item: %d\n", *p);
break;
case 3:
printf("Enter index to insert:\n");
scanf("%d", &index);
printf("Enter value to insert:\n");
scanf("%d", &value);
option_3 = insertNode(&head, index, value);
if (option_3 == 0) printf("NODE INSERTED!\n");
break;
case 4:
printf("Enter index to remove:\n");
scanf("%d", &index);
removeNode(&head, index);
break;
}
// Prompt User to Make Another Selection
puts("");
printf("----------------\n 1: printList()\n 2: findNode()\n 3: insertNode()\n 4: removeNode()\n-1: End\n----------------\n");
scanf("%d", &user_choice);
}
return 0;
}
void printList(ListNode *head)
{
// Linked List is Empty
if (head == NULL)
{
printf("LINKED LIST IS EMPTY!\n");
}
// Linked List is Not Empty
else
{
printf("LINKED LIST: ");
while (head != NULL)
{
printf("%d ", head->item);
head = head->next;
}
puts("");
}
}
ListNode* findNode(ListNode *head, int index)
{
// Linked List is Empty or Index is Invalid
if (head == NULL || index < 0)
{
printf("INVALID!\n");
return NULL;
}
// Linked List is not Empty, Check if Index > len(Linked List)
else
{
while (index > 0)
{
head = head->next;
if (head == NULL)
{
printf("INVALID!\n");
return NULL;
}
index--;
}
printf("INDEX FOUND!\n");
return head;
}
}
int insertNode(ListNode **ptrHead, int index, int value)
{
ListNode *cur, *pre;
// Linked List is Empty || Insert at Index 0
if ((*ptrHead) == NULL || index == 0)
{
cur = *ptrHead;
*ptrHead = malloc(sizeof(ListNode));
(*ptrHead)->item = value;
(*ptrHead)->next = cur;
return 0;
}
// Insert in the Middle
else
{
pre = findNode(*ptrHead, index-1);
if (pre != NULL)
{
cur = pre->next; // This is temporary
pre->next = malloc(sizeof(ListNode)); // L connects to nN
pre->next->item = value;
pre->next->next = cur; // nN connects to R
}
return 0;
}
return -1;
}
void removeNode(ListNode **ptrHead, int index)
{
ListNode *cur, *pre;
// Linked List is Empty
if ((*ptrHead == 0) || index < 0)
{
printf("INVALID!\n");
}
// Remove firstNode
else if (index == 0)
{
cur = findNode(*ptrHead, index);
*ptrHead = cur->next;
free(cur); // Unallocate the memory
}
// Remove Middle
else
{
pre = findNode(*ptrHead, index-1);
cur = findNode(*ptrHead, index);
pre->next = cur->next;
cur->next = NULL;
}
}
Hi all, I am writing a Linked List program in C with the 4 core functions. The functions and everything else works except for when I compile the code and type -1. The program exits. I wonder what is wrong. I tried debugging on code::blocks but nothing showed up.
What am I trying to achieve?
Create a Linked List with no nodes.
Code the 4 core functions of a Linked List (insert/remove/print/search).
What have I tried?
Scattering printf() statements to debug.
Checked on stackoverflow for similar problems.
Viewed the code on geeksforgeeks.
Any idea the cause of the problem might be? And any possible solutions for this type of problem?
When you type -1, the whole while (num_to_store != -1) loop will be skipped, and temp will remain uninitialized, that will make temp->next = NULL; invoke undefined behavior.
Related
I am supposed to do an assignment in C programming language. It includes linked lists and reading user input from the console.
The user inputs numbers into the console, for example ( 1 3 5 7 0 ), which are added, one by one, to the beginning of the linked list. 0 marks the end of the transition. This is what the linked list should look like after the first part: 7 5 3 1
I need to code two different functions that will delete different elements of the linked list.
First function deletes all elements from the list that have the value that you input, and second function deletes the element on the position that the user inputs, if it exists.
At the end, you should print the list.
I've written the the first function correctly, and I am sure about it, with the second function (the one that deletes elements on a certain position) I had some trouble. I made a simple function that counts how many nodes are there in total, so if someone puts a number larger than the amount of nodes, a message would pop up. I also used that function to make a for loop and used it as a limit when searching for the element on a certain position, if that makes any sense. The program also won't print anything, I have no idea why.
typedef struct Element Element;
struct Element
{
int number;
Element *next;
};
Element *addnewN(int number)
{
Element *newN = (Element*)malloc(sizeof(Element));
newN->number = number;
newN->next = NULL;
return newN;
}
Element *add_on_beginning(Element *head, Element *newN)
{
newN->next = head;
return head;
}
Element* delete_value(Element* head, int value)
{
Element *before = NULL;
Element *temp = head;
Element *newNhead = head;
while(temp != NULL)
{
if(temp->number == value)
{
if(before == NULL)
{
newNhead = temp->next;
free(temp);
temp = newNhead;
}
else
{
before->next = temp->next;
free(temp);
temp = before->next;
}
}
else
{
before = temp;
temp = temp->next;
}
}
return newNhead;
}
int counter(Element *head)
{
int count = 0;
Element *temp = head;
while(temp != NULL)
{
count++;
temp = temp->next;
}
return count;
}
Element* delete_on_position(Element* head, int position)
{
int limit = counter(head);
Element *temp = head;
Element *newNhead = head;
Element *before = NULL;
if(position > limit)
{
printf("Error.\n");
}
for(int i = 0; i < limit; i++)
{
if(position == 0)
{
newNhead = temp->next;
free(temp);
temp = newNhead;
}
else if(position == i)
{
before->next = temp->next;
free(temp);
temp = before->next;
}
else
{
before = temp;
temp = temp->next;
}
}
return head;
}
void printElement(Element *element)
{
printf("%d ", element->number);
}
void printList(Element *head)
{
Element *temp = head;
while(temp != NULL)
{
printElement(temp);
temp = temp->next;
}
}
void menu()
{
printf("\t MENU \n");
printf("1. Delete all elements from the list that have the value that
you input.\n");
printf("2. Delete the element on the position, if it exists.\n");
printf("3. Print the list. \n");
printf("4. Exit \n");
}
int main()
{
Element *head = NULL;
int i = 0;
int arr[1000];
char temp;
int x;
int y;
printf("Input the numbers you want: \n");
while(temp != '\n')
{
scanf("%d%c", &arr[i], &temp);
if(arr[i] == 0)
{
break;
}
head = add_on_beginning(head, addnewN(arr[i]));
i++;
}
menu();
while(1)
{
scanf("%d", &x);
switch(x)
{
case 1:
{
scanf("%d", &y);
head = delete_value(head, y);
break;
}
case 2:
{
scanf("%d", &y);
head = delete_on_position(head, y);
break;
}
case 3:
{
printList(head);
break;
}
case 4:
{
return 0;
}
}
}
return 0;
}
What you are supposed to get would be for example:
Input: 2 4 5 8 5 0 (in one line), and in one line each:
2
2
1
5
3
Output: 2 8
When debugged, the code does not show any errors.
add_on_beginning is not returning the correct value. It should return the node that was added, since it's the new head of the list. Nothing else will work correctly because of that, because head will always be NULL.
Element *add_on_beginning(Element *head, Element *newN)
{
newN->next = head;
return newN;
}
The purpose of this code is to manage insertion and deletion and visualisation. I just want to know if I'm doing everything correctly, let me know if there are more possible ways to do this. This is my first attempt, i didn't follow any tutorial.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
int n;
struct Node *next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(Node *pp, int n)
{
Node temp, last;
temp = (Node)malloc(sizeof(struct Node));
temp->n = n;
temp->next = temp;
temp->prev = temp;
if(*pp != NULL)
{
last = (*pp)->prev;
temp->next = (*pp);
temp->prev = last;
last->next = (*pp)->prev = temp;
}
*pp = temp;
}
void ViewList(Node head)
{
if(head == NULL)
{
return;
}
Node node = head->prev;
do
{
printf("Curr: %d\n", node->n);
node = node->prev;
}while(node != head->prev);
}
void ReadData(Node * head, int * n)
{
printf("\nInsert a number:");
scanf("%d", n);
NewNode(head, *n);
}
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
while(head != NULL)
{
if(head->n == d)
{
return head;
}
head = head->next;
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
void Delete(Node * head)
{
Node del = SearchNode(*head);
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del && del->next == *head)
{
*head = NULL;
free(del);
return;
}
if(*head == del)
{
*head = del->next;
del->prev->next = *head;
(*head)->prev = del->prev;
free(del);
return;
}
if((*head)->prev == del)
{
(*head)->prev = del->prev;
del->prev->next = *head;
free(del);
return;
}
del->next->prev = del->prev;
del->prev->next = del->next;
free(del);
}
int Menu()
{
int c;
printf("\n*** M E N U ***\n"
"1 - New Node\n"
"2 - View List\n"
"3 - Delete\n"
"0 - Exit\n"
"\n>> ");
scanf(" %d", &c);
return c;
}
int main()
{
int c,n;
Node head = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadData(&head, &n); break;
case 2: ViewList(head); break;
case 3: Delete(&head); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
How can i test if this is a real circular doubly linked list and not a simple doubly linked list?
Your program works fine, the only real bug I detected is in SearchNode: if the element is not present in the list, you enter an infinite loop. Your list is obviously a circular list and therefore you need to check if you have got back to the head in the function, which means that the element you're searching for is not in the list:
Corrected version:
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
Node start = head; // remember where we started
while (head != NULL)
{
if (head->n == d)
{
return head;
}
head = head->next;
if (head == start) // if we are back to where we started
break; // the element hasn't been found and we stop the loop
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
There are also some design flaws, that don't prevent the program from working correctly:
One of them is this: The n variable is not used outside ReadData, so it's pointless to declare it in main and pass it's pointer to ReadData.
Corrected version:
void ReadData(Node * head)
{
int n; // declare n locally
printf("\nInsert a number:");
scanf("%d", &n);
NewNode(head, n);
}
Call it like this: ReadData(&head) and remove int n; from main.
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;
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef struct _listnode
{
int item;
struct _listnode *next;
} ListNode;
int removeNode(ListNode **ptrHead, int index);
void printList(ListNode *head);
ListNode * findNode(ListNode *head, int index);
int main()
{
ListNode *head = NULL, *temp=NULL;
int i = 0;
int index = 0;
while (1)
{
printf("Enter a integer: ");
scanf("%d", &i);
if (i == -1)
break;
if (head == NULL)
{
head = malloc(sizeof(ListNode));
temp = head;
}
else{
temp->next = malloc(sizeof(ListNode));
temp = temp->next;
}
temp->item = i;
}
removeNode(&head, index);
return 0;
}
void printList(ListNode *head)
{
int i = 0;
if (head == NULL)
return;
while (head != NULL)
{
printf("%d ", head->item);
head = head->next;
}
printf("\n");
}
ListNode * findNode(ListNode *head, int index)
{
if (head == NULL || index < 0)
return NULL;
while (index > 0){
head = head->next;
if (head == NULL)
return NULL;
index--;
}
return head;
}
int removeNode(ListNode **ptrHead, int index)
{
ListNode *pre, *cur,*temp;
if (index >= 0)
{
printf("Enter index to remove: ");
scanf("%d", &index);
if ((pre = findNode(*ptrHead, index - 1)) != NULL)
{
cur = pre->next;
temp = cur;
pre->next = cur->next;
free(temp);
printList(*ptrHead);
}
}
return -1;
}
I successfully revamp my code and now I am able to remove the node and display out, but the whole program just crash after my printList function. It does not go back to remove node and I cant continue removing other indexes.
Output:
Enter a value: 2
Enter a value: 4
Enter a value: 6
Enter a value: 8
Enter a value: -1
Enter index to remove: 2
Current list: 2 4 8
Enter index to remove: 0
Current list: 4 8
Enter index to remove: -1
when you enter index = 0, the inner if block of removenode function will not be executed as the findnode functin returns NULL. But in your output for index = 0 you got node 2 removed. How did u get that?
removeNode(head, index); should be removeNode(&head, index);
And printList(ptrHead); should be printList(*ptrHead); (in removeNode) I have the feeling this piece of code goes crazy that's why your app is not responding anymore.
What compiler do you use? It should have warned you.
In your updated code:
You still do not set next to NULL.
You never increment index when you fill list.
You do not check if scanf() succeeds.
There is no need to use pointer to pointer in removeNode(), you can use:
int removeNode(ListNode *ptrHead, int index);
You have added removeNode() in printList() which is really out of place.
You do not have any free function for the list.
...
Original answer to original code:
Missing header file.
Miss match between function signatures in declaration and definition.
You never set next to NULL.
You do not free list before exit.
...
Code with some comments:
/* MISSING: <stdio.h> */
#include <stdlib.h>
typedef struct _listnode
{
int item;
struct _listnode *next;
} ListNode;
/* Signature miss-match */
int removeNode(ListNode **ptrHead, int index);
void printList(ListNode *head);
ListNode *findNode(ListNode *head, int index);
int main()
{
ListNode *head = NULL, *temp=NULL;
int i = 0;
int index = 0;
while (i != -1)
{
printf("Enter a integer: ");
scanf("%d", &i);
/* If -1 entered, -1 will be added to list. */
if (head == NULL)
{
head = malloc(sizeof(ListNode));
temp = head;
}
else{
temp->next = malloc(sizeof(ListNode));
temp = temp->next;
}
temp->item = i;
/* temp->next never set to NULL */
}
/* Miss match between function signature and call. */
removeNode(head, index);
/* No freeing of list before exit. */
return 0;
}
void printList(ListNode *head)
{
/* Redundant check of head != NULL */
if (head == NULL)
return;
while (head != NULL)
{
printf("%d", head->item);
head = head->next;
}
}
ListNode *findNode(ListNode *head, int index)
{
if (head == NULL || index < 0)
return NULL;
while (index > 0){
head = head->next;
if (head == NULL)
return NULL;
index--;
}
return head;
}
/* Why pass index as argument when it is not used? */
int removeNode(ListNode **ptrHead, int index)
{
ListNode *pre, *cur,*temp;
printf("Enter index to remove: ");
scanf("%d", &index);
/* Here you should check < 0, not != -1.
What if user enters -9999 ? */
if (index != -1)
{
if ((pre = findNode(*ptrHead, index - 1)) != NULL)
{
cur = pre->next;
temp = cur;
pre->next = cur->next;
free(temp);
/* Bad return statement, should be int */
return;
}
/* You only print list if none was removed. */
/* Miss match between function signature and call. */
printList(ptrHead);
}
return -1;
}
I wrote a program that inserts nodes into a linked list in descending order.But whenever I test my code with numbers 12,14,13,19,7 in this order.Whenever I entered 7 I took 7 is already in the list.But as easily seen 7 is not in the list before I inserted.After give this error,if I choose print option by typing 2 my program entered in an infinite loop.I can not see my mistake and I am very confused.
#include <stdio.h>
#include <stdlib.h>
struct node {
int content;
struct node* nextLink;
};
typedef struct node NODE;
void print (NODE*);
int insertNode (NODE** head, int x);
int main (void)
{
int num, choice;
NODE* head;
head = NULL;
do {
printf("\nPlease press 1 to insert or press 2 to print or press 0 to exit\n");
scanf("%d", &choice);
switch (choice) {
case 0:
return 0;
break;
case 1:
printf("Enter an integer to insert into the linkedlist: ");
printf("\n");
scanf("%d", &num);
insertNode(&head, num);
break;
case 2:
print(head);
break;
default:
printf("You entered an invalid number\n");
return 0;
break;
}
} while (choice == 1 || choice == 2);
return 0;
}
int insertNode (NODE** head, int i)
{
NODE* newNode;
newNode = (NODE*)malloc(sizeof(NODE));
newNode->content = i;
NODE* temporary = *head;
newNode->nextLink = NULL;
if ((*head == NULL) || ((*head)->content) < i) {
*head = newNode;
(*head)->nextLink = temporary;
}
else {
do {
if (((temporary->content) > i) && ((temporary->nextLink->content) < i)) {
newNode->nextLink = temporary->nextLink;
temporary->nextLink = newNode;
return;
}
else if (temporary->content == i) {
printf("To be inserted value is already in the list\n");
return;
}
temporary = temporary->nextLink;
} while (temporary->nextLink != NULL);
if (temporary->content == i) {
printf("To be inserted value is already in the list\n");
return;
}
temporary->nextLink = newNode;
}
return 0;
}
void print (NODE* head)
{
if (head == NULL) {
printf("\nLinkedList is empty \n");
}
while (head != NULL) {
printf("%d ", head->content);
head = head->nextLink;
}
}
I compiled it and ran it and it seemed to work fine except for one thing. insertNode is defined to return an int, yet 3 of the return statements are void returns. To get it to compile, I changed them to return 0;. If you were able to compile and run it as is, then it could be the stack was getting destroyed by the inconsistent returns.
Your code won't work, if the first two values to be inserted are in descending order. It would give segmentation fault.
For the insertion of 2nd element you need to be careful
So after if condition
else if (temporary->content > i && temporary->nextLink==NULL)
(*head)->nextLink = newNode;
Your code is doing too much. If you code it differently, there are no special cases (such as insert at the top, insert at the tail of the list).
int insertNode (NODE **head, int val)
{
NODE *newnode;
for ( ; *head; head = &(*head)->nextLink) {
if ( (*head)->content == val) {
printf("To be inserted value (%d)is already in the list\n", val);
return 0;
}
if ( (*head)->content > val) break;
}
newnode = malloc(sizeof *newnode); // Maybe check return here ;-)
newnode->content = val;
newnode->nextLink = *head;
*head = newnode;
return 1;
}