Printing a struct in a struct in a linked list - c

I have a struct like this:
typedef struct stockItem {
char *componentType;
char *stockCode;
int numOfItems;
int price;
} stockItem;
// declaration
stockItem *stockItem_new(char *componentType, char *stockCode, int numOfItems, int price);
And a struct like this to store many stock items ( linked list )
typedef struct inventory {
struct stockItem item;
struct inventory *next;
}inventory;
These are both in different header file.
I have created the linked list, I want to print off certain bits of data, such:
void outputData(){
// This temporarily takes the location of the structs in the
// linked list as we cycle through them to the end
struct inventory *myInv = pFirstNode;
printf("Current Inventory\n\n");
// Until the ptr reaches a value of NULL for next we'll
// keep printing out values
while(myInv != NULL){
// HERE IS MY PROBLEM HOW DO I PRINT OFF THE COMPONENTTYPE FROM THIS
printf("%s\n\n", myInv->item->compnentType);
// Switch to the next struct in the list
myInv = myInv->next;
}
}
EDIT:
stockItem *stockItem_new(char *componentType, char *stockCode, int numOfItems, int price){
// creates a new duration for the song
stockItem *item = (stockItem*)malloc(sizeof(stockItem));
// assigns the attributes
item->componentType = componentType;
item->stockCode = stockCode;
item->numOfItems = numOfItems;
item->price = price;
// returns it
return item;
}

We don't see the rest of the code, but since you have stockItem_new returning a pointer, then this is wrong:
typedef struct inventory {
struct stockItem item; ///missing *!
struct inventory *next;
} inventory;
Instead, we need to declare it as:
typedef struct inventory {
struct stockItem *item;
struct inventory *next;
} inventory;
Then you can assign to the item with your stockItem_new function and your outputData will work as you expect.
Update:
In your stockItem_new, you are not making a copy of the contents of componentType, but just pointing to the same value. You either need to allocate a new buffer each time and pass into stockItem_new or take care of that with strdup
item->componentType = strdup(componentType);
This will allocate enough memory and copy the contents of componentType. You would need to do this for any strings you will be keeping in your struct (since only the address is copied!).

Related

how to create a linked list with this struct as data?

I am trying to print out a table, namely the first ten elements in the periodic table as a linked list with a struct as data. The struct holds the elements' data like so:
typedef struct element{
char *name;
char *symbol;
float weight;
}element;
and then creating the list itself likeso:
typedef struct list{
struct element elements[]; //an array holding element types?
struct list *next;
}list;
so because I need to print out the first 10 elements, I tried using arrays to declare the names, symbols and weights, but I couldn't make the connection of which way to use that in the linked list as data:
char *names[10] = {"Hydrogen", "Helium", "Lithium", "Beryllium", "Boron", "Carbon", "Nitrogen", "Oxygen", "Fluorine", "Neon"};
char *symbols[10] = {"H","He","Li","Be","B","C","N","O","F","Ne"};
float weights[10] = {1.008,4.003,6.941,9.012,10.811,12.011,14.007,15.999,18.998,20.180};
It is unusual for a linked list to have an array of elements, though there are cases where it can be useful. In your case I think a linked list where each list element has one element is more appropriate:
typedef struct list{
struct element element;
struct list *next;
}list;
As a matter of style, we end up with the name element used in the structure name, as the typedef'd name and as a structure member. I suggest to rename them to struct ELEMENT and tElement. The same with the list structure. This will make it like:
typedef struct ELEMENT {
char *name;
char *symbol;
float weight;
} tElement;
typedef struct LIST {
tElement element;
struct LIST *next;
} tList;
I leave it to you to develop the functions to create and add to the list and to print it.
Just add the pointer the the next element. You do not need a new structure for it. Here is some example code (only adding to the list and printing implemented)
There is some code populating the list form the arrays.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct element{
char *name;
char *symbol;
float weight;
struct element *next;
}element;
element *addToList(element *head, const char *name, const char *symbol, float weight)
{
element *current, tmp;
if(!head)
{
head = realloc(head, sizeof(*head));
current = head;
}
else
{
element *wrk;
current = head;
while(current -> next) current = current ->next;
wrk = malloc(sizeof(*head));
if(wrk)
{
current -> next = wrk;
current = wrk;
}
}
if(current)
{
current -> name = malloc(strlen(name) + 1);
current -> symbol = malloc(strlen(symbol) + 1);
//add memory checks here
strcpy(current -> name, name);
strcpy(current -> symbol, symbol);
current -> weight = weight;
current -> next = NULL;
}
return head;
}
size_t printLinst(const element *head)
{
size_t nelems = 0;
while(head)
{
printf("%zu element = {\"%s\", \"%s\", %f}\n", ++nelems, head -> name, head -> symbol, head -> weight);
head = head -> next;
}
return nelems;
}
/* another list functions */
char *names[10] = {"Hydrogen", "Helium", "Lithium", "Beryllium", "Boron", "Carbon", "Nitrogen", "Oxygen", "Fluorine", "Neon"};
char *symbols[10] = {"H","He","Li","Be","B","C","N","O","F","Ne"};
float weights[10] = {1.008,4.003,6.941,9.012,10.811,12.011,14.007,15.999,18.998,20.180};
#define ARRSIZE(arr) (sizeof((arr))/sizeof((arr)[0]))
int main(void)
{
element *head = NULL;
for(size_t index = 0; index < ARRSIZE(weights); index++)
{
head = addToList(head, names[index], symbols[index], weights[index]);
}
printf("List is %zu elements long\n", printLinst(head));
/* another code */
}
https://godbolt.org/z/ddEzTx
You have two main options for linked list structure:
The items contain the links, and so constitute linked list nodes in their own right:
struct element {
char *name;
char *symbol;
float weight;
struct element *next; // <--- here
};
List nodes and data are separate(-ish). For example:
struct element {
char *name;
char *symbol;
float weight;
};
struct node {
struct element *element; // points to the item
struct node *next;
};
or maybe
struct node {
struct element element; // contains the item
struct node *next;
};
There can be a separate structure for the list itself, but there doesn't have to be. The minimal representation of the list is simply a pointer to the head node:
struct node *head;
It is not usual for there to be a structure containing the nodes directly, as you propose, because requiring the nodes to be drawn from such a pool would limit the maximum size of the list. There are other reasons why it can be useful to have a structure type representing the overall list, but that's probably more complexity than you need to worry about for your present task.
Whether you want to declare typedef aliases for your structure types is an entirely separate question, by the way. I rarely do so, myself. It is largely a style question, but I bring it up because some people have the mistaken impression that typedef is an essential element of the definition of a structure type.

