Click here to Skip to main content
15,886,919 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
My code stops running until the query "search flower rose" and does not continue to process the rest of the queries in in.txt. I think that the loop is exiting due to some other condition rather than reaching EOF but I am not entirely sure.

The other issue is that nothing is outputting to the out.txt file that I have created. This may be due to the EOF conditions but then again, not entirely sure.

Here is in.txt.
4 28 17
fish
animal
bird
fruit
animal cat 32
fish goldfish 20
animal dog 40
bird blackbird 10
animal bear 10
fruit mango 100
animal alligator 50
animal tiger 4
animal lion 2
fish swordfish 10
animal deer 5
animal cow 15
fish garfish 5
fish catfish 55
fish salmon 40
bird crow 21
bird dove 10
bird flamingo 15
fruit apple 50
fruit banana 50
fruit nectarine 10
fruit coconut 10
fruit peach 40
fruit apricot 30
fruit avocado 20
fruit cherry 100
fruit cranberry 100
animal horse 6
search fruit avocado
search fish tilapia
search animal cow
search bird crow
search bird cow
search animal cat
item_before animal deer
height_balance animal
height_balance bird
height_balance fish
search flower rose
count animal
count fruit
search animal koala
search animal cat
count animal
search fruit mango


What I have tried:

C++
#include <iostream>
#include <string.h>

using namespace std;

FILE *outfile;

class itemNode{
  public:
    char name [50];
    int count;
    itemNode *left, *right;

    itemNode(){
      name[0] = '\0';
      count = 0;
      left = NULL;
      right = NULL;
    }

    itemNode(char itemName[], int population){
      strcpy(name, itemName);
      count = population;
      left = NULL;
      right = NULL;
    }
};

class treeNameNode{
  public:
    char treeName[50];
    treeNameNode *left, *right;
    itemNode *theTree;

    treeNameNode(){
      treeName[0] = '\0';
      theTree = NULL;
      left = NULL;
      right = NULL;
    }

    treeNameNode(char name[]){
      strcpy(treeName, name);
      theTree = NULL;
      left = NULL;
      right = NULL;
    }
};

// Inserts data from the file into the Name tree and returns the root of the Name tree
treeNameNode* buildNameTree(FILE *infile, int N){
  treeNameNode *root = NULL;
  char name[50];
  for(int i = 0; i < N; i++){
    if(fscanf(infile, "%s", name) == EOF){
      break;
    }
    treeNameNode *newNode = new treeNameNode(name);
    if(root == NULL){
      root = newNode;
    }
    else{
      treeNameNode *temp = root;
      treeNameNode *parent = NULL;
      while(temp != NULL){
        parent = temp;
        if(strcmp(name, temp->treeName) > 0){
          temp = temp->right;
        }
        else{
          temp = temp->left;
        }
      }
      if(strcmp(name, parent->treeName) > 0){
        parent->right = newNode;
      }
      else{
        parent->left = newNode;
      }
    }
  }
  return root;
}

// Inserts a new name node into the Name tree and returns the root of the Name tree
treeNameNode* insertNameNode(treeNameNode *root, treeNameNode *newNode){
  if(root == NULL){
    return newNode;
  }
  if(strcmp(newNode->treeName, root->treeName) > 0){
    if(root->right != NULL){
      root->right = insertNameNode(root->right, newNode);
    }
    else{
      root->right = newNode;
    }
  }
  else{
    if(root->left != NULL){
      root->left = insertNameNode(root->left, newNode);
    }
    else{
      root->left = newNode;
    }
  }
  return root;
}

// Inserts a new item node into the item tree and returns the root of the item tree
itemNode* insertItemNode(itemNode *root, itemNode *newNode){
  if(root == NULL){
    return newNode;
  }
  if(strcmp(newNode->name, root->name) > 0){
    if(root->right != NULL){
      root->right = insertItemNode(root->right, newNode);
    }
    else{
      root->right = newNode;
    }
  }
  else{
    if(root->left != NULL){
      root->left = insertItemNode(root->left, newNode);
    }
    else{
      root->left = newNode;
    }
  }
  return root;
}

// Prints tree names from the Name tree by inorder traversal
void printTreeNames(treeNameNode *root) {
  if (root != NULL) {
    printTreeNames(root->left);
    cout << root->treeName << " ";
    fprintf(outfile, "%s ", root->treeName);
    printTreeNames(root->right);
  }
}

