Search linked list for certain node - c

I have created the data needed for my node(car).
struct data {
char carReg[10];
char make[20], model[20], colour[20];
int numPrevOwners;
bool reserved;
float reserveAmount;
};
I've also created the template for the node and the declared the global variables.
struct node {
struct data *element;
struct node *next;
};
struct node *front = NULL;
struct node *last = NULL;
In my viewSpecific() method I want the user to enter in a unique carReg and it will then find the node in which this is stored in and display it.
This is what I have so far:
void viewSpecific() {
char result[10];
printf("Please enter the registration of the car yiew wish to view.");
scanf("%s", &result);
struct node *current, *previous;
bool notFound = true;
printf("\n");
if (isEmpty())
printf("Error - there are no nodes in the list\n");
else {
I'm not quite sure what to do after this.

Check if the carReg entered by the user is the same as the current node's carReg.
If it isn't advance to the next node.
If you reach the end of the list, it's because the carReg was not found.
/* basically, something like */
current = front;
while (current != NULL) {
if (strcmp(current->element->carReg, userCarReg) == 0) /* found */ break;
current = current->next;
}
if (current == NULL) {
printf("carReg not found\n");
} else {
printf("carReg: %s\n", current->element->carReg);
printf("make: %s\n", current->element->make);
printf("previous owners: %d\n", current->element->numPrevOwners);
}

Related

Inside a loop a linked list seems to be ok but outside it is empty

I just started learning C, and I'm lost trying to read cars and their manufacturing years from a text file. The program says it doesn't find any cars when I try it with a .txt file containing the following rows:
Lada 1976
Ferrari 2005
Suzuki 1985
Volvo 1963
Toyota 1993
Honda 2011
I did a similar linked list program which read an integer from a user to be added to the list, instead of a file. I think this is completely identical, except now the program reads from a file. This goes wrong somewhere with the pointer first (my best guess from debugging prints I added to several places) or it could be that I have somehow managed to change the nodes only inside the while loop (another guess). Could someone point out what is wrong here?
#include <stdlib.h>
#include <stdio.h>
typedef struct car {
char brand[15];
int year;
struct car *prev;
struct car *next;
} car;
void readCars(char *fname, car *newCar, car *first, car *last);
void printCars(car *ptr, car *first);
void freeMemory(car *ptr, car *first);
int main(int argc, char *argv[]) {
car *first = NULL; // a pointer to the first node of the linked list
car *last = NULL; // a pointer to the last node of the linked list
car *newCar; // a pointer for new nodes
car *ptr; // a pointer for iterating the linked list
if(argc != 2) {
printf("No filename provided.\n");
exit(0);
}
printf("Reading the file %s.\n", argv[1]);
readCars(argv[1], newCar, first, last);
printCars(ptr, first);
freeMemory(ptr, first);
printf("Program ended.\n");
return(0);
}
void readCars(char *fname, car *newCar, car *first, car *last) {
FILE *tiedosto;
char rivi[22];
if ((tiedosto = fopen(fname, "r")) == NULL) {
printf("Failed to open the file.\nProgram ended.\n");
exit(0);
}
while (fgets(rivi, 22, tiedosto) != NULL) {
if ((newCar = (car*)malloc(sizeof(car))) == NULL) { // allocate memory for a new node
perror("Memory allocation failure.\n");
exit(1);
}
sscanf(rivi, "%s %d", newCar->brand, &newCar->year); // set the car brand and age to the new node
newCar->next = NULL; // set the pointer to next node to NULL as there is no next node
newCar->prev = last; // set the pointer to the previous node to the previous last node (NULL if there was no previous)
if (first == NULL) {
first = newCar; // the new node is the only node so it is the first node
last = newCar; // the new node is the only node so it is also the last node
} else {
last->next = newCar; // the new node is next node of the previous last node
last = newCar; // the new node is now the last node
}
}
fclose(tiedosto);
printf("File read into a linked list.\n");
}
void printCars(car *ptr, car *first) {
if(first == NULL) {
printf("No cars found.\n");
} else {
ptr = first;
int count = 1;
while (ptr != NULL) {
printf("%d. car: %s from the year %d.\n", count, ptr->brand, ptr->year);
count += 1;
ptr = ptr->next;
}
}
}
void freeMemory(car *ptr, car *first) {
ptr = first;
while (ptr != NULL) {
first = ptr->next;
free(ptr);
ptr = first;
}
printf("Memory freed.\n");
}
The lines
if (first == NULL) {
first = newCar; // the new node is the only node so it is the first node
last = newCar; // the new node is the only node so it is also the last node
} else {
last->next = newCar; // the new node is next node of the previous last node
last = newCar; // the new node is now the last node
}
in the function readCars only modify the variables first and last in the function readCars. They do not modify the variables first and last in the function main.
Therefore, the variable first in the function main will stay NULL, so, as far as that function is concerned, the linked list stays empty.
In order to solve the problem, the function main should not pass copies of the variables first and last to the function readCars, but should rather pass pointers (i.e. references) to these variables. So you should change the parameters of the function readCars to the following:
void readCars(char *fname, car *newCar, car **first, car **last)
You should also change the lines quoted above to the following:
if ( *first == NULL ) {
*first = newCar; // the new node is the only node so it is the first node
*last = newCar; // the new node is the only node so it is also the last node
} else {
(*last)->next = newCar; // the new node is next node of the previous last node
(*last) = newCar; // the new node is now the last node
}
Also, the parameter newCar of the function readCars does not serve any purpose as a parameter. You are instead using it as a local variable, so you should declare it as such and remove it from the parameter list of the function.
EDIT: As pointed out in the comment below, you are doing the same thing with the parameter ptr in the functions printCars and freeMemory. You should remove that parameter from these functions too.
My solution is:
#include <stdlib.h>
#include <stdio.h>
typedef struct car {
char brand[15];
int year;
struct car *prev;
struct car *next;
} car;
void readCars(char *fname, car *newCar, car **first, car **last);
void printCars(car *ptr, car *first);
void freeMemory(car *ptr, car *first);
int main(int argc, char *argv[]) {
car *first = NULL; // a pointer to the first node of the linked list
car *last = NULL; // a pointer to the last node of the linked list
car *newCar; // a pointer for new nodes
car *ptr; // a pointer for iterating the linked list
if(argc != 2) {
printf("No filename provided.\n");
exit(0);
}
printf("Reading the file %s.\n", argv[1]);
readCars(argv[1], newCar, &first, &last);
printCars(ptr, first);
freeMemory(ptr, first);
printf("Program ended.\n");
return(0);
}
void readCars(char *fname, car *newCar, car **first, car **last) {
FILE *tiedosto;
char rivi[22];
if ((tiedosto = fopen(fname, "r")) == NULL) {
printf("Failed to open the file.\nProgram ended.\n");
exit(0);
}
while (fgets(rivi, 22, tiedosto) != NULL) {
if ((newCar = (car*)malloc(sizeof(car))) == NULL) { // allocate memory for a new node
perror("Memory allocation failure.\n");
exit(1);
}
sscanf(rivi, "%s %d", newCar->brand, &newCar->year); // set the car brand and age to the new node
newCar->next = NULL; // set the pointer to next node to NULL as there is no next node
newCar->prev = *last; // set the pointer to the previous node to the previous last node (NULL if there was no previous)
if (*first == NULL) {
*first = newCar; // the new node is the only node so it is the first node
*last = newCar; // the new node is the only node so it is also the last node
} else {
(*last)->next = newCar; // the new node is next node of the previous last node
*last = newCar; // the new node is now the last node
}
}
fclose(tiedosto);
printf("File read into a linked list.\n");
}
void printCars(car *ptr, car *first) {
if(first == NULL) {
printf("No cars found.\n");
} else {
ptr = first;
int count = 1;
while (ptr != NULL) {
printf("%d. car: %s from the year %d.\n", count, ptr->brand, ptr->year);
count += 1;
ptr = ptr->next;
}
}
}
void freeMemory(car *ptr, car *first) {
ptr = first;
while (ptr != NULL) {
first = ptr->next;
free(ptr);
ptr = first;
}
printf("Memory freed.\n");
}
The main difference is that readCars needs a pointer to pointer to first and last. In this way, when the functions ends, the value of first and last does not change to the initial value (in the case NULL).
Let me know if you've understood.

Linked list insertion doesn't work as expected

I'm writing a function that places new nodes alphabetically into a linked list structure by sorting them by the name field. Here is my program, intended to test that it can successfully insert a new node into an existing structure:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 100
#define MAX_JOB_LENGTH 100
struct Employee
{
/* Employee details */
char name[MAX_NAME_LENGTH+1]; /* name string */
char sex; /* sex identifier, either ’M’ or ’F’ */
int age; /* age */
char job[MAX_JOB_LENGTH+1]; /* job string */
/* pointers to previous and next employee structures in the linked list
(for if you use a linked list instead of an array) */
struct Employee *prev, *next;
};
void place_alpha(struct Employee *new, struct Employee **root);
int main(){
struct Employee *a;
struct Employee *c;
struct Employee *b;
a = malloc(sizeof(struct Employee));
c = malloc(sizeof(struct Employee));
b = malloc(sizeof(struct Employee));
strcpy(a->name, "A");
a->sex = 'F';
a->age = 42;
strcpy(a->job, "Optician");
a->prev = NULL;
a->next = c;
strcpy(c->name, "C");
c->sex = 'F';
c->age = 22;
strcpy(c->job, "Nurse");
c->prev = a;
c->next = NULL;
strcpy(b->name, "B");
b->sex = 'M';
b->age = 34;
strcpy(b->job, "Rockstar");
b->prev = NULL;
b->next = NULL;
place_alpha(b, &a);
if(a->prev == NULL)
{
printf("a->prev is correct\n");
}else{
printf("a->prev is INCORRECT\n");
}
if(a->next == b)
{
printf("a->next is correct\n");
}else{
printf("a->next is INCORRECT");
}
if(b->prev == a)
{
printf("b->prev is correct\n");
}else{
printf("b->prev is INCORRECT\n");
}
if(b->next == c)
{
printf("b->next is correct\n");
}else{
printf("b->next is INCORRECT\n");
}
if(c->prev == b)
{
printf("c->prev is correct\n");
}else{
printf("c->prev is INCORRECT\n");
}
if(c->next == NULL)
{
printf("c->next is correct\n");
}else{
printf("c->next is INCORRECT\n");
}
}
void place_alpha(struct Employee *new, struct Employee **root) //Places a new node new into the database structure whose root is root.
{
if(*root==NULL) //If there is no database yet.
{
*root = new;
(*root)->prev = NULL;
(*root)->next = NULL;
}
else
{
if(strcmp(new->name, (*root)->name)<=0) // if the new node comes before root alphabetically
{
new->next = *root;
new->prev = (*root)->prev;
if((*root)->prev != NULL)
{
(*root)->prev->next = new;
}
(*root)->prev = new;
*root = new;
return;
}
else if((*root)->next == NULL) // If the next node is NULL (we've reached the end of the database so new has to go here.
{
new->prev = *root;
new->next = NULL;
(*root)->next = new;
return;
}
else if(strcmp(new->name, (*root)->name)>0) // If the new node comes after root alphabetically
{
place_alpha(new, &(*root)->next);
return;
}
}
}
Sadly, the program is unsuccessful, as showcased by the output:
a->prev is correct
a->next is correct
b->prev is INCORRECT
b->next is correct
c->prev is INCORRECT
c->next is correct
Program ended with exit code: 0
I can't figure out why, as I've clearly set b->next to c and c->prev to b.
This was tricky: there is a subtile bug in your place_alpha() function: you update *root even if it is not the root node of the list. This causes the pointer b to be updated erroneously. place_alpha() should only be called with a pointer to the actual root node.
I modified your code to make it more readable and reliable:
I wrote a function to create a new node
I protected the string copies from overflow using calloc() and strncat(). Read about these functions in the manual.
I use place_alpha() to insert all 3 nodes into the list in the same order you do.
I use newp instead of new to avoid C++ keywords in C code.
Note that place_alpha() must be called with a pointer to the head pointer of the list, if you pass a pointer to an intermediary node, chaining back along the prev links would locate the first node, but if the new employee should be inserted at the head of the list, you would not have the address of the root node to update in the caller's scope. This is the reason many programmers prefer to use a specific structure for the list head.
Here is the updated code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 100
#define MAX_JOB_LENGTH 100
struct Employee {
/* Employee details */
char name[MAX_NAME_LENGTH + 1]; /* name string */
char sex; /* sex identifier, either 'M' or 'F' */
int age; /* age */
char job[MAX_JOB_LENGTH + 1]; /* job string */
/* pointers to previous and next employee structures in the linked list
(for if you use a linked list instead of an array) */
struct Employee *prev, *next;
};
void place_alpha(struct Employee *new, struct Employee **root);
struct Employee *new_employee(const char *name, char sex, int age, const char *job) {
struct Employee *newp = calloc(1, sizeof(*newp));
if (!newp) {
fprintf(stderr, "cannot allocate employee\n");
exit(1);
}
strncat(newp->name, name, MAX_NAME_LENGTH);
newp->sex = sex;
newp->age = age;
strncat(newp->job, job, MAX_JOB_LENGTH);
newp->next = newp->prev = NULL;
return newp;
}
int main(void) {
struct Employee *list = NULL;
struct Employee *a = new_employee("A", 'F', 42, "Optician");
struct Employee *b = new_employee("B", 'M', 34, "Rockstar");
struct Employee *c = new_employee("C", 'F', 22, "Nurse");
place_alpha(a, &list);
place_alpha(c, &list);
place_alpha(b, &list);
if (a->prev == NULL) {
printf("a->prev is correct\n");
} else {
printf("a->prev is INCORRECT\n");
}
if (a->next == b) {
printf("a->next is correct\n");
} else {
printf("a->next is INCORRECT");
}
if (b->prev == a) {
printf("b->prev is correct\n");
} else {
printf("b->prev is INCORRECT\n");
}
if (b->next == c) {
printf("b->next is correct\n");
} else {
printf("b->next is INCORRECT\n");
}
if (c->prev == b) {
printf("c->prev is correct\n");
} else {
printf("c->prev is INCORRECT\n");
}
if (c->next == NULL) {
printf("c->next is correct\n");
} else {
printf("c->next is INCORRECT\n");
}
return 0;
}
void place_alpha(struct Employee *newp, struct Employee **root) {
// Insert a new node newp into the database structure whose root is root.
struct Employee *ep;
if (*root == NULL) { // if there is no database yet.
newp->next = newp->prev = NULL;
*root = newp;
return;
}
if ((*root)->prev) {
// invalid call, should only pass the root node address
fprintf(stderr, "invalid call: place_alpha must take a pointer to the root node\n");
return;
}
if (strcmp(newp->name, (*root)->name) <= 0) {
// if the new node comes before root alphabetically
newp->next = *root;
newp->prev = NULL;
newp->next->prev = newp;
*root = newp;
return;
}
for (ep = *root;; ep = ep->next) {
if (ep->next == NULL) {
// If the next node is NULL, we've reached the end of the list
// so newp has to go here.
newp->prev = ep;
newp->next = NULL;
newp->prev->next = newp;
return;
}
if (strcmp(newp->name, ep->next->name) <= 0) {
// The new node comes between ep and ep->next alphabetically
newp->prev = ep;
newp->next = ep->next;
newp->prev->next = newp->next->prev = newp;
return;
}
}
}
EDIT: place_alpha was a bit redundant, so I cleaned it and got a much simpler version:
void place_alpha(struct Employee *newp, struct Employee **root) {
//Places a new node newp into the database structure whose root is root.
struct Employee **link = root;
struct Employee *last = NULL;
while (*link && strcmp(newp->name, (*link)->name) > 0) {
last = *link;
link = &last->next;
}
newp->prev = last;
newp->next = *link;
if (newp->next) {
newp->next->prev = newp;
}
*link = newp;
}

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.

display function for nested singly linked list c

Im writing database program for my c class for few days now im trying to figure out how to work with singly linked lists its pretty hard to understand I would say ,well at least for me. Overall I got part of code necessary for my project, basicaly I got functions to add client and items to client thanks to help of somebody from stackoverflow I kinda figured how to add multiple items to 1 client but now I'm in trouble figuring out how exactly can I print it ,tried to do it the way you can see im my display function but it doesnt work for items linked to client what should I change to make it work?
#include <stdio.h>
#include <stdlib.h>
struct item{
char item_name[30];
struct item *NextItem;
};
struct client{
struct client *NextClient;
char name[30];
char last_name[30];
struct item *firstItem;
struct item *lastItem;
};
struct client *head = NULL;
/////////////////////////////
struct client* FindTailClient(struct client* head)
{
struct client *temp = head;
while( temp->NextClient != NULL)
{
temp = temp->NextClient;
}
return temp;
}
/////////////////////////////
////////
struct client *GetClientData()
{
char data[30];
struct client *temp;
temp = (struct client*)malloc(sizeof(struct client));
printf("Enter the person's name--->");
scanf("%s",data);
strcpy(temp->name,data);
printf("Enter the person's last name--->");
scanf("%s",data);
strcpy(temp->last_name,data);
temp->NextClient = NULL;
return temp;
}
///////////
struct item *GetItemData()
{
struct item *temp;
char data[30];
temp = (struct item*)malloc(sizeof(struct item));
printf("Enter the item name--->");
scanf("%s",data);
strcpy(temp->item_name,data);
temp->NextItem = NULL;
return temp;
}
///////////
//////////////
struct client* AddClient()
{
struct client *temp,temp1;
temp=head;
struct client *data = GetClientData();
if(head == NULL)
{
head=data;
head->NextClient = NULL;
}
else
{
while(temp->NextClient != NULL)
{
temp=temp->NextClient;
}
data->NextClient=NULL;
temp->NextClient=data;
}
}
///////////////////
///////////////////
///////////////////
void display()
{
struct client *CurrentClient = head;
struct item *ItemCurrent = head->firstItem;
while(CurrentClient != NULL)
{
printf(" -> %s ->%s \n",CurrentClient->name,CurrentClient->last_name);
while(ItemCurrent != NULL)
{
printf(" -> %s\n",ItemCurrent->item_name);
ItemCurrent=ItemCurrent->NextItem;
}
CurrentClient=CurrentClient->NextClient;
}
}
///////////////////
void AddItemToClient(struct client* head, struct item *item)
{
item->NextItem = NULL;
if(head->firstItem == NULL) {
head->firstItem = item;
} else {
head->lastItem->NextItem = item;
}
head->lastItem = item;
}
///////////////////
struct client *find(struct client *head, char name[])
{
while (head->NextClient != NULL )
{
if (strcmp(head->name,name) == 0)
{
printf("Target found: %s\n",head->name);
return head;
}
head = head->NextClient;
}
printf("target not found");
return NULL;
}
//////////////////
int main()
{
int i;
char data[30];
char name[30];
struct client *temp;
struct client *head;
struct item *data1;
for(i=0;i<2;i++)
{
AddClient();
}
printf("Insert name to find:");
scanf("%s",name);
temp = find(&head,name);
data1 = GetItemData();
AddItemToClient(temp,&data1);
display();
}
In this line: "while(ItemCurrent != ItemLast)" - ItemLast is undeclared. Maybe you wanted to write head->lastItem, or better ItemCurrent->next != NULL.
Also, make sure you store the clients you just created to be able to access them: head = AddClient(); instead of simply AddClient();

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