Adding to the end of a linked list not working

When Trying to add a Student to the end of my List it comes out to be in the wrong alphabetical order. I have tried changing the add to end part of my function but can't seem to see what's wrong.
This is the way I add to end
Student *prvPtr= headStudentList;
for(Student *curPtr = headStudentList->next; curPtr != NULL; curPtr = curPtr->next)
{
if (curPtr->next==NULL){
curPtr->next= newPtr; //newPtr
return headStudentList;
}
if(strcmp(curPtr->lastName,last)<0 ){ //change from first
if(strcmp(curPtr->firstName,first)<0 )
{
newPtr->next=curPtr->next;
curPtr->next =newPtr; //curPtr->next =newPtr
return headStudentList; //headStudentList
}
}
}
This is what is inside of the structs
typedef struct _grade {
char name[4];
double value;
struct _grade *next;} Grade;
////////////////////////////////////////////////////////////////////////////////////////
typedef struct _student {
char *lastName;
char *firstName;
Grade *headGradeList;
struct _student *next;} Student;
One thing i see is that you are skipping the first member of your linked list when you initialize your pointer in your for() loop. What if your list is empty? This wont add a node to the end.

Changing an int value in struct which is in linked list

I have a struct:
struct person{
char* name;
char* surname;
int age;
};
And I use this struct inside another struct for linked list:
struct listNode {
struct person data;
struct listNode *nextPtr;
};
typedef struct listNode ListNode;
typedef ListNode *ListNodePtr;
I am trying to insert one struct into the linked list. After that I want to get this struct by index and change the age value. In main, I have these codes:
int main() {
ListNodePtr startPtr = NULL;
struct person p;
p.age = 22;
p.surname = "Pilkington";
p.name = "Anthony";
insert(&startPtr, p);
printf("Age1:%d\n", p.age);
struct person p2 = getStruct(&startPtr, 0);
p2.age++;
printf("Age2:%d\n", p2.age);
struct person p3 = getStruct(&startPtr, 0);
printf("Age3:%d\n", p3.age);
return 0;
}
Now, my insert function and getStruct function are working correctly. But I cannot increment the age value. My output is:
Age1:22
Age2:23
Age3:22
I want to make the Age3 23. In insert function, I already allocate memory with malloc, but why can't I change the first value? How can I change this value without removing/adding the node from list?
I search the subject but I cannot find the answer that I want. So, If you can help me I appreciate that.
---EDIT-----
Sorry for not posting getStruct method, I am adding it below:
struct person getStruct(ListNodePtr *sPtr, int index) {
ListNodePtr currentPtr;
struct person c;
int counter = 0;
currentPtr = *sPtr;
while (currentPtr != NULL) {
if (counter == index) {
c = currentPtr->data;
}
counter++;
currentPtr = currentPtr->nextPtr;
}
return c;
}
Here:
struct person p2 = getStruct(&startPtr, 0);
You return a person by value, which is to say you make a copy. Then you modify the copy, not the original. You'll need to do this instead:
struct person *p2 = getStruct(&startPtr, 0);
p2->age++;
printf("Age2:%d\n", p2->age);
That is, return a pointer, which you can use to modify what it points to. This also requires a slight change to getStruct(), whose code you haven't posted.

