Struggling to form a linked list - c

I am working on a problem that involves creating an inventory of supermarket stock, and I'm having considerable difficulties. What the program is supposed to do is prompt a user for input (item name, quantity, weight, and price) and then add this item into a sorted (by increasing alphabetical order) database.
So my idea is to create a linked list. I've started by defining the following:
typedef struct item_t item;
struct item_t{
char name;
int weight;
int price;
int quantity;
item *next;
};
So the idea that I'm going for is that every item has its details stored in this structure type, and that *next will point to the next structure in the linked list.
Next I came up with this:
void add_new_node_at_end(char *user_input){
new_node = (*item_t)malloc(sizeof(item_t))
if (new_node == NULL){
printf("Memory failure");
exit(EXIT_FAILURE);
}
}
Is this correct so far?
Now, I'm not too sure what to do about the pointer *next when I create a new node, nor do I know how to change the fields of the structure. Can I simply use new_node.item = 'string' or do I need to malloc the field names as well?
Sorry, this might be a silly question but I really need someone to point me in the right direction.

You need one global root pointer (item_t* root) and initialize it with NULL which is the start of your list. For a single-linked list, point the next pointer of the new element to the element pointed at by root, and change root to point to the newly created element.
By doing this, you create daisy-chain of elements. The end is reached when item.next == NULL .

Related

Inventory system approach

So I'm creating a system to control inventory. I have a text file which contains all the items in the inventory.
as:
{component, stock code, count, price}
I am creating a struct to represent the stock (this is done in a header file):
typedef struct StockItem {
char *componentType;
char *stockCode;
int numOfItems
int price;
} StockItem;
I want to have a struct in which controls the entire inventory as a linked list, was wondering how would I do it so it would have a collection of StockItems. ( would this be a good way to do it)?
Also one more question, is it conventional to have the struct as a capital letter or not ?
EDIT:
typedef struct inventory {
struct StockItem item;
struct inventory *next;
}inventory;
inventory *pFirstNode = NULL;
inventory *pLastNode = NULL;
void createNewList(struct StockItem *item){
// Set aside enough space in memory for this struct
inventory *pNewStruct = (inventory*) malloc(sizeof(inventory));
// We can assign the value directly for the structs
// reference for the next struct in the linked list
pNewStruct->next = NULL;
printf("Enter Product Name: ");
// The & is needed only because scanf() is used
pNewStruct->item = item;
// When the first struct is created all of the following
// refer to the same struct
pFirstNode = pLastNode = pNewStruct;
}
If a linked list is suitable in your case really depends on how you want to access your inventory. If you plan only to go through it in sequence a linked list is good. If you store an index to a specific inventory item and later retrieve that item out of your list, thats going to be incredibly slow. In this case a datastructure with an array (std::vector for example) is better. But all of that also depends on the amount of data you have. Theres nothing wrong querying a linkedlist by index that only has 100 elements. For your specific question on how you can create a collection, are you limited to c, or can you use c++? The std namespace has a lot of useful collections including an implementation for a linkedlist and a vector which basically is an array, that dynamically resizes.
As you want to limit yourself to c, you will have to write your list implementation yourself. Its nothing that i would recommend somone who is still learning though. Implementing a decent list is really difficult. But if you really want to, this might be a good start. You also learn how linked lists work under the hood, which is a good thing considering a lot of people missuse linkedlists and wonder about bad performance afterwards.
Lets take the link above as an example. They defined a node struct:
typedef struct node {
int val;
struct node * next;
} node_t;
The field "val" is type int. In your case this will be the type of item, that you want to store in your list. Its going to be StockItem or a pointer to a StockItem, depending on how you want to manage your memory. If you want to add a StockItem to the list, you wrap it into a node and assign the pointer to that node to the "next" field of the previous node. Everything is also really well explained in the link i provided.
What you got so far is fine. Next, to add a node to your list, you should set the lastNode pointer and the next pointer in lastNode:
pLastNode->next = pNewStruct;
pLastNode = pNewStruct;

Struct - remove one of the elements

