Pointer to linkedlist randomly changing - c

For one of my school assignments I have to make my own stack library and a POSTFIX calculator.
The calculator has to make use of the stack library and do some calculations.
I am pushing two different numbers to my stack. Number 6 and 3. The header should point to the most recently added node (LIFO). So when 6 is added:
HEADER -> 6 -> NULL
When 3 is being added:
HEADER -> 3 -> 6 -> NULL
When I print the value of my header after adding '6' it's good. It's printing 6.
However, when I print the value of my header BEFORE adding '3' it's printing '3'. When it still should print 6.
So a summary of my problem:
When adding another node to my linkedlist, the header suddenly points to the newest node before even changing it.
You may understand me better with some code and debugging results.
Btw: Don't mind the typedefs, I don't like them. My teacher wants us to use it.
typedef struct stackObject* pStackObject_t;
typedef struct stackObject
{
void* obj;
pStackObject_t next;
} StackObject_t;
typedef struct stackMEta* pStackMeta_t;
typedef struct stackMEta
{
pStackObject_t stack;
size_t objsize;
int numelem; //number of elements
int handle; //welke stack
pStackMeta_t next;
} StackMeta_t;
int mystack_push(int handle, void* obj)
{
**DELETED NON RELATED CODE BASED ON FEEDBACK**
if (currentMeta->handle == handle)
{
pStackObject_t newObject = malloc(sizeof(StackObject_t));
newObject->obj = obj;
printf("%s%d\n", "Wanting to push int to stack: ", *(int*)obj);
//First node
if (currentMeta->stack == NULL)
{
currentMeta->stack = newObject;
currentMeta->stack->next = NULL;
printf("%s%d\n", " FIRST Curentmeta->stack pointing to ", *(int*)currentMeta->stack->obj);
return 0;
}
else
{
printf("%s%d\n", "NOT FIRST Currentmeta->stack pointing to ", *(int*)currentMeta->stack->obj);
newObject->next = currentMeta->stack;
currentMeta->stack = newObject;
printf("%s%d\n", "Currentmeta->stack ", *(int*)currentMeta->stack->obj);
printf("%s%d\n", "Currentmeta->stack->next ", *(int*)currentMeta->stack->next->obj);
printf("%s%d\n", "Succesful pushed int to stack: ", *(int*)currentMeta->stack->obj);
return 0;
}
}
return -1;
}
Terminal:
Created stack with handle: 1 and objsize 4 bytes
Wanting to push int to stack: 6
FIRST Curentmeta->stack pointing to 6
Wanting to push int to stack: 3
NOT FIRST Currentmeta->stack pointing to 3
Currentmeta->stack 3
Currentmeta->stack->next 3
Succesful pushed int to stack: 3
My unit tests are performing good with this code. My calculator does not, while it's the same function call.

I found out that it was working 50/50. Using the same input values in another program resulted in good things.
I changed the code to this:
pStackObject_t newObject = malloc(sizeof(StackObject_t));
newObject->obj = malloc(sizeof(currentMeta->objsize));
memcpy(newObject->obj, obj, currentMeta->objsize);
Now it's working fine. The previous code was somehow using the old values, while it was already out of scope. Thanks everyone for the help.

Related

C Read from File into LinkedList

