How to insert data in linked structure - c

My insertion worked, so a new question, How do I set a data to NULL in C? Pls see the last part for illustration.!
I have defined a structure type
typedef struct node {
char* data;
int weight;
bool end_of_key;
struct node * left;
struct node * equal;
struct node * right;
} node_t;
int main(int argc, char *argv[]){
node_t* root=NULL;
int weight;
int i = 1;
insert(root,"cat",3);
insert(root,"at",2);
insert(root,"cute",4);
.....
return 0 ;}
This is my insert function
node_t* insert(node_t* pNode,char* word, int weight) {
/**
* Create a new pNode, and save a character from word
*/
pNode = (node_t*)malloc(sizeof(node_t));
if(*pNode->data == NULL){
pNode->left = NULL;
pNode->equal = NULL;
pNode->right = NULL;
pNode->data = word;
}
if (word[0] < *(pNode->data)) {
/**
* Insert the character on the left branch
*/
pNode->left = insert(pNode, word, weight);
}
else if (word[0] == *(pNode->data)) {
if ((word[1]) == '\0') {
/**
*set pNode end_of_key_flag to true and assign weight
*/
pNode->end_of_key = true;
pNode->weight = weight;
// printf("%c", *(pNode->data++));
}
else {
/**
* If the word contains more characters, try to insert them
* under the equal branch
*/
// printf("%c", *(pNode->data++));
pNode->equal = insert(pNode,word + 1, weight);
}
}
else {
/**
* If current char in word is greater than char in pData
* Insert the character on the right branch
*/
pNode->right = insert(pNode,word, weight);
}
return pNode;}
this code is trying to do this
So my insertion finally worked but it appears that it can only insert one thing,I am wondering how do I set data to NULL in C?
if(*pNode->data == NULL){
pNode->left = NULL;
pNode->equal = NULL;
pNode->right = NULL;
pNode->data = word;
}
I want to run this four lines of code when *pNode->data is empty but it apparently did not work the way I wanted it to.

Some improvements of your code
insert() must have first parameter to be node_t ** (see comments)
char *data must be char data, because every node contains only one char
weight can be calculated when the list is filled up
Here is corrected version of your code. Function get() is used to find the key in the filled up list (for testing).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node {
char data;
int weight;
struct node * left;
struct node * equal;
struct node * right;
} node_t;
void insert(node_t** pNode, char* word, int weight)
{
char data;
node_t **pNext;
node_t *pCurrent;
if (word == NULL)
{
return ;
}
data = word[weight];
if (*pNode == NULL)
{
*pNode = malloc(sizeof(node_t));
pCurrent = *pNode;
memset(pCurrent, 0, sizeof(node_t));
pCurrent->data = data;
}
else
{
pCurrent = *pNode;
}
if (data == pCurrent->data)
{
weight ++;
if (strlen(word) == weight)
{
pCurrent->weight = weight;
return;
}
pNext = &pCurrent->equal;
}
else if (data > pCurrent->data)
{
pNext = &pCurrent->right;
}
else
{
pNext = &pCurrent->left;
}
insert(pNext, word, weight);
}
int get(node_t** pNode, char *word, int weight)
{
char data;
node_t **pNext;
node_t *pCurrent;
if (word == NULL)
{
return 0;
}
data = word[weight];
if (*pNode == NULL)
{
return 0; // not found
}
pCurrent = *pNode;
if (data == pCurrent->data)
{
weight ++;
if (strlen(word) == weight)
{
return pCurrent->weight;
}
pNext = &pCurrent->equal;
}
else if (data > pCurrent->data)
{
pNext = &pCurrent->right;
}
else
{
pNext = &pCurrent->left;
}
return get(pNext, word, weight);
}
int main()
{
node_t * root = NULL;
insert(&root, "cat", 0);
insert(&root, "at", 0);
insert(&root, "cute", 0);
printf("cat=%d\n",get(&root,"cat",0)); // cat=3
printf("at=%d\n",get(&root,"at",0)); // at=2
printf("cute=%d\n",get(&root,"cute",0)); // cute=4
// todo: free memory
return 0;
}
The code is tested except freeing the memory.