Pointer to pointer to nested structure

There are two structures for BST
typedef struct _price {
double price;
char* shopname;
} pricing;
typedef struct _bstnode {
int id;
pricing** pl;
int nr_of_prices;
struct _bstnode *left;
struct _bstnode *right;
struct _bstnode *parent;
} bstnode;
I need to make a function that can add and update price and shop name in BST Node. One Node may contain many shops and prices
void updatePrice(bstnode* root, int id, char* shop, double price){
//to do
}
I can add a single shop name and price but how to add several objects?
(*(root->pl))=malloc(sizeof (pricing)); // ---??
(*(root->pl))->price=price;
(*(root->pl))->shopname=shop;
If nr_of_prices belongs to pl, this will add dynamically one object:
int oldidx = root->nr_of_prices++;
root->pl = realloc( root->pl, root->nr_of_prices * sizeof(*root->pl));
root->pl[oldidx] = malloc(sizeof(pricing));
root->pl[oldidx]->price = price;
root->pl[oldidx]->shopname = shop;

Is it possible to store a struct into a linked list?

I'm writing a program that solves a maze using DFS algorithm and stack. I was thinking of storing the coordinates of the path used to get to the end onto a struct containing integers x,y for coordinates and then pushing that struct onto a stack to perform other instructions on (print, pop, etc.).
I have searched all over and have yet to find anything that helps. So I went ahead and set it up but I'm getting an error about type compatibility since I have my node data as an int but I'm trying to put in a struct. Being new to linked lists I have only seen data as an int or char. Finally, is it even possible to do what I want? If not could you suggest a way of passing both x,y coordinates onto the stack? Thank you in advance.
Here's a sample of my code, where to save space a1 is an instance of COORD, and list is initialized as well as the maze and such.
typedef struct node {
int data; /* Value or data stored in node*/
struct node *pNext; /* Reference to the next node address */
} NODE;
/*Structure declares pointers for front and back of the list*/
typedef struct LIST {
NODE *front;
NODE *back;
} LIST;
/* Structure to pass multiple values onto stack */
typedef struct COORD{
int x;
int y;
}COORD;
/*Example of one of the functions */
void lst_push_front(LIST *l, COORD *a1) {
NODE *p = malloc(sizeof(NODE));
p->data = a1;
p->pNext = l->front;
l->front = p;
if(l->back == NULL) // was empty, now one elem
l->back = p;
}
Check the code below.
Since COORD is a structure you can include it in another structure as shown in the below code.
Also make sure that the ordering of the structures are proper.
p->data.x is the right way to access the members of the structure COORD
#include <stdio.h>
/* Structure to pass multiple values onto stack */
typedef struct COORD{
int x;
int y;
}COORD;
typedef struct node {
COORD data; /* --> Changes done here */
struct node *pNext; /* Reference to the next node address */
} NODE;
/*Structure declares pointers for front and back of the list*/
typedef struct LIST {
NODE *front;
NODE *back;
} LIST;
void func(COORD *q)
{
NODE *p = malloc(sizeof(NODE));
p->data.x = q->x;
p->data.y = q->y;
printf("%d %d",p->data.x,p->data.y);
free(p);
}
int main(void) {
COORD *q = malloc(sizeof(COORD));
q->x = 20;
q->y = 30;
func(q);
free(q);
return 0;
}
As #barak manos mentions you should put COORD struct before NODE and change int data to COORD data and use p->data = *a1

Resources