I have a text file that I need to read a populate a linked list. The file structure is like this.
Ant,Adam 10 5
Mander,Sally 4 3
King,May 6 6
King,Joe 9 6
Graph,Otto 2 5
Carr,Redd 1 3
The name is szName. The second int is iDepartTmUnits, and the last int is iTime;
I'm trying to read the input from stdin
It should insert EVT_ARRIVE and EVT_DEPART events into the simulation's eventList. Assuming you are using fgets and sscanf, please make certain you check the count returned from your sscanf.
// Event Constants
#define EVT_ARRIVE 1 // when a person arrives
#define EVT_DEPART 2 // when a person departs the simulation
We have these structures
typedef struct
{
char szName[16]; // Name
int iDepartTmUnits; // time units representing how long he/she stays around
} Person;
// Event typedef (aka Element)
typedef struct
{
int iEventType; // The type of event as an integer:
// EVT_ARRIVE - arrival event
// EVT_DEPART - departure event
int iTime; // The time the event will occur
Person person; // The person invokved in the event.
} Event;
// NodeLL typedef - these are the nodes in the linked list
typedef struct NodeLL
{
Event event;
struct NodeLL *pNext; // points to next node in the list
} NodeLL;
// typedefs for the ordered link list
typedef struct
{
NodeLL *pHead; // Points to the first node in the ordered list
} LinkedListImp;
typedef LinkedListImp *LinkedList;
// typedefs for the Simulation
typedef struct
{
int iClock; // clock time
LinkedList eventList; // A linked list of timed events
} SimulationImp;
typedef SimulationImp *Simulation;
Now where I am struggling is how to populate a linked list with this information.
Actually I'm struggling with a lot to grasp my head around this, so I'm sorry at the question being overly complex or overly simple.
First Thing I am struggling with
I'm declaring it as
void generateArival(Event eventM[])
I believe that is incorrect, because in my main, I wouldn't pass it the event, I believe I would pass it a Simulation implementation.
Second Thing I Am struggling with
Here is the code I have so far where I am too copy from the file into a linked list.
while(!feof(pFilePerson))
{
iLineCount++;
i++;
fgets(szInputBuffer, MAX_LINE_SIZE, pFilePerson);
iScanfCnt = sscanf(szInputBuffer,"%s %d %d\n",
event.person.szName,
event.iTime,
event.person.iDepartTmUnits,
);
}
Lastly
I am to input the EVT_ARRIVE and EVT_DEPART into the eventList.
I believe that to be something like this,
they are int 1 and 2 respectfully, so I would need something like iEvent = event.iEventType;
and input that into the sim->eventList
Any help is appreciated, I need a lot more time with this concept of linked lists, but this is breaking my head.
EDIT
I can print out the name but not the numbers
while(fgets(szInputBuffer, sizeof szInputBuffer, pFilePerson) != NULL)
{
// print the input buffer as is (it also has a linefeed)
//printf("Person # %d: %s\n", iLineCount, szInputBuffer);
sscanf(szInputBuffer,"%s",
event.person.szName);
sscanf(szInputBuffer, "%I64d",
&event.person.iDepartTmUnits);
//linkList.event.iTime);
printf("%-7s\n", event.person.szName);
printf("%d\n", event.person.iDepartTmUnits);
}

How to implement a 'Pop' function that returns the "popped" element (i.e the data/value) ? (linked list stacks)