First, there is something wrong with your insert() signature
(as already pointed by #MichaelWalz )
you'd rather
node_t* insert(node_t** pNode, char* word, int weight);
and then
insert(&root,"cute",4);
why don't you start fixing this and edit your post ?

Related

Issue recursively printing nodes from a kd tree via pointers

Firstly, forgive me if i do something wrong here since its my first time posting a question.
Can anyone tell me what i am doing incorrectly. When i attempt to iterate through a kd tree and print off all of my points, the 'pnt' attribute to the node i pass in changes its value to a memory address. I am looking at the 'print' and 'printPasser' function (both are located at the bottom). I know i'm doing something wrong with pointers but i just don't know what. If anyone spots something else wrong, please do comment
'''
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
char axis;
struct node *left;
struct node *right;
unsigned int val;
struct point *pnt;
//struct point pnt;
} Node;
typedef Node * NodePtr;
typedef struct point
{
unsigned int xVal;
unsigned int yVal;
char *Datum;
} Point;
typedef Point * PointPtr;
typedef struct kdtree
{
struct node *root;
unsigned int xBound;
unsigned int yBound;
} kdTree;
typedef kdTree *kdTreePtr;
//|--------------------------------------------------
kdTreePtr create();
void insert(kdTree * tree, struct point pntInsert);
void insertVal(kdTree * tree, unsigned int xIn, unsigned int yIn, char * Datum);
struct point repeater(struct node * tmp, struct point * pnt);
void delete(kdTree * tree, struct point * pnt);
void destroy(kdTree * tree);
struct point pop(kdTree * tree);
void print(kdTree * tree);
void printPasser(struct node * root);
void insertAlt(kdTree * tree, struct point pntInsert);
void insertPasser(Node * root, struct point pntInsert);
struct point nearestNeighbor(kdTree * tree, struct point * pntInit);
struct point nearestNicestNeighbor(kdTree * tree, struct point * pntInit);
void scale(kdTree * tree, unsigned int xScaler, unsigned int yScaler);
void resize(kdTree * tree, unsigned int xBound, unsigned int yBound);
void analyze(struct node *root);
//|--------------------------------------------------
int main(void)
{
kdTree * basic;
basic = malloc(sizeof(kdTreePtr));
basic = create();
resize(basic, 30, 30);
//Point pntr;
Point pnt1;
Point* pntr1 = &pnt1;
pntr1->xVal = 2;
pntr1->yVal = 7;
pntr1->Datum = "Big";
Point pnt2;
Point* pntr2 = &pnt2;
pntr2->xVal = 3;
pntr2->yVal = 8;
pntr2->Datum = "Bigger";
print(basic);
insertAlt(basic, pnt1);
printf("Point: (%u,%u) main tester\n", basic->root->pnt->xVal, basic->root->pnt->yVal);
print(basic);
insert(basic, pnt2);
print(basic);
return 0;
}
kdTreePtr create()
{
kdTreePtr newTree = malloc(sizeof(kdTree));
newTree->xBound = 0;
newTree->yBound = 0;
newTree->root = malloc(sizeof(NodePtr));
newTree->root->left = NULL;
newTree->root->right = NULL;
newTree->root->pnt = NULL;
return newTree;
}
void resize(kdTree * tree, unsigned int xBound, unsigned int yBound)
{
tree->xBound = xBound;
tree->yBound = yBound;
}
void insertAlt(kdTree * tree, struct point pntInsert)
{
if (tree->root->pnt == NULL && tree->root->left == NULL && tree->root->right == NULL)
{
puts("empty");
//if(tree->root->pnt != NULL)
// printf("Point: (%u,%u) root\n", tree->root->pnt->xVal, tree->root->pnt->yVal);
tree->root->pnt = &pntInsert;
printf("Point: (%u,%u) root end\n", tree->root->pnt->xVal, tree->root->pnt->yVal);
}
else
{
puts("Iterate");
insertPasser(tree->root, pntInsert);
}
}
void insertPasser(Node * root, struct point pntInsert)
{
if (root->pnt == NULL && root->left != NULL && root->right != NULL)
{
if (root->axis == 'y')
{
if (pntInsert.yVal >= root->pnt->yVal)
insertPasser(root->right, pntInsert);
else
insertPasser(root->left, pntInsert);
}
else
{
if (pntInsert.xVal >= root->pnt->xVal)
insertPasser(root->right, pntInsert);
else
insertPasser(root->left, pntInsert);
}
}
else
{
Node *leftChild;
Node *rightChild;
rightChild = malloc(sizeof(NodePtr));
leftChild = malloc(sizeof(NodePtr));
unsigned int lower;
unsigned int xDif,yDif;
if (pntInsert.xVal >= root->pnt->xVal)
{
xDif = abs(pntInsert.xVal - root->pnt->xVal);
lower = root->pnt->xVal;
}
else
{
xDif = abs(root->pnt->xVal - pntInsert.xVal);
lower = pntInsert.xVal;
}
if (pntInsert.yVal >= root->pnt->yVal)
{
yDif = abs(pntInsert.yVal - root->pnt->yVal) ;
lower = root->pnt->yVal;
}
else
{
yDif = abs(root->pnt->yVal - pntInsert.yVal) ;
lower = pntInsert.yVal;
}
if (xDif >= yDif)
{
root->axis = 'y';
root->val = ((unsigned int)xDif / 2) + lower;
if (pntInsert.xVal >= root->pnt->xVal)
{
puts("test 1");
rightChild->pnt = &pntInsert;
leftChild->pnt = root->pnt;
root->right = rightChild;
root->left = leftChild;
root->pnt = NULL;
}
else
{
puts("test 2");
rightChild->pnt = root->pnt;
leftChild->pnt = &pntInsert;
*(root->right) = *rightChild;
*(root->left) = *leftChild;
root->pnt = NULL;
}
}
else
{
root->axis = 'x';
root->val = ((unsigned int)yDif / 2) + lower;
if (pntInsert.yVal >= root->pnt->yVal)
{
puts("test 3");
rightChild->pnt = &pntInsert;
leftChild->pnt = root->pnt;
root->right = rightChild;
root->left = leftChild;
root->pnt = NULL;
}
else
{
puts("test 4");
rightChild->pnt = root->pnt;
leftChild->pnt = &pntInsert;
root->right = rightChild;
root->left = leftChild;
root->pnt = NULL;
}
}
}
}
void insertVal(kdTree * tree, unsigned int xIn, unsigned int yIn, char * Datum)
{
Point pntInsert;
PointPtr pntInsertPtr = &pntInsert;
pntInsert.xVal = xIn;
pntInsert.yVal = yIn;
pntInsert.Datum = Datum;
insertAlt(tree, pntInsert);
//printf("%u,", tree->root->pnt->xVal);
//printf("%u\n", tree->root->pnt->yVal);
//printf("%u,", tree->root->pnt->yVal);
//printf("%u\n", tree->root->pnt->xVal);
}
void print(kdTree * tree)
{
if (tree->root->pnt == NULL && tree->root->left == NULL && tree->root->right == NULL)
puts("blank");
else
{
printf("Point: (%u,%u) \n", tree->root->pnt->xVal, tree->root->pnt->yVal);
printPasser(tree->root);
}
}
void printPasser(struct node * root)
{
printf("Point: (%u,%u) \n", root->pnt->xVal, root->pnt->yVal);
//PointPtr rootHolder =
if (root->left == NULL && root->right == NULL && root->pnt != NULL)
{
printf("Point: (%u,%u) \n", root->pnt->xVal, root->pnt->yVal);
}
else
{
printPasser(root->left);
printPasser(root->right);
}
}
'''
everything looks alright until i pass the node pointer into the 'printPasser' function where i take the point of root and get a new value that just looks to be the pointer values cast to an unsigned int.
I identified the following memory-related issues in your code:
kdTree * basic;
basic = malloc(sizeof(kdTreePtr));
basic = create();
You initialize basic twice. This is not a problem in itself, but it results in a memory leak of size kdTreePtr. Remove the first assignment.
newTree->root = malloc(sizeof(NodePtr));
Whenever you allocate an new Node, you only allocate a pointer-sized chunk of memory, not the size appropriate for a Node. You need to allocated sizeof(Node) bytes. There are multiple occurrences.
After fixing those, your code does not trigger a segmentation fault anymore (when compiling with optimizations enabled) and the output remains stable.

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;
}

