Reputation: 63
I have an assignment for uni in which I have to implement a binary search tree. It has to take information and write that to disk, and keep an index stored in the tree. However, whenever I call a function that has to do with the tree, the program crashes. The following code snippets are my bTree.h file, and the code which causes the crash.
/* binary tree ADT */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DATA_LENGTH 12
#define POS_LENGTH 8
struct INFO
{
char data[DATA_LENGTH];
int filePos;
};
struct NODE
{
struct INFO data;
struct NODE *left;
struct NODE *right;
};
/*
format for index data file
data identifier 12 bytes
position in file 8 bytes
--end of record-- total 20 bytes
*/
/*
Given a binary tree, return true if a node
with the target data is found in the tree. Recurs
down the tree, chooses the left or right
branch by comparing the target to each node.
*/
int lookupPos(struct NODE *node, char target[])
{
int length = strlen(target);
// 1. Base case == empty tree
// in that case, the target is not found so return false
if (node == NULL)
{
return -1;
}
else
{
// 2. see if found here, in which case return file pos.
if (strncmp(target, node->data.data, length) == 0)
{
return node->data.filePos;
}
else
{
// 3. otherwise recur down the correct subtree
if (strncmp(target, node->data.data, length) < 0)
{
return lookupPos(node->left, target);
}
else
{
return lookupPos(node->right, target);
}
}
}
}
/*
Give a binary search tree and a number, inserts a new node
with the given number in the correct place in the tree.
Returns the new root pointer which the caller should
then use (the standard trick to avoid using reference
parameters).
*/
struct NODE *insert(struct NODE *node, char info[], int pos)
{
int length = strlen(info);
// 1. If the tree is empty, return a new, single node
if (node == NULL)
{
struct INFO stuff;
strncpy(stuff.data, info, DATA_LENGTH);
stuff.filePos = pos;
node->data = stuff;
node->left = NULL;
node->right = NULL;
return(node);
}
else
{
// 2. Otherwise, recur down the tree
if (strncmp(info, node->data.data, length) <= 0)
{
node->left = insert(node->left, info, pos);
}
else
{
node->right = insert(node->right, info, pos);
}
return(node); // return the (unchanged) node pointer
}
}
struct NODE *loadTree(char filename[]) //cIndex.dat for customers, pIndex.dat for products
{
struct NODE *node;
char data[DATA_LENGTH];
char posStr[POS_LENGTH];
FILE* file;
file = fopen(filename,"rb");
char c;
fseek(file, 0, SEEK_SET);
while((c = fgetc(file)) != EOF) //reads until EOF char
{
fseek(file, -1, SEEK_CUR);
fread(data, sizeof(char), DATA_LENGTH, file);
fread(posStr, sizeof(char), POS_LENGTH, file);
insert(node, data, atoi(posStr));
}
fclose(file);
return node;
}
int saveTree(struct NODE *node, char filename[], int posInFile)
{
FILE *file;
file = fopen(filename, "r+b");
char c;
char posStr[POS_LENGTH];
fseek(file, posInFile, SEEK_SET);
while((c = fgetc(file)) != EOF)
{
fseek(file, -1, SEEK_CUR);
fwrite(node->data.data, sizeof(char), DATA_LENGTH, file);
sprintf(posStr, "%d", node->data.filePos);
fwrite(posStr, sizeof(char), POS_LENGTH, file);
posInFile = ftell(file);
saveTree(node->left, filename, posInFile);
saveTree(node->right, filename, posInFile);
}
fclose(file);
return 1;
}
int getSize(struct NODE *node)
{
if (node==NULL)
{
return 0;
}
else
{
return( getSize(node->left) + 1 + getSize(node->right));
}
}
And now the offending code snippets:
int filePos = getSize(tree);
and
insert(tree, cust.id, filePos);
saveTree(tree, "cIndex.dat", 0);
Can anyone help me?
Upvotes: 1
Views: 163
Reputation: 63481
You never allocate memory. In your insert
function:
if (node == NULL)
{
struct INFO stuff;
strncpy(stuff.data, info, DATA_LENGTH);
stuff.filePos = pos;
node->data = stuff;
node->left = NULL;
node->right = NULL;
return(node);
}
"If node
is NULL
then start assigning stuff to it". Yikes!
What you need to do is this:
node = malloc( sizeof(struct NODE) );
And the other thing I see as a major issue is this:
struct NODE *loadTree(char filename[])
{
struct NODE *node;
...
}
You must initialise node
to NULL
because you use its value inside insert
later on.
And Daniel Fischer has already pointed out that your strings in loadTree
may be one byte too short (thus you cannot reliably call strlen
and related string functions on them).
Upvotes: 2