I'm beginner in C and data structures, and getting a frustrating exception. I've compared with other doubly linked list codes but couldn't find the mistake.
While debuging the code, I get a warning about a read access violation from stdio.h and this is the troubled part:
return __stdio_common_vfprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS, _Stream, _Format, _Locale, _ArgList);
Could you help me please?
struct Node* NewNode() {
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node*));
new_node->next = NULL;
new_node->prev = NULL;
return new_node;
}
void InsertElement(char con, char name[51]) {
struct Node* new_node = NewNode();
strcpy(new_node->name,name);
if (head == NULL) {
head = new_node;
tail = head;
return;
}
if (con == 'H') {
head->prev = new_node;
new_node->next = head;
head = new_node;
}
else if (con == 'T') {
tail->next = new_node;
new_node->prev = tail;
tail = new_node;
}
}
void DisplayForward() {
if (head == NULL) {
printf("No Songs To Print\n*****\n");
return;
}
struct Node *temp = head;
while (temp != NULL) {
printf("%s\n", temp->name);
temp = temp->next;
}
printf("*****\n");
}
void DisplayReversed() {
if (head == NULL) {
printf("No Songs To Print\n*****\n");
return;
}
struct Node *temp = tail;
while (temp != NULL) {
printf("%s\n", temp->name);
temp = temp->prev;
}
printf("*****\n");
}
It seems the reason of the problem is the specified incorrect size of allocated memory in this declaration
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node*));
^^^^^^^^^^^^
You have to write
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
^^^^^^^^^^^^
That is you need to allocate memory for an object of the type struct Node instead of allocating memory for a pointer of the type struct Node *.
Pay attention to that the function InsertElement is unsafe because the user can specify a wrong value for the parameter con. In this case the function will produce a memory leak because the allocated node will not be inserted in the list and the address of the allocated memory for the node will be lost after exiting the function.
It is better to write two functions one of which will append a node to the beginning of the list and other - to the end of the list. In this case the parameter con will not be needed.
Related
Stack Overflow ... I have a linkedlist of 5 entries here, the addition process of the information in the heap is not completed, and I do not know where the error is ... Thank you
#include<stdio.h>
#include<stdlib.h>
struct Node{
char country_Name[20];
int Population;
int infe_people;
int reco_people;
int death_people;
struct Node *next;
}*head;
void AddCountry(){
struct Node *head = Null;
struct Node *newNode = (struct Node*) malloc(sizeof(struct Node));
printf("Country Name:\n");
scanf("%s",&newNode->country_Name);
printf("Number of Population:\n");
scanf("%d",&newNode->Population);
printf("Number of Infected:\n");
scanf("%d",&newNode->infe_people);
printf("Number of recovered:\n");
scanf("%d",&newNode->reco_people);
printf("Number of death:\n");
scanf("%d",&newNode->death_people);
newNode->next = null;
if(head == null){
head = newNode;
newNode->next = null;
}else{
struct Node *temp = head;
while(temp != null){
temp = temp->next;
}
temp->next = newNode;
}
}
First declaring a local variable head is wrong ,because this variable is only in Addcountry stack and it is invisible in other function.
struct Node {
char country_Name[20];
int Population;
int infe_people;
int reco_people;
int death_people;
struct Node* next;
}*head=NULL;//one head for all of your program ,don't declare other heads in functions
and since your function can insert the first node of the list ,you should change this function to return head node or pass head node by reference like this void AddCountry(Node **head)
in this else statement:
else{
struct Node *temp = head;
while(temp != null){
temp = temp->next;
}
temp->next = newNode;
}
there are mistakes. After declaring temp first allocate memory for it ,then use it(and assign head to it).Also here you are dereferencing the Null pointer.
look
else {
struct Node* temp;
temp = (Node*)malloc(sizeof(Node));
temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
And finally my advice is not using int for country population, since it probably need more space than that. change it with unsigned long int or long int.
here is the code:
struct Node {
char country_Name[20];
long int Population;
int infe_people;
int reco_people;
int death_people;
struct Node* next;
}*head=NULL;
void AddCountry(Node **head) {
struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));
printf("Country Name:\n");
scanf(" %s", &newNode->country_Name);
printf("Number of Population:\n");
scanf(" %ld", &newNode->Population);
printf("Number of Infected:\n");
scanf(" %d", &newNode->infe_people);
printf("Number of recovered:\n");
scanf(" %d", &newNode->reco_people);
printf("Number of death:\n");
scanf(" %d", &newNode->death_people);
newNode->next = NULL;
if (*head == NULL) {
*head = newNode;
newNode->next = NULL;
}
else {
struct Node* temp;
temp = (Node*)malloc(sizeof(Node));
temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
}
int main()
{
AddCountry(&head);//function call in main
}
also note those space I added to your scanf before arguments they are needed, otherwise you will probably have problem(because of \n at the end of your scanf).
PS: NULL not null.(might be problem)
You have several problems.
the information in the heap is not completed
As said in comment in AddCountry you shadow the global var head with the local var, just remove the line
struct Node *head = Null;
Using capitalized names for the global vars avoid that kind of confusion.
In
while(temp != null){
temp = temp->next;
}
temp->next = newNode;
you will dereference the null pointer, do
while(temp->next != NULL){ /*<<< change here */
temp = temp->next;
}
temp->next = newNode;
I strongly encourage you to check the value return by scanf to know if you got or not a value rather than to suppose the input values are correct / exist
Also limit the length of the read string to not write out of the buffer, so replace
scanf("%s",&newNode->country_Name);
by
scanf("%19s",newNode->country_Name);
because country_Name is an array sized 20, also note I removed the &
In :
if(head == null){
head = newNode;
newNode->next = null;
}else{
it is useless to set again newNode->next because you already did few lines before
You use null and Null, probably you mean NULL
I am just trying to insert a value to a sorted doubly linked list in C.
When I print it out using the following it never shows the newly created node. I created a new node and then set the values and then update the prev and next pointers for the new node and the node that was in front of it. I am sure it has something to do with pass by reference and would like to understand why?
struct NodeType {
int data;
struct NodeType * prev;
struct NodeType * next;
}*head, *last;
void insert_double(int key);
void displayList();
void find_node(int key);
int main()
{
head = NULL;
last = NULL;
/* Create a list with one as value and set as head */
head = (struct NodeType *)malloc(sizeof(struct NodeType));
head->data = 3;
head->prev = NULL;
head->next = NULL;
last = head;
int value=1;
insert_double(value);
printf("0\n");
displayList();
printf("1\n");
value=2;
printf("2\n");
find_node(value);
printf("3\n");
displayList();
return 0;
}
void displayList()
{
struct NodeType * temp;
int n = 1;
if(head == NULL)
{
printf("List is empty.\n");
}
else
{
temp = head;
printf("DATA IN THE LIST:\n");
while(temp != NULL)
{
printf("DATA of %d node = %d\n", n, temp->data);
n++;
/* Move the current pointer to next node */
temp = temp->next;
}
}
}
void find_node(int key)
{
struct NodeType * temp;
struct NodeType * newnode;
newnode->data=key;
if(head == NULL){
printf("No nodes");
}
else{
temp=head;
while(temp!=NULL)
{
if((temp->data)< key){
newnode->prev=temp->prev;
newnode->next=temp;
temp->prev=newnode;
break;
}
else{
temp=temp->next;
}
}
}
}
void insert_double(int key)
{
struct NodeType * newnode;
if(head == NULL)
{
printf("Empty!\n");
}
else
{
newnode = (struct NodeType *)malloc(sizeof(struct NodeType));
newnode->data = key;
newnode->next = head; // Point to next node which is currently head
newnode->prev = NULL; // Previous node of first node is NULL
/* Link previous address field of head with newnode */
head->prev = newnode;
/* Make the new node as head node */
head = newnode;
}
}
Your code is basically correct. You are just missing two important edge cases when dealing with linked list. First is when you are using find_node to insert some value, but it's gonna be add in the beginning in the list. In this case your newly created node becomes a new head of a list so you have to update a head variable. The second edge case is kind of opposite, it happens when you are inserting the new node to the end of the list. Then it becomes an end of a list so you need to update tail.
Missing those two edge cases happens a lot when first working with the linked lists, so don't worry. I think pretty much everybody who worked with linked list made these mistakes in the beginning of his journey.
Moreover you are using the uninitialized pointer to the NodeType structure in find_node:
struct NodeType * newnode;
it should be:
struct NodeType * newnode = (struct NodeType *)malloc(sizeof(struct NodeType));
Thanks to both of you. Here is the solution I came up based on both of your input:
void insert_sorted_node(int key){
struct NodeType * temp = (struct NodeType *)malloc(sizeof(struct NodeType));
struct NodeType * newnode = (struct NodeType *)malloc(sizeof(struct NodeType));
newnode->data=key;
/* no nodes at all*/
/* insert_sorted_node(value) can't start empty list, need to fix */
if(head == NULL){
printf("head =null");
temp = head;
head->data=key;
head->prev=NULL;
head->next=NULL;
last = head;
}
else{
temp=head;
while(temp!=NULL)
{
printf("\n\ndata = %d\nkey = %d\n", temp->data, key);
/* key is new head
1) check if key < head->data
*/
if(key<head->data)
{
printf("\nnew head\n");
newnode->prev = head->prev;
newnode->next = temp;
temp->prev = newnode;
head = newnode;
break;
}
/* key is tail
if temp->next = NULL
*/
else if(temp->next == NULL)
{
printf("\ntail\n");
newnode->prev = temp;
newnode->next = NULL;
temp->next = newnode;
last = newnode;
break;
}
/* key is middle head
if key > temp->data and key< temp->next->data
*/
else if((key>temp->data)&&(key<temp->next->data))
{
printf("\nmiddle\n");
newnode->prev=temp;
newnode->next=temp->next;
temp->next=newnode;
temp->next->prev=newnode;
break;
}
else{
printf("next\n");
temp=temp->next;
}
}
}
}
Your insertion function works fine, as does displayList.
However, the program has undefined behavior in the find_node function:
void find_node(int key)
{
struct NodeType * temp;
struct NodeType * newnode;
newnode->data=key; //<-- BOOM! (writing to uninitialized pointer)
if(head == NULL){
printf("No nodes");
}
else{
temp=head;
while(temp!=NULL)
{
if((temp->data)< key){
newnode->prev=temp->prev; //<-- BOOM!
newnode->next=temp; //<-- BOOM!
temp->prev=newnode;
break;
}
else{
temp=temp->next;
}
}
}
}
It's not really clear what you're trying to achieve there. If this really is a find function, it should not be attempting to perform operations on nodes or copy any data.
All you really need is something like this:
struct NodeType* find_node(int key)
{
for(struct NodeType* temp = head; temp != NULL; temp = temp->next)
{
if (temp->data == key)
return temp;
}
return NULL;
}
I have a linked list where each node stores a word and a number. I can add nodes at the top of the list (push), at the center of the list (insertAfter) and at the end of the list (append). I now added a function to delete nodes, where it will take a char, it will search that char through the list and delete the node that stores that char.
The problem is that deleteNode will work with a normal node added at the top of the list, but when i append a node at the end or add it at the middle of the list it won't work.
Tl;dr deleteNode works with nodes created with push but not with nodes created with append or insertAfter.
The error i get is segmentation fault, so i don't have a specific error from the compiler. I'm trying to debug it by running different parts of the code but i still can't find the problem.
struct Node
{
int data;
char *word;
struct Node *next;
};
void push(struct Node** head_ref, int new_data, char *new_word)
{
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->word= malloc(strlen(new_word));
strcpy(new_node->word, new_word);
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
/* Given a node prev_node, insert a new node after the given
prev_node */
void insertAfter(struct Node* prev_node, int new_data, char *new_word)
{
if (prev_node == NULL)
{
printf("the given previous node cannot be NULL");
return;
}
struct Node* new_node =(struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->word= malloc(strlen(new_word));
strcpy(new_node->word, new_word);
new_node->next = prev_node->next;
prev_node->next = new_node;
}
void append(struct Node** head_ref, int new_data, char *new_word)
{
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
struct Node *last = *head_ref;
new_node->data = new_data;
new_node->word= malloc(strlen(new_word));
strcpy(new_node->word, new_word);
new_node->next = NULL;
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
while (last->next != NULL)
last = last->next;
last->next = new_node;
return;
}
void deleteNode(struct Node **head_ref, char *word)
{
struct Node* temp = *head_ref, *prev;
if (strcmp(word, (*head_ref)->word)==0)
{
*head_ref = temp->next; // Changed head
free(temp); // free old head
return;
}
while (strcmp(word, (*head_ref)->word)!=0)
{
prev = temp;
temp = temp->next;
}
if (temp == NULL) return;
prev->next = temp->next;
free(temp); // Free memory
}
This part looks strange:
while (strcmp(word, (*head_ref)->word)!=0)
{
prev = temp;
temp = temp->next;
}
In the strcmp you use head_ref but in the body you update temp to move to the next element.
Did you intend to do:
while (strcmp(word, temp->word)!=0)
{
prev = temp;
temp = temp->next;
}
Further there should probably some check for temp being NULL. Like:
while (temp && strcmp(word, temp->word)!=0)
Apart from what was stated by #4386427, you are not allocating enough space for your strings there:
new_node->word= malloc(strlen(new_word));
Notice that the C library function size_t strlen(const char *str) computes the length of the string str up to, but not including the terminating null character. So i would rather suggest:
new_node->word= malloc(strlen(new_word) + 1);
new_node->word[strlen(new_word)] = '\0';
This can cause you some problems with the memory. ;)
Or event better, use calloc, so the second line will be unnecessary:
new_node->word= calloc(strlen(new_word) + 1, sizeof(char));
The answers you have are OK, but just for the record, after enough practice it should look kinda like this:
void deleteNode(struct Node **pplist, char *word)
{
for (struct Node *n = *pplist; n; n=*(pplist = &(n->next)))
{
if (!strcmp(n->word,word))
{
*ppnode = n->next;
free(n->word);
free(n);
break;
}
}
}
The point is that you can just move the pointer to the node pointer through the list instead of treating the head as a special case.
Similarly, you can do append like this:
void append(struct Node** pplist, int new_data, char *new_word)
{
for(; *pplist; pplist=&((*pplist)->next));
push(pplist, new_data, new_word);
}
and insert_after(prev... is just push(&(prev->next)...
I am trying to read from a list that has 1 word per line and 20 lines, and then add each word to the end of a linked list. My problem is that when I print out the linked list at the end it is printing that last word in the file 20 times instead of each word once. I have been working on this for hours and can't figure out what i'm doing wrong.
In my main I have
while (!feof(input)) {
fscanf(input, "%s", currentName);
head = insert(head, currentName);
}
print(head);
delete(head);
Insert Function
node* insert(node* head, char* name) {
node *temp = NULL;
if (head == NULL) {
head = create_node(name);
}
else {
temp = head;
while(temp->next != NULL){
temp = temp->next;
}
temp->next = create_node(name);
}
return head;
}
Create Function
node* create_node(char* name) {
node *newNode;
newNode = malloc(sizeof(node));
if(newNode == NULL) {
printf("Failed to create node");
}
newNode->name = name;
newNode->next = NULL;
return newNode;
}
Print and Delete
void print(node* head){
while (head != NULL) {
printf("%s -> ", head->name);
head = head->next;
}
printf("NULL\n");
}
void delete(node* head) {
node *temp = NULL;
while(head != NULL) {
temp = head;
head = head->next;
free(temp);
}
}
You're saving the address of the same buffer back in main() for each and every insertion. Each node is simply holding the base address of currentName, the content of which is changed with each input processed. Therefore you have a linked list of structures containing name pointers, where each points to the same buffer (currentName). Thus the last one will be the only one you see.
You need to dynamically allocate space for the name in create_node. The following uses the POSIX function strdup() to do this, though you're perfectly free to use a strlen/malloc combination if you desire.
node* create_node(char* name)
{
node *newNode;
newNode = malloc(sizeof(node));
if(newNode == NULL)
printf("Failed to create node");
newNode->name = strdup(name);
newNode->next = NULL;
return newNode;
}
Don't forget when you're cleanup up your linked list to free() each node name to avoid a memory leak.
void delete(node* head)
{
node *temp = NULL;
while(head != NULL)
{
temp = head;
head = head->next;
free(temp->name);
free(temp);
}
}
Unrelated: Your while-loop condition for loading your content is wrong. Read this answer to see why
I'm trying to add to my linked list only if the item I'm inserting isn't already in the link list but when I try to traverse it and print out all of the items nothing is printing out. I can't seem to see what I'm doing wrong. Any help would be appreciated
// my add function
void add(char *val)
{
printf("%s", val);// val is getting printed so i know its being passed in.
if(head == NULL){
struct node *new_node = (struct node *)malloc(sizeof(struct node));
head = new_node;
head->item = val;
head->next = NULL;
} else{
struct node *current = head;
struct node *newNode = (struct node *) malloc(sizeof(struct node));
if (newNode == NULL) {
exit(-1);
}
newNode->item = val;
newNode->next = NULL;
while (current != NULL) {
current = current->next;
}
current = newNode;
}
}
//my traverse function
void goThroughList() {
struct node *current = head;
while(current != NULL){
printf("%s\n",current->item);
current= current->next;
}
}
add doesn't successfully add anything once head has been assigned. It only updates a local current pointer. You could fix that by changing the code that searches for the tail of the list to
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
If this doesn't help, can you update your question to show how add is being called? (To rule out the possibility that the same char array is being used for multiple calls, leaving all nodes with their item pointers pointed to the same buffer.
Also, there is no code I can see that checks for duplicates. You could implement this inside the branch of add where head already existed by iterating through the list using strcmp to compare each node's item with val.
your add function is incorrect
try this one :
void add(char *val)
{
printf("%s", val);// val is getting printed so i know its being passed in.
if(head == NULL){
struct node *new_node = (struct node *)malloc(sizeof(struct node));
new_node->item = val;
new_node->next = NULL;
head = new_node;
}
else{
struct node *current = head;
while (current->next != NULL) {
if(strcmp(current->item, val) == 0)
return;
current = current->next;
}
struct node *new_node = (struct node *)malloc(sizeof(struct node));
new_node->item = val;
new_node->next = NULL;
current->next = new_node;
}
}
what list does this function go trought ?
void goThroughList() {
struct node *current = head;
while(current != NULL){
printf("%s\n",current->item);
current= current->next;
}
}
try this instead :
void goThroughList(struct node* llist)
{
if(llist)
{
printf("%s" , llist->item);
goThroughList(llist->next);
}
}