All Nodes in a linked list point to same object

The problem is somewhere in here....
char buffer[80];
char *name;
while (1) {
fgets(buffer, 80, inf); //reads in at most 80 char from a line
if (feof(inf)) //this checks to see if the special EOF was read
break; //if so, break out of while and continue with your main
name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");//get first token up to space
stock = newStock(name,...)
....
}
I'm working in C with generic linked lists. I made a list implementation that I've tested and know works with chars. I'm trying to add stocks (I created a stock struct) to the linked list, with each node of the linked list holding a stock struct, but when I finish reading in the stocks all of the nodes point to the same struct and I can't figure out why. Here's some snippets of my code
list *list = malloc(sizeof(list));
newList(list, sizeof(stock_t));
while(1) {
...
(read from file)
...
stock_t *stock;
stock = newStock(name, closes, opens, numshares, getPriceF, getTotalDollarAmountF,getPercentChangeF,toStringF);
addToBack(list, stock);
}
Here's the newStock function:
stock_t *newStock(char *name, float closingSharePrice, float openingSharePrice, int numberOfShares, getPrice getP, getTotalDollarAmount getTotal, getPercentChange getPercent, toString toStr) {
stock_t *stock = malloc(sizeof(stock));
stock->stockSymbol = name;
stock->closingSharePrice = closingSharePrice;
stock->openingSharePrice = openingSharePrice;
stock->numberOfShares = numberOfShares;
stock->getP = getP;
stock->getTotal = getTotal;
stock->getPercent = getPercent;
stock->toStr = toStr;
return stock;
}
In a way I see what's wrong. newStock returns a new pointer every time, but it always gets stored in the variable 'stock' which is what every node points to, so it's going to be equal to whatever the last pointer newStock returned was...but I don't see the way around this. I tried having newStock return just a stock_t, and doing addToBack(list, &stock), but that didn't solve the problem either.
Any help would be appreciated!
Here is some code from the list:
typedef struct node {
void *data;
struct node *next;
}node_t;
typedef struct {
int length;
int elementSize;
node_t *head;
node_t *tail;
} list;
void newList(list *list, int elementSize) {
assert(elementSize > 0);
list->length = 0;
list->elementSize = elementSize;
list->head = list->tail = NULL;
}
void addToBack(list *list, void *element) {
node_t *node = malloc(sizeof(node_t));
node->data = malloc(list->elementSize);
node->next = NULL; //back node
memcpy(node->data, element, list->elementSize);
if (list->length == 0) { //if first node added
list->head = list->tail = node;
}
else {
list->tail->next = node;
list->tail = node;
}
list->length++;
}
Here's code from the stock struct:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef float (*getPrice)(void *S);
typedef float (*getTotalDollarAmount)(void *S);
typedef float (*getPercentChange)(void *S);
typedef char *(*toString)(void *S);
typedef struct stock{
char *stockSymbol;
float closingSharePrice;
float openingSharePrice;
int numberOfShares;
getPrice getP;
getTotalDollarAmount getTotal;
getPercentChange getPercent;
toString toStr;
}stock_t;
The generic functions probably seem like overkill but this is for homework (if you couldn't tell already) so we were asked to specifically use them. I don't think that has anything to do with the problem though.
Here are the definitions for those functions anyway
float getPriceF(void *S) {
stock_t *stock = (stock_t*)S;
return stock->closingSharePrice;
}
float getTotalDollarAmountF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice) * (stock->numberOfShares));
}
float getPercentChangeF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice - stock->openingSharePrice)/(stock->openingSharePrice));
}
char *toStringF(void *S) {
stock_t* stock = (stock_t*)S;
char *name = malloc(20*sizeof(char));
//sprintf(name, "Symbol is: %s. ", (stock->stockSymbol));
return stock->stockSymbol;
}
void printStock(void *S) {
char *str = toStringF(S);
printf("%s \n", str);
}
And this is how I'm traversing the list:
typedef void (*iterate)(void *); //this is in the list.h file, just putting it here to avoid confusion
void traverse(list *list, iterate iterator) {
assert(iterator != NULL);
node_t *current = list->head;
while (current != NULL) {
iterator(current->data);
current = current->next;
}
}
And then in my main I just called
traverse(list, printStock);
I can't find any problems with your code (that would cause your problem, anyway - there are places where you don't check the return from malloc() and stuff like that, but those are not relevant to this question). You don't supply the definition of stock_t, so I made a new data struct, and a new couple of functions, otherwise I just copied and pasted the code you provided:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* Your code starts here */
typedef struct node {
void *data;
struct node *next;
}node_t;
typedef struct {
int length;
int elementSize;
node_t *head;
node_t *tail;
} list;
void newList(list *list, int elementSize) {
assert(elementSize > 0);
list->length = 0;
list->elementSize = elementSize;
list->head = list->tail = NULL;
}
void addToBack(list *list, void *element) {
node_t *node = malloc(sizeof(node_t));
node->data = malloc(list->elementSize);
node->next = NULL; //back node
memcpy(node->data, element, list->elementSize);
if (list->length == 0) { //if first node added
list->head = list->tail = node;
}
else {
list->tail->next = node;
list->tail = node;
}
list->length++;
}
/* Your code ends here */
/* I made a new struct, rather than stock, since you didn't supply it */
struct mydata {
int num1;
int num2;
};
/* I use this instead of newStock(), but it works the same way */
struct mydata * newNode(const int a, const int b) {
struct mydata * newdata = malloc(sizeof *newdata);
if ( newdata == NULL ) {
fputs("Error allocating memory", stderr);
exit(EXIT_FAILURE);
}
newdata->num1 = a;
newdata->num2 = b;
return newdata;
}
/* I added this function to check the list is good */
void printList(list * list) {
struct node * node = list->head;
int n = 1;
while ( node ) {
struct mydata * data = node->data;
printf("%d: %d %d\n", n++, data->num1, data->num2);
node = node->next;
}
}
/* Main function */
int main(void) {
list *list = malloc(sizeof(list));
newList(list, sizeof(struct mydata));
struct mydata * data;
data = newNode(1, 2);
addToBack(list, data);
data = newNode(3, 4);
addToBack(list, data);
data = newNode(5, 6);
addToBack(list, data);
printList(list);
return 0;
}
which outputs this:
paul#MacBook:~/Documents/src$ ./list
1: 1 2
2: 3 4
3: 5 6
paul#MacBook:~/Documents/src$
demonstrating that you have a 3 node list, with all nodes different and where you'd expect them to be.
Either there is some other problem in code you're not showing, or for some reason you are thinking each node points to the same struct when it actually doesn't.
One possibility is that you have a char * data member in your stock struct. It's impossible to tell from the code you provided, but it's possible that you really are creating different nodes, but they all end up pointing to the same name, so they just look like they're the same. If you're assigning a pointer to name, you should make sure it's freshly allocated memory each time, and that you're not just, for instance, strcpy()ing into the same memory and assigning the same address to each stock struct.
EDIT: Looks like that was your problem. This:
name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");
should be:
name = (char *) malloc(sizeof(char)*20);
....
strcpy(name, strtok(buffer, " "));
Right now, you malloc() new memory and store a reference to it in name, but then you lose that reference and your memory when you overwrite it with the address returned from strtok(). Instead, you need to copy that token into your newly allocated memory, as shown.