// Helper function to traverse the item tree inorder and print the data of the item trees
void traverse_itemTree(itemNode *root){
  if(root != NULL){
    traverse_itemTree(root->left);
    cout << root->name << " ";
    fprintf(outfile, "%s ", root->name);
    traverse_itemTree(root->right);
  }
}

// Takes the root of the Name Tree and prints the data of the Name Tree and the corresponding Item Trees
void traverse_in_traverse(treeNameNode *root){
  if(root != NULL){
    traverse_in_traverse(root->left);
    cout << "\n***" << root->treeName << "***" << endl;
    fprintf(outfile, "\n***%s***", root->treeName);
    traverse_itemTree(root->theTree);
    traverse_in_traverse(root->right);
  }
}

// Takes a name string and searches this name in the name tree and returns that node
treeNameNode* searchNameNode(treeNameNode *root, char treeName[50]){
  if(root == NULL){
    return NULL;
  }
  if(strcmp(root->treeName, treeName) == 0){
    return root;
  }
  else if(strcmp(root->treeName, treeName) > 0){
    return searchNameNode(root->left, treeName);
  }
  else{
    return searchNameNode(root->right, treeName);
  }
}

// Takes a name string and searches this name in the item tree and returns that node
itemNode* searchItemNode(itemNode *root, char itemName[50]){
  if(root == NULL){
    return NULL;
  }
  if(strcmp(root->name, itemName) == 0){
    return root;
  }
  else if(strcmp(root->name, itemName) > 0){
    return searchItemNode(root->left, itemName);
  }
  else{
    return searchItemNode(root->right, itemName);
  }
}

// Helper function to count the number of items
void countItems(itemNode *root, int *count){
  if(root != NULL){
    countItems(root->left, count);
    *count += root->count;
    countItems(root->right, count);
  }
}

// Prints the total number of items in a given tree
void count(treeNameNode *root, char treeName[50]){
  int count = 0;
  treeNameNode *temp = searchNameNode(root, treeName);
  countItems(temp->theTree, &count);
  cout << "\n" << treeName << " count " << count << endl;
  fprintf(outfile, "\n%s count %d\n", treeName, count);
}

// Searches for a particular item in a given tree and displays the count of the item if it is found
// Otherwise, prints item not found
// However, if the tree does not exist, then it prints tree does not exist
void search(treeNameNode *root, char treeName[50], char itemName[50]){
  treeNameNode *tree = searchNameNode(root, treeName);
  if(tree == NULL){
    cout << "\n" << treeName << " does not exist" << endl;
    fprintf(outfile, "\n%s does not exist\n", treeName);
  }
  itemNode *item = searchItemNode(tree->theTree, itemName);
  if(item == NULL){
    cout << "\n" << itemName << " not found in " << treeName << endl;
    fprintf(outfile, "\n%s not found in %s\n", itemName, treeName);
  }
  else{
    cout << "\n" << item->count << " " << itemName << " found in " << treeName << endl;
  }
}

// Helper function to traverse the item tree and count the items before the given item
void traverse_before(itemNode *root, char itemName[50], int *count){
  if(root != NULL){
    traverse_before(root->left, itemName, count);
    if(strcmp(root->name, itemName) < 0){
      (*count)++;
    }
    traverse_before(root->right, itemName, count);
  }
}

// Counts the items in a given tree coming before a given item name
void item_before(treeNameNode *root, char treeName[50], char itemName[50]){
  int count = 0;
  treeNameNode *tree = searchNameNode(root, treeName);
  traverse_before(tree->theTree, itemName, &count);
  cout << "\nitem before " << itemName << ": " << count << endl;
  fprintf(outfile, "\nitem before %s: %d\n", itemName, count);
}

// Helper function to find the height of a given tree
int height(itemNode *node){
  if(node == NULL){
    return 0;
  }
  int left = height(node->left);
  int right = height(node->right);
  
  return (left > right) ? left + 1 : right + 1;
}

