all link list value changed when new string input - c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 40
struct ticket
{
char *visitor;
struct ticket *nextPtr;
};
// insert a new value into ticket data list
void append(struct ticket **head_ref, char *visitor)
{
// allocate node
struct ticket *new_node = (struct ticket *)malloc(sizeof(struct ticket));
struct ticket *last = *head_ref;
// put in the data
new_node->visitor = visitor;
// This new node is the last node
new_node->nextPtr = NULL;
// If the Linked List is empty, then make the new node as head
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
// Else traverse till the last node */
while (last->nextPtr != NULL)
{
last = last->nextPtr;
}
// Change the next of last node
last->nextPtr = new_node;
return;
}
// This function prints contents of linked list starting from head
void printList(struct ticket *node)
{
while (node != NULL)
{
printf("\n%s", node->visitor);
node = node->nextPtr;
}
}
char Name[31] = {'\0'};
int main(void)
{
/* Start with the empty list */
struct ticket *head = NULL;
int i = 0;
printf("Name: "); // instruction
scanf("%[^\n]%*c", Name);
append(&head, Name);
printList(head);
printf("Name: "); // instruction
scanf("%[^\n]%*c", Name);
append(&head, Name);
printList(head);
return 0;
}
I want to store some string the linked list, but when I try to input any string and add to the linked list, all the previous value of the linked list has been changed to the last string that I have enter.
What I get ->
Name: Chris
Chris
Name: Lebron
Lebron
Lebron
What I expect ->
Name: Chris
Chris
Name: Lebron
Chris
Lebron

As noted your program currently just stores a link to the character array. Following is one route you might go with storing a name in your linked list if you can afford to limit your names to a specific character length.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 40
struct ticket
{
char visitor[MAX]; /* Utilized your maximum length */
struct ticket *nextPtr;
};
// insert a new value into ticket data list
void append(struct ticket **head_ref, char *visitor)
{
// allocate node
struct ticket *new_node = (struct ticket *)malloc(sizeof(struct ticket));
struct ticket *last = *head_ref;
// put in the data
// new_node->visitor = visitor;
strcpy(new_node->visitor, visitor); /* Store the name in this fashion */
// This new node is the last node
new_node->nextPtr = NULL;
// If the Linked List is empty, then make the new node as head
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
// Else traverse till the last node */
while (last->nextPtr != NULL)
{
last = last->nextPtr;
}
// Change the next of last node
last->nextPtr = new_node;
return;
}
// This function prints contents of linked list starting from head
void printList(struct ticket *node)
{
printf("\nNames\n-------------------\n");
while (node != NULL)
{
printf("%s\n", node->visitor);
node = node->nextPtr;
}
}
char Name[31] = {'\0'};
int main(void)
{
/* Start with the empty list */
struct ticket *head = NULL;
//int i = 0;
printf("Enter name(s) or type 'quit' to end entry\n\n");
while (1) /* Allow for variable number of vistors to be entered and stored */
{
printf("Name: "); // instruction
scanf("%[^\n]%*c", Name);
if ((strcmp(Name, "quit") == 0))
{
break;
}
append(&head, Name);
}
printList(head);
return 0;
}
Utilizing the "MAX" constant in your code, the linked list structure was revised to allocate enough storage for a character string of 39 characters plus the NULL terminator. Along with a slight tweak to the input of names in the main function, the program can be tested with the entry of one or more names.
Following is a sample output illustrating the storage and retrieval of your linked list data.
#Dev:~/C_Programs/Console/LinkedList/bin/Release$ ./LinkedList
Enter name(s) or type 'quit' to end entry
Name: Chris
Name: Lebron
Name: Milly
Name: Joe
Name: quit
Names
-------------------
Chris
Lebron
Milly
Joe
You might want to explore other approaches for allocating variable amounts of character data down the road, but you might want to utilize the simple fixed length approach for storing string data in your linked list structure if you have a feel for the maximum length of the names to be stored.
Give that a try to see if it meets the spirit of your project.

Related