Confused as to how to implement a single function that would at the same time pop the element and return it as return value.
So far all I've seen are pop functions that return a pointer to the new head of the stack.
Here's a start, but...
#define VALUE int
typedef struct node_t {
VALUE item;
struct node_t *next;
} node;
.
.
.
// Function
VALUE pop(node *stack_head) {
// Used to store the node we will delete
node *deleteNode = stack_head;
// Error Checking // <<====== (btw, is this actually necessary ?)
if (!deleteNode || !stack_head) {
if (!stack_head) fprintf(stderr, "\nPop failed. --> ...\n");
if (!deleteNode) fprintf(stderr, "\nPop Failed. --> ...\n");
return 0;
}
// Storing the value in a variable
VALUE popped_item = stack_head->item;
// Updating the head
stack_head = stack_head->next; <<====== THERE'S A PROBLEM HERE ! (i think)
// Freeing/Deleting the 'popped' node
free(deleteNode);
// Return 'popped' value
return popped_item;
}
.
.
.
stack_head = stack_head->next;
Doesn't actually change the address that the pointer stack_head (i.e the head of the stack) points to... and so the value is indeed returned for the first pop but subsequent pops return errors.
Yes because it is a local variable but then how would you change the actual pointer (the one that points to the head of the stack) to point to the new head of the stack?
The parameter stack_head is local to the function pop, so when you modify it the result is not visible outside of the function.
You need to pass the address of the variable you want to modify, then in the function you dereference the pointer parameter to change what it points to.
So change your function to this:
VALUE pop(node **stack_head) {
node *deleteNode = *stack_head;
if (!*stack_head) {
fprintf(stderr, "\nPop failed. --> ...\n");
return 0;
}
VALUE popped_item = (*stack_head)->item;
*stack_head = (*stack_head)->next;
free(deleteNode);
return popped_item;
}
And call it like this:
node *stack_head = NULL;
// do something to push onto the stack
VALUE v = pop(&stack_head);
Okay, this will be a pretty long digest, but hopefully worth it. You can see a testcase of the code I've presented as my conclusion here and obtain a modular version of the code here. My suggestion would be that you use a structure like this:
struct {
size_t top;
T value[];
}
The reason you probably shouldn't use classical linked lists for this (or anything, really) is covered by this video courtesy of Bjarne Stroustrup. The basis of the problem is that the majority of your overhead is in allocation and cache misses which don't occur so much when you keep everything in one allocation.
If I were to write this for convenient use, perhaps:
#define stack_of(T) struct { size_t top; T value[]; }
This should allow you to declare empty stacks fairly sensibly, like:
int main(void) {
stack_of(int) *fubar = NULL;
}
This is familiar enough to templates in other languages to work fairly well, and also not a hideous abuse of the preprocessor. I'm sure I've written a push_back function somewhere which we can adapt to this version of push which I've linked to externally as it's not important for the conclusion of this answer (bear with me here; we'll come back to that momentarily)...
So now we have stack_of(T) and push(list, value) which we can use like:
int main(void) {
stack_of(int) *fubar = NULL;
push(fubar, 42);
push(fubar, -1);
}
The simplest solution for pop might be something like:
#define pop(list) (assert(list && list->top), list->value[--list->top]))
... but this does suffer a drawback we'll discuss later. For now we have as a testcase:
int main(void) {
stack_of(int) *fubar = NULL;
int x;
push(fubar, 42);
push(fubar, -1);
x = pop(fubar); printf("popped: %d\n", x);
x = pop(fubar); printf("popped: %d\n", x);
x = pop(fubar); printf("popped: %d\n", x);
}
... and as you'll see during debug the assert fails during execution telling us we've popped more than we've pushed... probably a good thing to have. Still, this doesn't actually reduce the size of the stack. To do that we actually need something more like push again, except we get rid of these lines:
list->top = y; \
list->value[x] = v; \
So there's an opportunity for refactoring. Thus I bring you operate():
#define operate(list, ...) { \
size_t x = list ? list->top : 0 \
, y = x + 1; \
if ((x & y) == 0) { \
void *temp = realloc(list, sizeof *list \
+ (x + y) * sizeof list->value[0]); \
if (!temp) \
return EXIT_FAILURE; \
list = temp; \
} \
__VA_ARGS__; \
}
Now we can redefine push in terms of operate:
#define push(list, v) operate(list, list->value[x] = v; list->top = y)
... and pop looks kind of like it did before, but with an invocation of operate on the end to cause list to shrink (from quadruple its size, for example when you've popped 3 elements off of a list of 4) to no larger than double its size.
#define pop(list) (assert(list && list->top), list->value[--list->top]); \
operate(list, )
Summing it all up, you can see a testcase of the code I've presented here and obtain a modular version of the code here...

Last element value appears in first and last position when printing linked list

Happy New Year.
This question arises from a project to program a game called Laby-chiffres in C. To see the game look in the third batch of games on this link: http://www.rci-jeux.com/jeux/labychiffres/laby.swf .
Context:
I am using a linked list to store the path taken by a player through a grid of numbers. The player's aim is to find a path from the departure point to the arrival point, with a given length and given total of the numbers in the path. There is a switch statement for a menu and then one to accept the direction the player wants to move in. This works as I have code that shows that the 'passage' of the player to each number is recorded correctly
Problem:
When I try to print the path (which is a requirement of the assignment - and useful for the player to see) I print the path in the correct order, except that the last element, i.e. where the player most recently moved to, is shown at the start and the end of the list.
Example: Player makes moves through positions with values as follows. Starting with the departure point value 5 -> 8 -> 4-> 1. What is printed at each stage is:
5->
8->8->
4->8->4->
1->8->4->1->
What I have tried
I have looked at several other linked list questions, but none I have seen have the same issue that I have.
I have tried changing lots of things, but to be honest now more experimentally than anything. For example, changing the empiler function to add elements at the wrong end prints the path in the wrong order (as expected) but still prints the most recently reached number twice, just both at the start of the path rather than one at the start and one at the end.
Relevant functions
The lecturer has said explicitly that the printing needs to reverse the order so these are the printing functions:
void affiche_chemin (PLATEAU jeu, PILE pile){
afficher_pile_inverse(&jeu , jeu.chemin.P_sommet);
printf("\n");
}
void afficher_pile_inverse(PLATEAU *P_jeu, ELEMENT *P_cur){
if(P_cur != NULL){
afficher_pile_inverse(P_jeu,P_cur->P_suivant);
printf("%d->",lire_valeur_a(P_jeu,&P_cur->valeur));
}
}
lire_valeur_a reads the value in the grid, which is part of the PLATEAU structure given below and read in from a text file. This appears to work so I am not including it to try to keep the question length down.
The function to add elements is :
ELEMENT* empiler(PILE *P_liste, ELEMENT *P_elt_ajoute){
P_elt_ajoute ->P_suivant = P_liste->P_sommet;
P_liste->P_sommet = P_elt_ajoute;
return P_elt_ajoute;
}
Given the lecturers comments about needing to reverse the order to print correctly I think I am adding elements at the right end of the list.
These functions initialise the path, and allocate a new ELEMENT, and are just given for reference as used in the next extract.
void initialiser_pile(PILE *P_pile){
P_pile->P_sommet = NULL;
}
ELEMENT *nouvel_element (POSITION nouvelle_valeur){
ELEMENT *P_elt;
P_elt =(ELEMENT*) malloc(sizeof(ELEMENT));
if(P_elt ) { /* NULL equivalent to false like 0 */
P_elt->valeur = nouvelle_valeur;
P_elt->P_suivant = NULL;
}
return P_elt;
}
This code sets up the path for the first time when the text file for the game is read, so it is the first time empiler is used to add an element to a path. (This extract is from a long function using fscanf multiple times to read the game text file, and seems to work correctly.)
ELEMENT *P_sommet = nouvel_element(PLAT->dep);
if (P_sommet == NULL){
printf("Erreur d'allocation\n");
return 0;
}
initialiser_pile(&PLAT->chemin);
empiler (&PLAT->chemin,P_sommet);
PLAT->longcur = 1;
PLAT->sumcur=PLAT->grille[PLAT->dep.indl][PLAT->dep.indc];
The following function is used for adding elements during the game.
int choix_indep_jeu_update(PLATEAU *jeu, POSITION *new_pos, int pas, int dir){
ELEMENT *new = nouvel_element(*new_pos);//1 Make new element
if (new == NULL) return 0;
empiler( &jeu->chemin, new );//should add new element
jeu->longcur++;
jeu->sumcur = jeu->sumcur + lire_valeur_a(jeu, new_pos);
affiche_grille(*jeu);
affiche_chemin(*jeu,jeu->chemin);
return 1;
}
Data Structures
typedef struct position_st{
int indl;//indice of ligne
int indc;//indice of colonne
}POSITION;
typedef struct element_st{
POSITION valeur;
struct element_st *P_suivant;
}ELEMENT;
typedef struct pile_st{
ELEMENT * P_sommet;
}PILE;
typedef struct plat_st{
//########## GAME FILE INFORMATION
int nl; //number of lines in grid
int nc; //number of columns in grid
POSITION dep; //position du depart: dep.indl and dep.indc
POSITION arr; //position d'arrive: arr.indl and arr.indc
int longdem; //length demanded
int sumdem; //total demanded
int ** grille; //Playing grid
//#######INFO re GAME IN PROGRESS ########
int longcur; //longueur courant
int sumcur; //totale courant
PILE chemin; //The path
}PLATEAU;
I simplified your code and it seems to be working, assuming that you want empiler() to insert elements into the front of the list, so they end up in reverse order. I added afficher_pile_inverse1() so that the last value doesn't have a "->" after it. So the error is in creating the list or there's an issue with the grid function which you did not show.
#include <stdio.h>
#include <stdlib.h>
typedef int POSITION;
typedef struct element_st{
POSITION valeur;
struct element_st *P_suivant;
}ELEMENT;
typedef struct pile_st{
ELEMENT * P_sommet;
}PILE;
void empiler(PILE *P_liste, ELEMENT *P_elt_ajoute){
P_elt_ajoute ->P_suivant = P_liste->P_sommet;
P_liste->P_sommet = P_elt_ajoute;
}
void afficher_pile_inverse1(ELEMENT *P_cur){
if(P_cur != NULL){
afficher_pile_inverse1(P_cur->P_suivant);
printf("%d->",P_cur->valeur);
}
}
void afficher_pile_inverse(ELEMENT *P_cur){
if(P_cur != NULL){
afficher_pile_inverse1(P_cur->P_suivant);
printf("%d",P_cur->valeur);
}
}
void affiche_chemin (PILE pile){
afficher_pile_inverse(pile.P_sommet);
printf("\n");
}
int main(void){
ELEMENT ae[4] = {{0,NULL},{1,NULL},{2,NULL},{3,NULL}};
PILE P_liste = {NULL};
size_t i;
for(i = 0; i < 4; i++)
empiler(&P_liste, &ae[i]);
affiche_chemin(P_liste);
return 0;
}

Logical error for linked list in C

#include <stdio.h>
#include <stdlib.h>
#define UINT unsigned int
struct item
{
UINT time ; // time in tics which is used to order the list.
UINT id ; // penguin id number.
UINT event ; // event this item describes.
struct item *next ; // pointer to next item in list.
};
struct item *head=NULL;
struct item *trail=NULL;
void link_list(UINT time, UINT id, UINT event)
{
struct item *t=NULL;
static int i=0;
if(i==0)
{
head->time=time;
head->id=id;
head->event=event;
trail=head;
trail->next=NULL;
i++;
printf("Hello Word\n");
}
t=malloc(sizeof(struct item));
trail->next=t;
trail->time=time;
trail->id=id;
trail->event=event;
trail=t;
trail->next=NULL;
if(i!=0)
printf("I am \n");
}
int main(int argc, char *argv[])
{
UINT x[3]={4,5,7}, y[3]={40,50,60}, z[3]={100,900,500};
int i=0;
head=malloc(sizeof(struct item));
trail=head;
link_list(x[0], y[0], z[0]);
link_list(x[1], y[1], z[1]);
link_list(x[2], y[2], z[2]);
struct item *f=NULL;
f=head;
do
{
printf("trail: %d %d %d\n", f->time, f->id, f->event);
f=f->next;
}
while(f!=NULL);
return 0;
}
Good day,
I'm currently having a logical problem with my code implementation of my linked list logically. This code is the framework I am using to integrate it into a larger program which will use linked list so I need to get this right.
Basically what is happening is when I finally reach the do while loop which I use as a debugging line to see the contents of a linked list I will get this output on my command line:
trail: 4 40 100
trail: 5 50 900
trail: 7 60 500
trail: 0 0 0
I am expecting the output to be like this:
trail: 4 40 100
trail: 5 50 900
trail: 7 60 500
I have excluded the other printf's in my code as they are just used to check if I am indeed going through my functions properly. Also this might be unrelated but is there a better debugger for c under linux? Because the built in debugger goes crazy when it steps into a malloc command so I have to debug all programs inside my head. :(
If by built-in debugger you mean gdb, you can tell it to step over malloc(); if your program crashes in malloc, though, you have run into a memory allocation or use bug in your program.
One apparent bug is that you do not initialize "t" correctly in link_list(), and in particular t->next is garbage, and your program will probably crash when it tries to follow it. I think you mean to set t->time, t->id etc., not trail->time.
The best way to append to a linked list is usually to have a separate function that returns a new list item with all the fields initialized, and then in the routine to append, just manipulate pointers. It also helps if your list head is just a pointer, not a struct, but that's a style issue.
Best of all is to use a library that supplies linked lists for you, but that's no good if you are learning about linked lists!
You're appending a new node to the tail, then writing in your datum to the tail node, then moving the tail pointer to the new node:
t=malloc(sizeof(struct item));
trail->next=t;
trail->time=time;
trail->id=id;
trail->event=event;
trail=t;
trail->next=NULL;
t is set to a new node.
the next pointer of the current list tail is set to point to t
the time, id, and event fields of the node pointed by tail are written.
tail reference is now moved to t, which still contains no data.
There are a plethora of things that can improve this code, starting with using modular design for a "list" management, but this is your immediate problem.

Binary Tree of Strings returning wrong order

I am fairly new to C and have been learning from K&R's book The C Programming Language.
After doing the exercises on Binary trees I wanted to make a header for binary trees for
char*, long and double.
There is a function in the following code that has been giving me grief - it should fill an array of character pointers with the values stored in the tree in lexicographical order however it has a bug somewhere. Here's the code for the String Tree Header btree.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/************** TYPES **************/
typedef struct ctree
{
char *name;
ctree *left;
ctree *right;
};
/************** Globals **************/
static int c_inc = 0;
/************** Function Prototypes **************/
ctree *add_to_c_tree (ctree *cnode, char *name);
void print_c_tree (ctree *cnode);
ctree *c_tree_alloc (void);
void c_tree_free (ctree *cnode);
void return_c_tree (ctree *cnode, char **array);
/************** Function Definitions **************/
/* add_to_c_tree() : Adds a new node to a *character binary tree */
ctree *add_to_c_tree (ctree *cnode, char *name){
/* If the node is null, allocate memory for it,
* copy the name and set the internal nodes to null*/
if(cnode == NULL){
cnode = c_tree_alloc();
cnode->name = strdup(name);
cnode->left = cnode->right = NULL;
}
/* If initialised then add to the left node if it is lexographically
* less that the node above it else add it to the right node */
else{
if(strcmp(name, cnode->name) < 0)
cnode->left = add_to_c_tree(cnode->left,name);
else if(strcmp(name, cnode->name) > 0)
cnode->right = add_to_c_tree(cnode->right,name);
}
return cnode;
}
/* print_c_tree() : Print out binary tree */
void print_c_tree(ctree *cnode){
if (cnode != NULL) {
print_c_tree(cnode->left);
printf("%s\n",cnode->name);
print_c_tree(cnode->right);
}
}
/* return_c_tree() : return array of strings containing all values in binary tree */
void return_c_tree (ctree *cnode, char **array){
if (cnode != NULL) {
return_c_tree (cnode->left,array+c_inc);
c_tree_free(cnode->left);
*(array+c_inc++) = strdup(cnode->name);
// printf("arr+%d:%s\n", c_inc-1,*(array+(c_inc-1)));
return_c_tree (cnode->right,array+c_inc);
c_tree_free(cnode->right);
}
}
/* c_tree_alloc() : Allocates space for a tree node */
ctree *c_tree_alloc(void){
return (ctree *) malloc(sizeof(ctree));
}
/* c_tree_free() : Free's Memory */
void c_tree_free (ctree *cnode){
free(cnode);
}
Which I have been testing with bt.c:
#include "btree.h"
int main(void){
ctree *node = NULL; char *arr[100];
node = add_to_c_tree(node, "foo");
node = add_to_c_tree(node, "yoo");
node = add_to_c_tree(node, "doo");
node = add_to_c_tree(node, "woo");
node = add_to_c_tree(node, "aoo");
node = add_to_c_tree(node, "boo");
node = add_to_c_tree(node, "coo");
print_c_tree(node);
return_c_tree(node,arr);
for (int i = 0; i < 7; ++i)
{
printf("%d:%s ..\n",i, arr[i]);
}
return 0;
}
The reason for this question is that I have been having issues with the return_c_tree() function, which is meant to mimic the behaviour of K&R's print_c_tree() function except instead of recursively calling itself until a NULL ptr and printing out the name of the nodes in lexicographical order it is meant to add their names to an array of character ptrs and free the nodes memory.
However the output I get when run as above is:
aoo
boo
coo
doo
foo
woo
yoo
0:aoo ..
1:(null) ..
2:boo ..
3:doo ..
4:foo ..
5:coo ..
6:(null) ..
Which shows that the print function works fine but the return function obviously isn't.
The confusing thing is that if the call to printf() in return_c_tree() is uncommented this is the result:
aoo
boo
coo
doo
foo
woo
yoo
arr+0:aoo
arr+1:boo
arr+2:coo
arr+3:doo
arr+4:foo
arr+5:woo
arr+6:yoo
0:aoo ..
1:(null) ..
2:boo ..
3:doo ..
4:foo ..
5:coo ..
6:(null) ..
Which implies that it actually does add the strings in the right order.
Also I have tried it without the c_inc variable -> ie just incrementing array
before passing it to the right node which the produces the same results from the printf
in return_c_tree() but different from main:
arr+-1:aoo
arr+-1:boo
arr+-1:coo
arr+-1:doo
arr+-1:foo
arr+-1:woo
arr+-1:yoo
0:foo ..
1:yoo ..
2:coo ..
3:(null) ..
4:(null) ..
5:(null) ..
6:(null) ..
I'm rather confused, so If anyone can help I would appreciate it greatly. I'm sure I'm just incrementing it in the wrong place but I can't work out where.
I thought I had finally understood pointers but apparently not.
Best
P
Your problem is how you handle your pointer to array when you recursively call. This will fix your return_c_tree function:
void return_c_tree (ctree *cnode, char **array)
{
if (cnode != NULL) {
return_c_tree (cnode->left,array); // <--- CHANGED 2ND PARAM
c_tree_free(cnode->left);
*(array+c_inc++) = strdup(cnode->name);
return_c_tree (cnode->right,array); // <--- AGAIN, CHANGED 2ND PARAM
c_tree_free(cnode->right);
}
}
You're using a global variable c_inc to keep track of the current index into the array. However, when you recursively called return_c_tree, you passed in array+c_inc, but you did not offset c_inc to account for this. Basically, you double-counted c_inc each time.
While this solves your particular problem, there are some other problems with your code.
In general, using global variables is asking for trouble. There's no need to do it here. Pass c_inc as a parameter to return_c_tree.
Also, mixing global variables with recursion is especially prone to problems. You really want recursive routines to keep their state on the stack.
As a commenter pointed out, all of your code in btree.h should really be in btree.c. The point of header files is to define an interface, not for code.
(This is more stylistic) Your return_c_tree function is really two distinct functions: copy the elements of the tree (in order) into the array, and free the memory used by the tree. These two operations are conceptually distinct: there are times that you'll want to do one and not both. There can be compelling performance (or other) reasons to mix the two, but wait until you have some hard evidence.

Resources