Ok, starting to get it. I will post my solution in the hope that other may benefit from this thread and see where it leads. I find the biggest problem with this matter to actually understand in plain english, what is really happening. Since I try not to program by trial and error, but from a good understanding, I will post my train of thought here and hope that you will correct me in case of misunderstanding.
From the ground up:
1. What do I want?
I want to implement a linked list with a separate function that can be called from main() to add extra nodes to the list. This means that I need to be able to fill a linkedList that is created in main() from a separate function.
2. The theory
(a)Variables to functions in C are passed by value. As soon as a function terminates, the locally declared variables are freed and nothing remains. So, if I want to populate a list from main(), you'll have to make sure this does not happen.
(b)Pointers are no exception to this. When you pass a pointer to a function you pass the value of the pointer - the adress it points to - to the function. As with other variables, you can manipulate this inside the function but when it comes back the pointer will be unchanged, i.e. the pointer will still contain the same adress (and therefore point to the same adress).
(c) You can however use the adress information of the pointer to manipulate what's at that adress. You can manipulate the content of the pointed-to memory. Again, the pointer remains the same, but what it refers to can be directly manipulated from a function and will remain changed after exiting the function.
(d) Per consequence, if I pass a pointer to a pointer, I can manipulate two things. First I can manipulate the content of memory that the first pointer refers to, i.e. the value of the second pointer, i.e. the adress that that pointer refers to and per consequence I can manipulate the contect of the adress that the second pointer points to as described in (c).
3.Ok, how to do it?
Solution 1 - pointer to pointer, all memeory dynamically allocated in the function
I pass a pointer to a pointer to the list (list is book). In the function I allocate for both structures (the actual order and the wrapper bookOrder) and I add these to the tail of book. This works, see below.
Code:
//Solution 1 - pointer to pointer, all memeory dynamically allocated in the function
#include <stdio.h>
#include <stdlib.h>
typedef struct order {
char dir;
float price;
int size;
char instr[5];
};
struct bookOrder {
struct bookOrder *next;
struct order *order;
};
void printBook(struct bookOrder *book) {
int i = 0;
printf("------------------------------------\n");
while ((book != NULL) && (i < 11)){
printf("Printbook price:%f size:%i \n",(book->order)->price, (book->order)->size);
book = book->next;
++i;
if (i == 10) {
printf("Printing function may be artifically terminated");
}
}
if (i == 0) {
printf("Book is empty\n");
}
printf("------------------------------------\n");
}
void addOrder(struct bookOrder **book, struct order ord) {
struct bookOrder *walker = *book;
struct bookOrder *newBook = malloc(sizeof(**book));
struct order *newOrder = malloc(sizeof(ord));
newOrder->price = ord.price;
newOrder->size = ord.size;
newBook->order = newOrder;
newBook->next = NULL;
if (*book == NULL) {
*book = newBook;
}
else {
while (walker->next != NULL)
walker = walker->next;
walker->next = newBook;
}
}
int main(void) {
//print empty book
struct bookOrder *book = NULL;
printBook(book);
//insert first order and print
struct order inpOrder;
inpOrder.price = 37;
inpOrder.size = 600;
addOrder(&book, inpOrder);
printBook(book);
//insert second order and print
inpOrder.price = 67;
inpOrder.size = 340;
addOrder(&book, inpOrder);
printBook(book);
return 0;
}
Solution 2 - single pointer, all memory dynamically allocated in the function
When I think about this, I sense that I do not fully graps it. Listen to this.
The pointer in main() refers to 1 bookRecord. When adding nodes to this list, I do not mean to change this pointer at all. What I want to do is to take this pointer, travel to the end of the list by following the bookOrder->next field untill it refers to NULL and then attach the new record to it. If I make sure that I allocate memory, this seems possible which would imply that I do not have to pass a pointer to a pointer to a list, but only a pointer to the list. I have done that below, but this does not work, where is my reasoning flawed? Again, a bit lengthy and it may seem like I am losing myself in it, but as I said, I just need to really understand how this works.
Code:
//Solution 2 - single pointer, all memory dynamically allocated in the function
#include <stdio.h>
#include <stdlib.h>
typedef struct order {
char dir;
float price;
int size;
char instr[5];
};
struct bookOrder {
struct bookOrder *next;
struct order *order;
};
void printBook(struct bookOrder *book) {
int i = 0;
printf("------------------------------------\n");
while ((book != NULL) && (i < 11)){
printf("Printbook price:%f size:%i \n",(book->order)->price, (book->order)->size);
book = book->next;
++i;
if (i == 10) {
printf("Printing function may be artifically terminated");
}
}
if (i == 0) {
printf("Book is empty\n");
}
printf("------------------------------------\n");
}
void addOrder(struct bookOrder *book, struct order ord) {
struct bookOrder *walker = book;
struct bookOrder *newBook = malloc(sizeof(book));
struct order *newOrder = malloc(sizeof(ord));
newOrder->price = ord.price;
newOrder->size = ord.size;
newBook->order = newOrder;
newBook->next = NULL;
if (book == NULL) {
book->order = newBook->order;
book->next = NULL;
}
else {
while (walker->next != NULL)
walker = walker->next;
walker->next = newBook;
}
}
int main(void) {
//print empty book
struct bookOrder *book = NULL;
printBook(book);
//insert first order and print
struct order inpOrder;
inpOrder.price = 37;
inpOrder.size = 600;
addOrder(book, inpOrder);
printBook(book);
//insert second order and print
inpOrder.price = 67;
inpOrder.size = 340;
addOrder(book, inpOrder);
printBook(book);
return 0;
}
Thanks for your patience.