I cant find the error of my linked list( why is my head pointer moving?)

I have tried so many times to set my head pointer pointing to the first node. At first(in the empty list) it correctly points the first node. But after the first loop, the head pointer points to the newnode linked. Actually now Im quite unsure about my whole code as well.
int main(void){
struct library *head = NULL; //set the head pointer to NULL
int option;
printf("Enter the number:");
while((option = getchar())!= 9){
switch(option){
case '1':
{
char title[1000];
char author[1000];
char subject[1000];
printf("Enter title of the book you want to add:");
scanf("%s",title);
printf("Enter author of the book you want to add:");
scanf("%s",author);
printf("Enter subject of the book you want to add:");
scanf("%s",subject);
add_book(title,author,subject,&head);
printf("successful! and head pointer is pointing to %s\n",head->collection.title);
break;
}
}
}
void add_book(char title[],char author[],char subject[], struct library ** head){
struct library *current;
struct library *newnode = malloc(sizeof(struct library));
newnode->collection.title = title;
newnode->collection.author = author;
newnode->collection.subject = subject; // assigning value inside newnode
newnode->num_books = 0;
newnode->next = NULL; // assign NULL value to the end of newnod
//when the head is NULL which means when the list is empty
if(*head == NULL)
{
current = newnode;
*head = current;
return;
}
else
{
current = *head; //assign the first node to current pointer
//find the last node of the list
while(current->next != NULL)
{
current = current->next;
}
current->next = newnode; // link the last node to new node
return;
}
}
This is struct for this
struct book {
char* title;
char* author;
char* subject;
};
struct library {
struct book collection;
int num_books;
struct library* next;
};
The lifetime of char title[1000];, char author[1000];, and char subject[1000]; ends when execution reaches the end of the block inside case '1': { /* ... */ }. Once this happens, the pointers that were assigned in add_book become dangling pointers - pointing to invalid memory.
To remedy this, you must ensure the lifetime of your strings matches the lifetime of the structures that contain them. This can be done either by allocating enough space in the structure itself
struct book {
char title[1000];
/* etc. */
};
or by dynamically allocating enough space for a copy of each string. In any case you must copy the string to this memory (man 3 strcpy).
If it is available on your system, man 3 strdup does both steps of the second form at once. Otherwise, it is roughly the same as strcpy(malloc(strlen(source_string) + 1), source_string);.
Also note that the scanf specifier %s is as dangerous as gets when used without a field-width specifier (e.g., char buffer[1000]; scanf("%999s", buffer);), as it can potentially overflow your buffer.
An example program. Enter strings one-by-one, and terminate with EOF CTRL+D (Windows: CTRL+Z, RETURN).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct link {
char *string;
/* alternatively: char string[512]; */
struct link *next;
};
void add_link(struct link **root, const char *string) {
struct link *node = calloc(1, sizeof *node);
node->string = strdup(string);
/* alternatively: strcpy(node->string, string) */
if (*root) {
struct link *tail = *root;
while (tail->next)
tail = tail->next;
tail->next = node;
} else
*root = node;
}
int main(void) {
struct link *head = NULL;
while (1) {
char buffer[512];
if (!fgets(buffer, sizeof buffer, stdin))
break;
/* remove newline */
buffer[strcspn(buffer, "\n")] = '\0';
add_link(&head, buffer);
}
for (struct link *node = head, *next; node; node = next) {
next = node->next;
printf("STRING: %s\n", node->string);
free(node->string);
free(node);
}
}
Note: in a real program you should always check the return values of your memory allocating functions (malloc, calloc, strdup, etc.) as they can fail.

wrong output when code runs problem with linked list?

Upon running the code below i get the output
NAME: (null) | GPA: 0.000000 | YEAR: (NULL)
are the linked lists not implemented correctly? I am currently using a makefile and bringing in a test.data file with names and gpa and senior/ect..
Ollie 2.9 freshmen
John 3.2 senior
Julie 2.2 freshmen
Joe 1.8 freshmen
Mary 3.8 senior
Sue 3.4 junior
Jane 2.7 senior
Bob 2.8 senior
Fred 3.2 freshmen
Bill 3.3 junior
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "students.h"
Student *top = NULL;
Student *temp, *temp1, *temp2;
// Creates the entire linked list from the file.
// Should call readNext and push
// Returns head of the linked list
Student *buildStudentList()
{
Student *p;
p = readNext();
push(&top, p);
return top; //TODO: Change return
}
//Read a single line from standard input and return a student structure located on the heap
Student *readNext()
{
Student *s =(Student*) malloc(sizeof(Student));
scanf("%s", s -> name);
scanf("%f", &s -> gpa);
scanf("%s", s -> year);
s->next = NULL;
return s; //TODO: Change return
}
//Return a student structure stored on the heap
Student *makeStudent(char *name, float gpa, char *year)
{
Student *s =(Student*) malloc(sizeof(Student));
s -> name = name;
s -> gpa = gpa;
s -> year = year;
s -> next = NULL;
return s; //TODO: Change return
}
//insert a new student node at the head of the linked list
void push(Student **list, Student *student)
{
top = *list;
student -> next = top;
top = student;
}
//Insert a student node in the desired position on the linked list
void insert(Student *list, Student *s, int position)
{
int i;
top = list;
temp = top;
for(i = 1; i < position -1; i++)
{
temp = temp -> next;
}
if(temp == NULL)
{
//blank
}
else
{
s -> next = temp -> next;
temp -> next = s;
}
}
//Displays contents of a single student structure
void display(Student *s){
printf("NAME:%s | GPA: %f | YEAR:%s
", s -> name, s-> gpa, s -> year);
}
//Displays contents of the entire linked list
void displayAll(Student *list)
{
temp = list;
while(temp != NULL)
{
display(temp);
temp = temp -> next;
}
}
//Delete all data allocated on the heap before terminating program
void cleanUp(Student *list)
{
temp1 = list;
temp2 = temp1 -> next;
while(temp1 != NULL)
{
free(temp1);
temp1 = temp2;
}
if(temp2 != NULL)
{
temp2 = temp2 -> next;
}
}
//Main function tests your functions.
int main()
{
printf("Program Started
");
//Construct Linked List from Standard Input
Student *list = buildStudentList();
//Insert a new student in desired position
Student *s = makeStudent("Max",3.0, "senior");
insert(list, s, 3);
//Display entire linked list
displayAll(list);
//Free all heap memory
cleanUp(list);
printf("Program Successful Exit
");
exit(EXIT_SUCCESS);
}
Since you didn't post your struct definition, I had to guess whether (e.g.) name was char *name; or (e.g. char name[100];). Within the code, it used it as a pointer.
So ...
Your readNext and makeStudent don't allocate space for the strings (char * pointers) name and year, so they're probably segfaulting.
insert takes Student *list when it really needs Student **list.
IMO, you should have a separate List type to avoid confusion (that has a single element: Student *head;). So, wherever you have Student *list, you replace it with List *list
When you do that, you don't have to pass down Student ** [a double star] pointer when you mean a list. Using list->head is a lot easier and more descriptive than *list.
Also, be consistent. Some functions take Student **list if they modify the list [they have to]. Others use Student *list, but they should be consistent as well.
No need for the various global scope temp variables. These should be function scoped and use more descriptive names.
Your insert has issues. It will orphan the node it's trying to insert if no position match is found (e.g. insert at position 99 in your example). Usual is to insert at tail or return an error code. Also, it wasn't totally clear what position meant [to me], because of the code you had. It could have been "insert before" or "insert after" the Nth node.
You can't insert a literal newline in a double quoted string. So, use the \n escape sequence (e.g.) printf("hello world\n");
Also, functions that take no arguments should use void (e.g.) instead of int main(), use int main(void).
Here's a cleaned up version of your code, incorporating what I've mentioned above:
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
//#include "students.h"
typedef struct student Student;
struct student {
Student *next;
float gpa;
char *name;
char *year;
};
typedef struct list {
Student *head;
} List;
//insert a new student node at the head of the linked list
void
push(List *list, Student *student)
{
student->next = list->head;
list->head = student;
}
//Return a student structure stored on the heap
Student *
makeStudent(char *name, float gpa, char *year)
{
Student *s = (Student *) malloc(sizeof(Student));
s->name = strdup(name);
s->gpa = gpa;
s->year = strdup(year);
s->next = NULL;
return s;
}
//Read a single line from standard input and return a student structure located on the heap
Student *
readNext(void)
{
char name[1000];
float gpa;
char year[1000];
Student *s = NULL;
int count = scanf("%s %f %s",name,&gpa,year);
if (count == 3) {
printf("readNext: name='%s' gpa=%g year='%s'\n",name,gpa,year);
s = makeStudent(name,gpa,year);
}
return s;
}
// Creates the entire linked list from the file.
// Should call readNext and push
// Returns head of the linked list
List *
buildStudentList(List *list)
{
Student *p;
while (1) {
p = readNext();
if (p == NULL)
break;
push(list, p);
}
return list;
}
//Insert a student node in the desired position on the linked list
int
insert(List *list, Student *s, int position)
{
Student *cur;
Student *prev;
int i;
int goflg;
//position -= 1;
#if 0
i = 1; // insert before Nth position
#else
i = 0; // insert after Nth position
#endif
prev = NULL;
for (cur = list->head; (cur != NULL) && (i < position);
++i, cur = cur->next) {
prev = cur;
}
// this may not be needed -- usual is to insert at tail if position is not
// found -- this will orphan the node to be inserted
#if 0
goflg = (i == position);
#else
goflg = 1;
#endif
if (goflg) {
s->next = cur;
if (prev != NULL)
prev->next = s;
else
list->head = s;
}
return goflg;
}
//Displays contents of a single student structure
void
display(Student *s)
{
printf("NAME:%s | GPA: %f | YEAR:%s\n", s->name, s->gpa, s->year);
}
//Displays contents of the entire linked list
void
displayAll(List *list)
{
Student *temp = list->head;
while (temp != NULL) {
display(temp);
temp = temp->next;
}
}
//Delete all data allocated on the heap before terminating program
void
cleanUp(List *list)
{
Student *cur;
Student *next;
for (cur = list->head; cur != NULL; cur = next) {
next = cur->next;
free(cur->name);
free(cur->year);
free(cur);
}
list->head = NULL;
}
//Main function tests your functions.
int
main(void)
{
List top = { NULL };
List *list;
printf("Program Started\n");
//Construct Linked List from Standard Input
list = buildStudentList(&top);
//Insert a new student in desired position
Student *s = makeStudent("Max", 3.0, "senior");
insert(list, s, 3);
//Display entire linked list
displayAll(list);
//Free all heap memory
cleanUp(list);
printf("Program Successful Exit\n");
exit(EXIT_SUCCESS);
}

C Function to leave only unique nodes in singly linked list

I'm having an issue: in a function, program needs to compare two nodes and delete one of them if the node values are the same (example: A -> B -> B -> C >>> A -> B -> C). In a few words: it have to leave only unique nodes.
Steps that I've done: created list from data given in data file and it prints out perfectly. Now I'm struggling comparing two nodes.
Steps that I'm thinking of doing: Put two nodes values in two different variables, then comparing those two and if latest node is equal to previous, delete the latest and somehow link previous node to next node. Then the cycle goes all over again.
Question: How do I compare node with further one?
Here's the code that I have right now:
#include <stdio.h>
#include <stdlib.h>
#define LENGTH 255
struct node {
int info;
struct node *next;
} *head = NULL;
int create(FILE **data){
char read[LENGTH];
printf("Write data file name: ");
scanf("%s", read);
*data = fopen (read, "r");
if (data == NULL) {
printf("Error reading given file.");
}
return 0;
}
int put_Symbols_into_list(FILE *data) {
struct node *new_node, *current;
char c;
printf("Data given: ");
while (!feof(data)){
new_node = (struct node*)malloc(sizeof (struct node));
c = fscanf(data, "%s", &new_node -> info);
printf("%s ", &new_node -> info);
if (head == NULL){
head = new_node;
current = new_node;
} else {
current -> next = new_node;
current = new_node;
}
}
}
int delete_Same_Symbols() {
}
int main() {
FILE *data;
struct node *n;
create(&data);
put_Symbols_into_list(data);
delete_Same_Symbols();
//display_List(n);
return 0;
}
An efficient way of remove duplicates is the following:
1. Sort the list
2. Run through the list once deleting any adjacent duplicates.
Whether this solution works for you depends on whether your data can be ordered.
Traverse the list from head to end and maintain a Hash table.
For every element,check whether value is in the hash table: if yes, remove the node; else put value in the hash table.
Time Complexity: O(n) on average (assuming that hash table access time is O(1) on average).
I'll give you the function that will remove the duplicates.
Assuming that your code is working fine and that the info is an int value
Note that if info is a string you will need strcmp function instead of head->info == info.
int exist(NODE *head, int info) {
while (head && head->info != info) // strcmp(info,head->info) != 0
head = head->next;
return head->info == info; // strcmp(info,head->info)
}
void removeDuplicates(NODE **phead, int info) {
NODE *tmp = *phead;
while (tmp->info != info) // strcmp(info,head->info) != 0
tmp = tmp->next;
NODE *tmp1 = tmp->next;
tmp->info = tmp1->info; // strcpy(tmp->info,tmp1->info)
tmp->next = tmp1->next;
free(tmp1);
}

Linked list questions

Hey so i am trying to create a linked list. The following code segment opens the file for reading, which then gets passed into a function to take the string break it down and place it into a node which is suppose to be placed into the list in an appropriate location.
void print_list(struct vm_node *root);
int addNodeBottom(char *val, struct vm_node *head);
struct stock_item* setupNode(char *line);
int main(int argc, char * argv[]) {
struct vm vm;
struct menu_item menu_items[NUM_MENU_ITEMS];
struct vm_node *vmNode;
vmNode = malloc(sizeof(struct vm_node));
/* The UNUSED() function is designed to prevent warnings while your
* code is only partially complete. Delete these 4 function calls once
* you are using the data structures declared above in your own code */
UNUSED(argc);
UNUSED(argv);
UNUSED(vm);
UNUSED(menu_items);
if (argc != 3) {
printf("insuffcient arguments \n");
return EXIT_SUCCESS;
}
/*open stock file*/
char* fileName = argv[1];
FILE *file;
file = fopen(fileName, "r+");
char buf[256];
vmNode->next = NULL;
while (fgets(buf, sizeof buf, file) != NULL) {
addNodeBottom(buf,vmNode);
}
print_list(vmNode);
/* Test reason for reaching NULL. */
if (feof(file)) /* if failure caused by end-of-file condition */
puts("End of file reached");
else if (ferror(file)) /* if failure caused by some other error */
{
perror("fgets()");
fprintf(stderr, "fgets() failed in file %s at line # %d\n", __FILE__,
__LINE__ - 9);
exit(EXIT_FAILURE);
}
fclose(file);
return EXIT_SUCCESS;
}
the following function is how i have described the setupNode function.
struct stock_item* setupNode(char *line) {
struct stock_item *root;
root = malloc(sizeof(struct stock_item));
char *ptr;
const char del[2] = "|";
const char delm[2] = ".";
char *prices;
strcpy(root->id, strtok_r(line, del, &ptr)); // returns the ID and stores in in the root node.
strcpy(root->name, strtok_r(NULL, del, &ptr)); // returns the description and stores it in the root node.
strcpy(root->description, strtok_r(NULL, del, &ptr)); // returns the description and stores it in the root node.
prices = strtok_r(NULL, del, &ptr); // returns a string of the price for vm_item.
int dol = atoi(strtok(prices, delm));
int cent = atoi(strtok(NULL, delm));
root->price.dollars = dol;
root->price.cents = cent;
int quantity = atoi(strtok_r(NULL, del, &ptr)); // returns how many items are in stock.
root->on_hand = quantity;
return root;
}
This is the addNode function
int addNodeBottom(char *val, struct vm_node *head){
//create new node
struct vm_node *newNode = malloc(sizeof(struct vm_node));
if(newNode == NULL){
printf("%s", "Unable to allocate memory for new node\n");
exit(-1);
}
newNode->data = setupNode(val);
newNode->next = NULL; // Change 1
//check for first insertion
if(head->next == NULL){
head->data = newNode->data;
head->next = newNode;
}
else
{
//else loop through the list and find the last
//node, insert next to it
struct vm_node *current = head;
while (TRUE) { // Change 2
if(current->next == NULL)
{
current->next = newNode;
break; // Change 3
}
current = current->next;
};
}
free(newNode);
return 0;
}
and the printList function
void print_list(struct vm_node *root) {
while (root) {
printf("%s ", root->data->id);
root = root->next;
}
printf("\n");
}
Here is the typeDefs
#ifndef VM_TYPE
#define VM_TYPE
#define IDLEN 5
#define NAMELEN 40
#define DESCLEN 255
#define NUMDENOMS 8
#define UNUSED(var) (void)var
#define COIN_COUNT 20
#define DEFAULT_ONHAND 20
/* Type definition for our boolean type */
typedef enum truefalse
{
FALSE, TRUE
} BOOLEAN;
/* Each price will have a dollars and a cents component */
struct price
{
unsigned dollars,cents;
};
/* The different denominations of coins available */
enum denomination
{
FIVE_CENTS, TEN_CENTS, TWENTY_CENTS, FIFTY_CENTS, ONE_DOLLAR,
TWO_DOLLARS, FIVE_DOLLARS, TEN_DOLLARS
};
/* Each coin in the coins array will have a denomination (20 cents,
* 50 cents, etc) and a count - how many of that coin do we have on hand
*/
struct coin
{
enum denomination denom;
unsigned count;
};
/* The data structure that holds the data for each item of stock
*/
struct stock_item
{
char id[IDLEN+1];
char name[NAMELEN+1];
char description[DESCLEN+1];
struct price price;
unsigned on_hand;
};
/* The data structure that holds a pointer to the stock_item data and a
* pointer to the next node in the list
*/
struct vm_node
{
struct stock_item * data;
struct vm_node * next;
};
/* The head of the list - has a pointer to the rest of the list and a
* stores the length of the list
*/
struct vm_list
{
struct vm_node * head;
unsigned length;
};
/* This is the head of our overall data structure. We have a pointer to
* the vending machine list as well as an array of coins.
*/
struct vm
{
struct vm_list * item_list;
struct coin coins[NUMDENOMS];
char * foodfile;
char * coinsfile;
};
#endif
and the format of the text file that is being read in for parsing.
I0001|Coke |375 ml Can of coke |3.50|50
I0002|Pepsi |375 ml Can of pepsi |3.00|20
I0003|Lemon Cheesecake|A delicious, 1/8 size slice of cheesecake |4.00|10
I0004|Mars Bar |A delicious 50 g Mars Bar chilled just the way you like it.|3.00|20
I0005|Lemon Tart |A delicious lemon butter tart with a pastry based |3.75|12
The output when trying to print the list is complete garbage so any thoughts?
You have undefined behavior, because in addNodeBottom you make e.g. current->next point the new node you allocate, then you free the new node, so the pointer in current->next now point to unallocated memory.
Also, when setting up the first node (when head->next is NULL) then don't set the next pointer of head, let it be NULL. Instead to distinguish between an empty list or not, check for a non-null data field:
if (head->data == NULL)
{
// List is empty
}
else
{
// List is not empty
}
Other tips: There's no need to allocate a new node until you actually add it to the list. And the loop to find the last node in the list can be simplified to this:
vm_node *current;
for (current = head; current->next != NULL; current = current->next)
{
// Empty loop body
}
After the above loop current will be the last node in the list, and you can now allocate a new node.
If I would rewrite the addNodeBottom function (without modifying the function signature), it would look something like this (without any error handling):
int addNodeBottom(char *val, struct vm_node *head){
//create new node
stock_item *data = setupNode(val);
if (head->data == NULL)
head->data = data;
else
{
vm_node *current;
for (current = head; current->next != NULL; current = current->next)
;
current->next = malloc(sizeof(*current->next));
current->next->data = data;
current->next->next = NULL;
}
return 0;
}
Note: You must set vmNode->data = NULL before calling the above function for the first time, not only vmNode->next.
The main issue is because you are creating a new Node, storing data in it and then deleting the new node using free.
I understand your logic as it is now in the list so you do not need it anymore. But that is not the issue. In the list you merely put a pointer that points to the new node you created. You do not copy the new node in the list. You only put a pointer that points to the allocated memory for the node you created. If you free that part of the memory then it no longer exists and that part can be overwritten by any other application or yours. So it ends up being garbage.

Why does this C code print only the first & last node entered?

#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char *Name;
int grade;
int cost;
}Hotel; /*This is data element in each node*/
typedef struct hinfo
{
Hotel h;
struct hinfo *next;
}Hinfo; /*This is a single node*/
typedef struct
{
Hinfo *next; /*This is the head pointer of the linked list*/
}HotelHead;
void createHotel(HotelHead *h);
void DisplayHotel(HotelHead h);
int main()
{
HotelHead *list=(HotelHead *)malloc(sizeof(HotelHead));
list->next=NULL;
createHotel(list);
DisplayHotel(*list);
return(0);
}
void createHotel(HotelHead *h) /*This function creates the list of hotels*/
{
char ans='y';
while(ans=='y' || ans=='Y')
{
char *name=(char *)malloc(20*sizeof(char));
Hinfo *new=(Hinfo *)malloc(sizeof(Hinfo));
printf("\nEnter hotel name: ");
scanf("%[A-Za-z0-9 ]",name);
printf("\nEnter hotel grade & cost: ");
scanf("%d %d",&new->h.grade,&new->h.cost);
new->h.Name=name;
new->next=NULL;
if(h->next==NULL){h->next=new;}
else
{
Hinfo *current=h->next;
while(current->next!=NULL){current->next=current->next->next;}
current->next=new;
}
printf("\nEnter another hotel?(Y/N): ");
scanf("%s",&ans);
getchar(); /*dummy getchar to eat unwanted character*/
}
}
void DisplayHotel(HotelHead h) /*This function displays all hotels in the list*/
{
Hinfo *current=h.next;
printf("\nHotel list:\n");
while(current!=NULL)
{
printf("\n%s %d %d\n",current->h.Name,current->h.grade,current->h.cost);
current=current->next;
}
}
You want to move current while walking the list instead of changing the value of current->next. Change this:
while (current->next != NULL) {
current->next = current->next->next;
}
to this:
while (current->next != NULL) {
current = current->next;
}
That said, it would be better to move current while adding new nodes instead of walking the linked list from the start every time. For example (skeleton code):
Hinfo *current;
while (...) {
Hinfo *new = malloc(sizeof(Hinfo));
// initialize new node
if (current != NULL) {
current->next = new;
}
current = new;
// prompt to enter more nodes
}
The DisplayHotel function is OK! The problem is with createhotel function.
When you do:
while( current->next != NULL ){
current->next = current->next->next;
}
Here you are actually changing the list, removing an element.
Try doing:
while( current->next != NULL ){
current = current->next;
}
Also the best approach would be to always have a pointer to the last element of the list on the head, so you add new elements directly instead of always going thorough the entire list! (remember to update the head when you add a new element)
This is incorrect:
char *name=(char *)malloc(sizeof(20));
You are allocating (sizeof(int)) bytes, not 20 bytes.
No matter what else you're doing, this will cause problems.

Resources