Let's say I have the following struct:
struct object {
char *name;
struct object *next;
};
Using that I can easily create a table as a described in K&R C book. And remove all the objects by that:
object *object_destroy(object *obj)
{
if (obj != NULL) {
object_destroy(obj->next);
free(obj->name);
free(obj);
obj = NULL;
}
}
But what I want is to remove one of the objects in table, saving all the others. I really have no idea how to implement that, because just free() that object is won't work: the objects after it will be permamently lost. I can't obj_to_remove = obj_to_remove->next too, because after that I will lose all the objects before that object.
So can you point me out what I am missing? Thanks.
You are effectively attempting to delete a single node from a singly linked list (as opposed to a doubly-linked-list, or a circular list, also known as a ring buffer).
Please refer to the references below for more information on the concept of a singly linked list. In short, you:
Start at the first node in the list (the head node).
Cycle through the list one node at a time, keeping a pointer to the previously accessed node, until you find the node you want to delete.
Point the previous node in the list to the one ahead of the current/found node.
3.1. If there is no node afterwards (we are at the end of the list), set to NULL.
3.2. If the head/first node was the one found, set the head node to the second node in the list.
Delete the elements inside the node if the node has been found.
Delete the current node itself.
The second reference will be very helpful to you, as it covers building a list from scratch, adding items to the end of the list (appending), inserting items at an arbitrary point in the list, deleting individual items, and clearing out the whole list.
References
Deleting from a Linked List, Accessed 2014-04-22, <https://www.cs.bu.edu/teaching/c/linked-list/delete/>
Singly linked list - insert, remove, add, count source code, Accessed 2014-04-22, <http://www.cprogramming.com/snippets/source-code/singly-linked-list-insert-remove-add-count>
You have the following 1->2->3->4->5 and you want to remove the element 3. The final result will be 1->2->4->5.
To do this you just need to do the following steps:
1- If the element is in the middle of the list:
Traverse the table, for each element you save previous element and the element itself.
When the element equals the one you want to delete you have cur_el = 3 and prev_el = 2. (cur_el and prev_el are pointers to the elements 3 and 2)
Now just make prev_el->next = cur_el->next (don't forget to keep a pointer to the prev_el.
Finally just free the cur_el.
2- If the element is the first of the list (let's say you want to delete 1):
- Set the first list element as cur_el->next (here cur_el points to 1, the first element in the list)
free the cur_el
3- If the element is in the end of the list (in this case 5):
- go to the last element, get the penultimate element (let's call the pointer to this one prev_el)
set prev_el->next = null
free cur_el
Also, notice that removing an element from the list has a complexity of O(n), where n is the number of elements of the list.
If you just insert and remove from the begin or from the end you can reach a O(1).
In the question, the memory structure is referred to as a 'table'. Perhaps it would be better to call it a 'linked-list'.
int object_destroy(
object **head, /* The head of the linked-list is required in order to maintain proper list nodes linkage. */
object *obj
)
{
int rCode=0;
/* Unlink the node to be destroyed. */
if(*head == obj) /* Is the obj to destroy the head list node? */
*head = obj->next;
else
{
object *temp = *head;
/* Find the parent list node (to the one that will be destroyed). */
while(temp)
{
if(temp->next == obj)
break;
temp=temp->next;
}
/* Not found? */
if(NULL == temp)
{
rCode=ENOENT;
fprintf(stderr, "obj node not found in list\n");
goto CLEANUP;
}
/* Unlink the node, and patch the list so that remaining nodes are not lost. */
temp->next = temp->next->next;
}
/* Free the node to be destroyed. */
if(obj->name)
free(obj->name);
free(obj);
CLEANUP:
return(rCode);
}

confused over the usage of free () in C

This is done by someone who is better in C programming than me.
confused over the usage of free () in C
below is the struct of linked list
typedef struct node {
int value;
struct node *next;
} ListNode;
typedef struct list {
ListNode *head;
} LinkedList;
after created a list with some nodes
his code does this when exit
void deleteList(LinkedList *ll) {
if (ll != NULL) {
ListNode *temp;
while (ll->head) {
temp = ll->head;
ll->head = temp->next;
free(temp);
}
free(ll);
}
}
The above is what I don't understand. Why he needs to create such complexity, why not just do free(ll).
Please help
thanks in advance.
Linked list is made up of individual objects that happen to point at each other. If you want to delete a list you have to delete all of its nodes. free() won't do that. It doesn't know that these objects make up a list. It doesn't even know that these objects contain pointers to anything. Therefore you need to iterate over the list and free each node by hand.
if you have a linked list, suposse that every "*" is a node.
0 1 2 3 4
head--> *--*--*--*--*
the first *, es the head, is you just do "free ll"
this will be on the memory
0 1 2 3 4
head-->nul *--*--*--*
the problem here, is, all the "memory" that you ask for those nodes will still be there, and now you can't know where is it (you have nothing poiting to that memory) for every malloc you need a free (not 100% true, but for simple things work).
What that algorithm do is:
get the reference to the next node (if you don't do this and you free the node, you won't be able to get the "next" node, becouse head will be pointing to nothing ).
free the head.
make head point to the reference that you get before.
You can do with the following struct alone
typedef struct node {
int value;
struct node *next;
} ListNode;
But every time you have to declare a global variable struct node *HEAD. In a bigger program it may confuse you. The author has done this so that you can create a linked list like a variable. Every time you have to create a new linked list all you have to do is declare
LinkedList *ll;
When there are two struct, one has to free the objects of both the struct.
That's because each pointer points to a memory location. You need to free all memory locations that were previously allocated. free(ll) would only remove the node pointed to by the ll pointer.

Linked-list is confusing

I am stuck, as I don't understand what is this code doing:
struct node
{
int info; /* This is the value or the data
in the node, as I understand */
struct node *next; /* This looks like a pointer. But
what is it doing in real life? */
} *last; /* What is this and why is it
outside the body? What is this
thing doing? */
I know that when a node is created, it has a value, and it is pointing to some other node
but I don't understand the syntax.
Is this a better way of writing the code above?
Is there a simpler way of writing the same struct for better understanding?
In my lectures they presume that the student has understanding of what they teach.
Well, we can explain this to you, but we can't understand it for you.
Code snippet you've provided is definition of variable last, being pointer to newly defined structure type node. It can be written other way as:
typedef struct _node_t {
int info;
node_t *next;
} node_t;
node_t *last;
This way we define typedef, which is, say, alias of type definition to some short name — in this particular case, it aliases structure of two fields as the name node_t. Wherever you define something as being of type node_t, you tell compiler that you mean 'this should be aforementioned structure of two fields', and node_t *last means 'variable last should be pointer to node_t type'.
So, back to syntax:
struct foo {
int a;
float b;
void *c;
} bar, *baz;
means 'Define structure type foo, and make it contain three fields — integer a, float-point b and untyped pointer c, then make variable bar to be of this structure type, and make variable baz to point to this structure type'.
Now to pointer. What you see is called 'recursive definition', e.g. type mentions itself in it's own definition. They are okay, if language supports them (C does), but one could avoid recursive definitions in linked list node structure by specifying next node pointer to be just untyped:
struct node_t {
int info;
void *next;
};
This way you no longer reference node_t type from node_t type, but that adds you some inconveniences when using this type (you have to explicitly cast next to node_t type, like ((*node_t)(last->next))->info instead of just last->next->info).
If you feel you need additional reference, consider taking a look at interactive online tutorials, like http://www.learn-c.org/ (I'm not affiliated).
that is the simplest way to write a linked list node , but why name it last ? name it node instead , this makes it more understandable , but here's how it works.
when a linked list is first created it contains only the root node (the first node in a linked list) , when you add a node , you fill the info field with the data that node will hold (note that info may be any kind of data , character , string , int ...) then set next to NULL , since that node is the last node in the list.
when you add another node , you change the value of next to point to the node you just added and you set the value of next to NULL in the node you just created because now that is the last node in the list .
you can repeat this to add as many nodes as your memory allow you to.
this link may help you to better understand structures
typedef struct marks {
int m;
struct marks *next;
} marks_t;
This way we define a structure so that a Linked List can be formed. Now we have defined the last variable next as a "structure pointer" which gives us the address of the next element in the list (i.e. as structure only)!
The last element does not point to any node (here marks structure) and hence the pointer variable has NULL value.
Now to define the first element:
marks_t *list;
if (list == NULL) {
list = (marks_t *) malloc(sizeof(marks_t));
}
list->m = 15;
list->next = NULL;
Now if we want to add an element next to this (i.e. second element):
marks_t *next1;
next1 = (marks_t *) malloc(sizeof(marks_t));
next1->m = 27;
next1->next = NULL;
list->next = next1; // Storing address of next1 structure in list

More than 1 linked list - Adding elements

I need to make a program that has (at most) 50 linked lists. Basically, my program generates some messages and based on a indicator that comes in the front of my string, I need to put the message in the right linked list.
I don't know if it is clear enough but I will try to show part of my code (the important part). The function I made to add a new element (on the top) of the linked list is the following:
void InsertLL (News p, char M[]) {
char * text = malloc(strlen(M)+1);
strcpy(text, M);
News s,t;
t = malloc(sizeof(struct List));
t-> Text = text;
s = p;
p = t;
p-> next = s;
}
My struct List (the type of the elements of my lists) contains a char pointer (called text) and a pointer to the next element of the list.
Simulating my program, suppose that I received a message that needs to be put in the linked list where the begin is pointed by the pointer p[0]. So I create a new element (forget the case that the list is empty, I already made this one) and add in the top of my list using the function I've shown.
Now, suppose that I received another message that needs to be put in the next pointer p[1]. If I print p[0] -> Text, I get the text of p[1]->Text.
I mean, if I add a new element in the list pointed by p[i], all the previous texts p[i] -> Texts gets the new text of this new element. I have no idea what am I doing wrong.
I don't know if it is enough to help me, if more information is needed, just tell me.
Problem with your code is you are not maintaining the list of nodes. you are overwriting the same node again and again.
Algo:
If no node then create one.
If nodes are present then navigate to end node.(You can use tail
pointer for quicker access).
Append the node at the end.
Creating Node:
Declare a node type pointer.
Allocate memory to it.
Update the content of the node.
Set the next pointer of the node to null.
Add this node to end of the list.
ex. inserting node 3 in the list of node 1 and node 2.
This is the general approach that you can use
typedef struct node{
int val; //you can use your text here
struct node* next;
}NODE;
struct node* head=0;
int addNode(int v){
if(head==0){ //checking for empty node.
struct node* n=malloc(sizeof(NODE));
n->val=v;
head=n;
}
else{
struct node* temp=head;
while(temp->next != 0) //Navigating till end
{
temp=temp->next;
}
struct node* n=malloc(sizeof(NODE)); //allocating memory
n->val=v; //you need to use strcpy for string here.
temp->next=n; //adjusting pointers
n->next=0;
}
}
You can check this demo created by me for Double linked List http://ideone.com/s6TtUX

Resources