// Finds whether a given tree is height balanced or not
void height_balance(treeNameNode *root, char treeName[50]){
  treeNameNode *tree = searchNameNode(root, treeName);
  int leftHeight = height(tree->theTree->left);
  int rightHeight = height(tree->theTree->right);
  int difference = abs(leftHeight - rightHeight);
  // If the difference is more than 1, then the tree is imbalanced
  if(difference > 1){
    cout << "\n" << treeName << ": left height " << leftHeight << ", right height " << rightHeight << ", difference " << difference << ", not balanced" << endl;
    fprintf(outfile, "\n%s: left height %d, right height %d, difference %d, not balanced\n", treeName, leftHeight, rightHeight, difference);
  }
  // Otherwise, the tree is balanced
  else{
    cout << "\n" << treeName << ": left height " << leftHeight << ", right height " << rightHeight << ", difference " << difference << ", balanced" << endl;
    fprintf(outfile, "\n%s: left height %d, right height %d, difference %d, balanced\n", treeName, leftHeight, rightHeight, difference);
  }
}

// Processes queries from the file and calls the appropriate functions
void query(treeNameNode *root, FILE *infile, int Q){
  for(int i = 0; i < Q; i++){
    char query[50];
    char treeName[50];
    char itemName[50];
    if(fscanf(infile, "%s", query) == EOF){
      break;
    }
    if(strcmp(query, "search") == 0){
      if(fscanf(infile, "%s %s", treeName, itemName) == EOF){
        break;
      }
      search(root, treeName, itemName);
    }
    else if(strcmp(query, "item_before") == 0){
      if(fscanf(infile, "%s %s", treeName, itemName) == EOF){
        break;
      }
      item_before(root, treeName, itemName);
    }
    else if(strcmp(query, "height_balance") == 0){
      if(fscanf(infile, "%s", treeName) == EOF){
        break;
      }
      height_balance(root, treeName);
    }
    else if(strcmp(query, "count") == 0){
      if(fscanf(infile, "%s", treeName) == EOF){
        break;
      }
      count(root, treeName);
    }
  }
}

int main(){
  FILE *infile = fopen("in.txt", "r");
  outfile = fopen("out.txt", "w");
  int N, I, Q;
  if(fscanf(infile, "%d %d %d", &N, &I, &Q) == EOF){
    return 0;
  }
  treeNameNode *root = buildNameTree(infile, N);
  for(int i = 0; i < I; i++){
    char treeName[50], itemName[50];
    int population;
    if(fscanf(infile, "%s %s %d", treeName, itemName, &population) == EOF){
      break;
    }
    itemNode *newNode = new itemNode(itemName, population);
    treeNameNode *tree = searchNameNode(root, treeName);
    tree->theTree = insertItemNode(tree->theTree, newNode);
  }
  printTreeNames(root);
  traverse_in_traverse(root);
  query(root, infile, Q);
  fclose(infile);
  fclose(outfile);
}
Posted
Comments
jeron1 20-Mar-24 14:14pm    
Is it possible to step through the code using a debugger?
Andre Oosthuizen 20-Mar-24 15:14pm    
I agree with Jeron, it is a lot of code for us to try and find a bug to identify the problem. Rather be specific and point to a line with an actual error than to dump all code here. Once we know where the problem or waht the errors are, we can help.
merano99 20-Mar-24 22:03pm    
There are so many mistakes, you have a free choice.

Look at your search function. What happens when an item is not found? You clearly print the fact that the item does not exist, but then what happens? You might need either a return statement somewhere or wrap part of the function in an else clause.
 
Share this answer
 
Several things don't fit together in this program.
The following excerpt alone is creepy:
C++
for (int i = 0; i < I; i++) {
    char treeName[50], itemName[50];
    int population;
    if (fscanf(infile, "%s %s %d", treeName, itemName, &population) == EOF) {
        break;
    }
    itemNode* newNode = new itemNode(itemName, population);
    treeNameNode* tree = searchNameNode(root, treeName);
    tree->theTree = insertItemNode(tree->theTree, newNode);
}

1. The use of char arrays and fscan instead of more suitable C++ data types and functions.
2. Since some lines only have two values, the population remains undefined.
3. The fscanf function detects if too few elements have been read, but it is not checked properly.
4. Reading character strings with the scanf() function is critical.
5. In principle, the allocation of memory can fail, which is not taken into account.
6. The function searchNameNode() can return a nulptr, which is not noticed.
7. The function searchNameNode() is a recursive function, why is it called several times in a loop?
8. The parameter passing of some functions is very bad, because unnecessarily much is copied
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900