Doubly linked list: Incompatible pointer types

at the moment I'm working on an implementation of a balanced B-Tree in C. I decided to use doubly linked lists but I have run into some problems. At the moment I get warnings for line 94, 95 and 96 because apparently the pointer types are incompatible.
I really don't see how and any help would be greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int data1;
int data2;
int data2exists; // no: 0 , yes: 1
struct node * parent;
struct node * left;
struct node * middle;
struct node * right;
} node;
node * insert(int *, node *, node *);
void getInput(int *);
node * createNode(int *);
void quickSwap(node *, int *, int *, int *, int *);
node * splitLeaf(int *, int *, int *, node *, node *);
void printTree(node *);
void main() {
int input;
getInput(&input);
node * root = createNode(&input);
getInput(&input);
insert(&input, root, root); // returns current pos
getInput(&input);
insert(&input, root, root); // returns current pos
getInput(&input);
insert(&input, root, root); // returns current pos
printTree(root);
}
node * insert(int * input, node * root, node * currentPos) {
printf("data1: [%i], data2: [%i], d2exists: [%i], input: [%i]\n", currentPos->data1, currentPos->data2, currentPos->data2exists, *input);
if (currentPos->left == NULL && currentPos->middle == NULL && currentPos->right == NULL) {
// no children
if (*input > currentPos->data1 && currentPos->data2exists == 0) {
// data1 < input, no data2
currentPos->data2 = *input;
currentPos->data2exists = 1;
return(currentPos);
// printf("CASE1: data1 < input, no data2, no children\n");
}
if (*input < currentPos->data1 && currentPos->data2exists == 0) {
// data1 > input, no data2
currentPos->data2 = currentPos->data1;
currentPos->data1 = *input;
currentPos->data2exists = 1;
return(currentPos);
// printf("CASE2: data1 > input, no data2, no children\n");
}
if (currentPos->data2exists == 1) {
// data2 exists
int smallest;
int middle;
int largest;
quickSwap(currentPos, input, &smallest, &middle, &largest);
printf("s: [%i] m: [%i] l: [%i]\n", smallest, middle, largest);
root = splitLeaf(&smallest, &middle, &largest, currentPos, root);
}
}
return(currentPos);
}
void printTree(node * root) {
if (root->parent != NULL) {
printf("printTree() did not receive root!!!!\n");
return;
}
else {
printf("%i || %i", root->data1, root->data2);
printf("\n");
// printf("%i || %i", root->left->data1, root->left->data2);
// printf("\t\t");
// printf("%i || %i", root->middle->data1, root->middle->data2);
// printf("\t\t");
// printf("%i || %i", root->right->data1, root->right->data2);
// printf("\n");
}
}
node * splitLeaf(int * smallest, int * middle, int * largest, node * currentPos, node * root) {
// this function needs to return root!
if (currentPos->parent == NULL) {
// currentPos is root
// create a parent with median
node * root = createNode(middle);
node * left = createNode(smallest);
node * middle = createNode(largest);
// genau hier gehts weiter! hier müssen root, left und, middle verknüpft werden!
root->left = left;
root->middle = middle;
left->parent = middle->parent = root;
// printf("root-addr: %i, left->parent: %i\n", root, left->parent);
return(root);
}
}
void quickSwap(node * currentPos, int * input, int * smallest, int * middle, int * largest) {
// writes values to *smallest, *middle and *largest ordered by size
if (currentPos->data1 > currentPos->data2) {
*smallest = currentPos->data2;
*middle = currentPos->data1;
}
else {
*smallest = currentPos->data1;
*middle = currentPos->data2;
}
if (*input < *smallest) {
*largest = *middle;
*middle = *smallest;
*smallest = *input;
}
else if (*input < *middle) {
*largest = *middle;
*middle = *input;
}
else {
*largest = *input;
}
}
node * createNode(int * input) {
node * ptr = (node*) malloc(sizeof(node));
ptr->data1 = * input;
ptr->data2 = 0;
ptr->data2exists = 0;
ptr->parent = NULL;
ptr->left = NULL;
ptr->middle = NULL;
ptr->right = NULL;
return(ptr);
}
void getInput(int * input) {
printf("Enter a number\n");
scanf(" %i",input);
}
Aha! The problem is a tricky one. It has to do with the definition of your node struct. The members parent, left, middle and right are of type struct node but you typedefed the struct to be node directly. My guess is that GCC ignores the undefined struct node and hopes it's defined somewhere else.
In other words: the type node exists, but struct node doesn't. Therefore when you try to assign a node to a struct node GCC doesn't know what to do. So change
typedef struct {
...
} node;
to
typedef struct node {
...
} node;
Although it might be wiser to use another name for the struct node than the type node.
Some nitpicks:
GCC complains that main doesn't return an int (just return 0;)
In splitLeaf you're redeclaring the arguments int * middle to node * middle and the same with root.
splitLeaf doesn't return anything when currentPos->parent isn't NULL (though maybe you haven't finished the function yet)

Creating a binary search tree in C99

I've got a programming class assignment due tonight at 8 PM CDT that I'm having trouble with. We are to take a list of the following numbers via reading a file:
9
30
20
40
35
22
48
36
37
38
place them in an array (easy enough), and then read these into a binary search tree using C. The first number in the list is the number of elements in the tree. The rest are placed into the following struct:
typedef struct node_struct {
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
I think I've got the first part down pat. Take the stuff in using fscanf (I didn't choose to use this method, I like fgets better), call an insertion function on each member of the array, then call a "createNode" function inside the insertion function.
Problem is, I'm only getting one member into the BST. Furthermore, the BST must satisfy the condition node->left->data <= node->data < node->right->data... in other words, the nodes must be in order in the tree.
Here's what I have so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// def BST node struct
typedef struct node_struct {
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
// prototypes
Node* createNode(int data);
Node* bstInsert(Node* root, int data);
// helper function prototypes
void padding(char ch, int n);
void displayTree(Node* root, int depth);
int main(int argc, char **argv)
{
FILE *in = NULL;
int num_read, count=0, array_size = 0;
if(argc != 2){
printf("hw3 <input-file>\n");
return 1;
}
in = fopen(argv[1], "r");
if(in == NULL){
printf("File can not be opened.\n");
return 2;
}
// read in the first line to get the array size
fscanf(in, "%d", &array_size);
// declare the array
int array[array_size];
// read from the second line to get each element of the array
while(!feof(in)){
fscanf(in, "%d", &num_read);
array[count] = num_read;
count++;
}
fclose(in);
if (array_size != count) {
printf("data error. Make sure the first line specifies the correct number of elements.");
return 3;
}
Node *root1 = NULL, *root2 = NULL, *root3 = NULL;
int i;
// task1: construct a bst from the unsorted array
printf("=== task1: construct a bst from the unsorted array ===\n");
for (i = 0; i < array_size; i++) {
root1 = bstInsert(root1, array[i]);
}
displayTree(root1, 0);
return 0;
}
Node* bstInsert(Node* root, int data) {
if(root == NULL){
root = createNode(data);
if(root != NULL){
root= createNode(data);
}
else{
printf("%d not inserted, no memory available.\n", data);
}
}
Node* current, previous, right;
current = root;
previous = root->left;
next = root->right;
else{
if(previous->data <= current->data){
}
}
return root;
}
Node* createNode(int data) {
// TODO
Node* aRoot;
if(!data)
return NULL;
aRoot = malloc(sizeof(Node));
if(!aRoot){
printf("Unable to allocate memory for node.\n");
return NULL;
}
aRoot->data = data;
aRoot->left = NULL;
aRoot->right = NULL;
return aRoot;
}
/* helper functions to print a bst; You just need to call displayTree when visualizing a bst */
void padding(char ch, int n)
{
int i;
for (i = 0; i < n; i++)
printf("%c%c%c%c", ch, ch ,ch, ch);
}
void displayTree(Node* root, int depth){
if (root == NULL) {
padding (' ', depth);
printf("-\n");
}
else {
displayTree(root->right, depth+1);
padding(' ', depth);
printf ( "%d\n", root->data);
displayTree(root->left, depth+1);
}
}
main, createNode, displayTree, and padding are okay, I believe. It's bstInsert where I'm having trouble. I'm just not sure how to order things to create a valid tree.
EDIT:
I've edited bstInsert and injected some more logic. It should be printing out more leaves on the tree, but alas, it's only printing out the number "30". Here's the new function.
Node* bstInsert(Node* root, int data) {
if(root == NULL){
root = createNode(data);
if(root != NULL){
root= createNode(data);
}
else{
printf("%d not inserted, no memory available.\n", data);
}
}
else{
if(data < root->data){
bstInsert(root->left, data);
}
else if(data > root->data || data == root->data){
bstInsert(root->right, data);
}
}
return root;
}
You have to assign the newly created node pointer to the correct part of the tree. This code does that. The key change is using the return value from bstInsert() correctly. The other changes are cosmetic. Note that I checked the input array by printing it out; also, it is sensible to print out the BST as you build it.
Don't use feof() as a loop control condition. It is almost invariably wrong when used as a loop control, but at least you have to also check the input operation that follows. I've written a lot of programs in my time; I've hardly ever used feof() (I found two places in my own code with it; in both, it was correctly used to distinguish between EOF and an error after an input had failed.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// def BST node struct
typedef struct node_struct
{
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
// prototypes
Node *createNode(int data);
Node *bstInsert(Node *root, int data);
// helper function prototypes
void padding(char ch, int n);
void displayTree(Node *root, int depth);
int main(int argc, char **argv)
{
FILE *in = NULL;
int num_read, count=0, array_size = 0;
if (argc != 2)
{
printf("hw3 <input-file>\n");
return 1;
}
in = fopen(argv[1], "r");
if (in == NULL)
{
printf("File can not be opened.\n");
return 2;
}
// read in the first line to get the array size
fscanf(in, "%d", &array_size);
// declare the array
int array[array_size];
// read from the second line to get each element of the array
while (count < array_size && fscanf(in, "%d", &num_read) == 1)
array[count++] = num_read;
fclose(in);
if (array_size != count)
{
printf("data error. Make sure the first line specifies the correct number of elements.");
return 3;
}
for (int i = 0; i < array_size; i++)
printf("%d: %d\n", i, array[i]);
Node *root1 = NULL;
// task1: construct a bst from the unsorted array
printf("=== task1: construct a bst from the unsorted array ===\n");
for (int i = 0; i < array_size; i++)
{
root1 = bstInsert(root1, array[i]);
displayTree(root1, 0);
}
displayTree(root1, 0);
return 0;
}
Node *bstInsert(Node *root, int data)
{
if (root == NULL)
{
root = createNode(data);
if (root == NULL)
printf("%d not inserted, no memory available.\n", data);
}
else if (data < root->data)
root->left = bstInsert(root->left, data);
else
root->right = bstInsert(root->right, data);
return root;
}
Node *createNode(int data)
{
Node *aRoot;
aRoot = malloc(sizeof(Node));
if (!aRoot)
{
printf("Unable to allocate memory for node.\n");
return NULL;
}
aRoot->data = data;
aRoot->left = NULL;
aRoot->right = NULL;
return aRoot;
}
/* helper functions to print a bst; You just need to call displayTree when visualizing a bst */
void padding(char ch, int n)
{
for (int i = 0; i < n; i++)
printf("%c%c%c%c", ch, ch, ch, ch);
}
void displayTree(Node *root, int depth)
{
if (root == NULL) {
padding (' ', depth);
printf("-\n");
}
else {
displayTree(root->right, depth+1);
padding(' ', depth);
printf ( "%d\n", root->data);
displayTree(root->left, depth+1);
}
}
Ok, think about what you want to do in the different tree configurations:
when the tree is empty -> create a root node
when the tree isn't empty -> how do the value to be inserted and the value of the root compare?
above -> insert in the right subtree
below -> insert in the left subtree
equal -> do nothing (this actually depends on how your assignment tells you to treat duplicates)
From this basic algorithm, you should be able to figure out all the corner cases.
A simplified solution (naive insertion with recursion, data input noise removed):
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
static int nums[] = { 6, 8, 4, 1, 3, 7, 14, 10, 13 }; // instead of the user input
typedef struct _node {
int value;
struct _node *left;
struct _node *right;
} node;
node *node_new(int v)
{
node *n = malloc(sizeof(*n));
assert(n);
n->value = v;
n->left = NULL;
n->right = NULL;
return n;
}
void insert(node **tree, node *leaf)
{
if (*tree == NULL) {
*tree = leaf;
} else if (leaf->value > (*tree)->value) {
insert(&((*tree)->right), leaf);
} else {
insert(&((*tree)->left), leaf);
}
}
void dump(node *tree, int level)
{
static const char *pad = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
if (tree != NULL) {
printf("%sSelf: %d\n", pad + 16 - level, tree->value);
if (tree->left) {
printf("%sLeft node:\n", pad + 16 - level);
dump(tree->left, level + 1);
}
if (tree->right) {
printf("%sRight node:\n", pad + 16 - level);
dump(tree->right, level + 1);
}
} else {
printf("%sEmpty\n", pad + 16 - level);
}
}
int main()
{
size_t n = sizeof(nums) / sizeof(*nums);
int i;
node *tree = NULL;
for (i = 0; i < n; i++) {
insert(&tree, node_new(nums[i]));
}
dump(tree, 0);
// give some work to the kernel
return 0;
}
You should consider doing this recursively. Remember that each node is a tree in itself:
#include <stdio.h>
#include <stdlib.h>
typedef struct tree_struct {
int value;
struct tree_struct* left;
struct tree_struct* right;
} Tree;
Tree* addToTree(int value, Tree* tree)
{
if (tree == NULL) {
tree = malloc(sizeof(Tree));
tree->value = value;
tree->left = NULL;
tree->right = NULL;
} else {
if (value < tree->value) {
tree->left = addToTree(value, tree->left);
} else {
tree->right = addToTree(value, tree->right);
}
}
return tree;
}
int main(int argc, char** argv)
{
Tree* tree = NULL;
int in;
while (scanf("%d", &in) != EOF) {
tree = addToTree(in, tree);
}
return 0;
}

Resources