Reputation: 99
I have a project I'm working on that works with Binary Search Trees and file input/output. The binary search tree seems to functioning properly, however one of the requirements is to be able to add data to the binary tree via input from a file (And later output all the binary tree data). I used the fgets+sscanf method to look through the file, and it appears that it grabs all the items correctly, but the strings get drastically altered. I suspect it to be a null terminator issue but cannot pinpoint where exactly I could fix it at. When I add nodes to the binary tree manually (not from the file), they are added without issue, and are written to a new text file without issue. The only issue comes from reading the data from a file, which is throwing some odd errors that modify my data (E.G. strings appear in weird formats like é@—Ç as opposed to the expected output of FirstName1 LastName1).
Also would like to apologize, I am still fairly new to C. So it may appear a little messy.
As noted in the code below, I attempted manually adding null terminators to the strings since I believed that to be the issue. I've attempted changing the file contents and adding null terminators there, and I've tried using fscanf method of reading the file instead as well. I researched other stackoverflow pages searching for something I might be missing, but I haven't found anything. I'm sure it's something silly that I've overlooked.
Again, these below text file contents are only concerning from what is added from the file. Anything I manually add by calling the addNode function with string literals works without problem
My 'input' text file that I tried adding students from (aka that addFile uses in my tests):
400085 FirstName1 LastName1 3.88 CompSci
400076 FirstName2 LastName2 2.77 LibertyArts
My 'output' text file that writeFile uses:
400085 é@—Ç 3.880000 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
400076 é@—Ç 2.770000 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
addFile Takes a string name, finds the file, and opens its contents
void addFile(char* name) {
FILE* myFile = fopen(name, "r");
if (myFile == NULL) {
perror(name);
return;
}
int tempId = 0;
char firstName[100];
char lastName[100];
double GPA = 0.0;
char major[100];
int res = 0;
char line[10000];
while (fgets(line, 1000, myFile) != NULL) {
res = sscanf(line, "%d %s %s %lf %s", &tempId, firstName, lastName, &GPA, major);
firstName[99] = '\0';
lastName[99] = '\0';
major[99] = '\0';
addNode(tempId, firstName, lastName, GPA, major);
}
fclose(myFile);
}
WriteFile Writes into the text file, testFile.txt the contents of the binary search tree
void preorder(struct Node* nodeAt) {
char buffer[10000];
snprintf(buffer, sizeof(buffer), "%d %s %s %lf %s \n", nodeAt->id, nodeAt->firstName, nodeAt->lastName, nodeAt->GPA, nodeAt->major);
strcat(tempString, buffer);
if (nodeAt->leftChild != NULL)
preorder(nodeAt->leftChild);
if (nodeAt->rightChild != NULL)
preorder(nodeAt->rightChild);
}
void writeFile() {
FILE* fp = fopen("testFile.txt", "w");
tempString = (char*) malloc(sizeof(char*) * 10000);
preorder(root);
fprintf(fp, "%s", tempString);
free(tempString);
tempString = "";
}
Other related functions that addFile calls
/*
createNode() method
"safe" way of creating the node. Also cleans up the code.
*/
struct Node* createNode(int id, char* firstName, char* lastName, double GPA, char* major) {
struct Node* myNode = (struct Node*) malloc(sizeof(struct Node));
if (myNode != NULL) {
myNode->id = id;
myNode->firstName = firstName;
myNode->lastName = lastName;
myNode->GPA = GPA;
myNode->major = major;
myNode->rightChild = NULL;
myNode->leftChild = NULL;
myNode->parent = NULL;
return myNode;
}
else
return NULL;
}
/*
addNode() + addNodeHelper() methods
Adds a node to the binary tree. The helper method is just recursive to make searching easier
*/
struct Node* addNodeHelper(struct Node* nodeAt, int id, struct Node* nodeToAdd) {
struct Node* temp = nodeAt;
if (temp->leftChild == NULL && id < temp->id) {
nodeAt->leftChild = nodeToAdd;
nodeAt->leftChild->parent = nodeAt;
}
else if (temp->rightChild == NULL && id > temp->id) {
nodeAt->rightChild = nodeToAdd;
nodeAt->rightChild->parent = nodeAt;
}
if (id < temp->id)
addNodeHelper(temp->leftChild, id, nodeToAdd);
else if (id > temp->id)
addNodeHelper(temp->rightChild, id, nodeToAdd);
}
void addNode(int id, char* firstName, char* lastName, double GPA, char* major) {
struct Node* myNode = createNode(id, firstName, lastName, GPA, major);
if (myNode != NULL) {
struct Node* findTheNode = findNode(root, myNode->id);
if (root == NULL) {
root = myNode;
return;
}
if (findTheNode != NULL) {
printf("ERROR: Student ID must be unique!\n");
return;
} else
addNodeHelper(root, myNode->id, myNode);
}
}
Any hints/recommendations are much appreciated :)
Upvotes: 0
Views: 60
Reputation: 780723
createNode
is just saving pointers to the strings that it's given. addFile
overwrites the same strings each time through the loop, so every node has the same pointers. Also, these are local variables, so the pointers become invalid after addFile
returns.
You need to make copies of the strings.
addNode(tempId, strdup(firstName), strdup(lastName), GPA, strdup(major));
Upvotes: 1