B+ tree insertion and searching - c++

I'm trying to implement insertion and searching of information in files using b+tree, while doing so im getting an error as undefined reference
I've made changes from the original code whose link is given below only the main.cpp and header file has been changed
main.cpp
#include <iostream>
#include <vector>
//#include <algorithm>
#include <fstream>
#include <string>
//#include <filesystem>
#include "BPTree.h"
void insertionMethod(BPTree** bPTree) {
int rollNo;
int age, marks;
std::string name;
std::cout << "Please provide the rollNo: ";
std::cin >> rollNo;
std::cout << "\nWhat's the Name, Age and Marks acquired?: ";
std::cin >> name >> age >> marks;
std::string fileName = "DBFiles/";
fileName += std::to_string(rollNo) + ".txt";
FILE* filePtr = fopen(fileName.c_str(), "w");
std::string userTuple = name + " " + std::to_string(age) + " " + std::to_string(marks) + "\n";
fprintf(filePtr, userTuple.c_str());
//fclose(filePtr);
(*bPTree)->insert(rollNo, filePtr);
fclose(filePtr);
std::cout << "Insertion of roll No: " << rollNo << " Successful"<<std::endl;
}
void searchMethod(BPTree* bPTree) {
int rollNo;
std::cout << "What's the RollNo to Search? ";
std::cin >> rollNo;
bPTree->search(rollNo);
}
int main() {
bool flag = true;
int option;
int maxChildInt = 4, maxNodeLeaf = 3;
std::cout << "Please provide the value to limit maximum child Internal Nodes can have: ";
std::cin >> maxChildInt;
std::cout << "\nAnd Now Limit the value to limit maximum Nodes Leaf Nodes can have: ";
std::cin >> maxNodeLeaf;
BPTree* bPTree = new BPTree(maxChildInt, maxNodeLeaf);
std::cout<<bPTree->getMaxLeafNodeLimit()<<std::endl;
do {
std::cout << "\nPlease provide the queries with respective keys : " << std::endl;
std::cout << "\tPress 1: Insertion \n\tPress 2: Search<< std::endl;
std::cin >> option;
switch (option) {
case 1:
insertionMethod(&bPTree);
break;
case 2:
searchMethod(bPTree);
break;
default:
flag = false;
break;
}
}while (flag);
return 0;
}
BPTree.h
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <string>
#ifndef NODE_H
#define NODE_H
class Node {
public:
bool isLeaf;
std::vector<int> keys;
Node* ptr2next;
union ptr {
std::vector<Node*> ptr2Tree; //Array of pointers to Children sub-trees for intermediate Nodes
std::vector<FILE*> dataPtr; // Data-Pointer for the leaf node
ptr(); // To remove the error !?
~ptr(); // To remove the error !?
} ptr2TreeOrData;
friend class BPTree; // to access private members of the Node and hold the encapsulation concept
public:
Node(){
this->isLeaf = false;
this->ptr2next = NULL;
}
};
class BPTree {
private:
int maxIntChildLimit; //Limiting #of children for internal Nodes!
int maxLeafNodeLimit; // Limiting #of nodes for leaf Nodes!!!
Node* root; Node* pparent = NULL; //Pointer to the B+ Tree root
void insertInternal(int x, Node** cursor, Node** child); //Insert x from child in cursor(parent)
Node** findParent(Node* cursor, Node* child){
if (cursor->isLeaf || cursor->ptr2TreeOrData.ptr2Tree[0]->isLeaf)
return NULL;
for (int i = 0; i < cursor->ptr2TreeOrData.ptr2Tree.size(); i++) {
if (cursor->ptr2TreeOrData.ptr2Tree[i] == child) {
pparent = cursor;
} else {
Node* tmpCursor = cursor->ptr2TreeOrData.ptr2Tree[i];
findParent(tmpCursor, child);
}
}
return &pparent;
}
public:
BPTree();
BPTree(int degreeInternal, int degreeLeaf){
this->maxIntChildLimit = degreeInternal;
this->maxLeafNodeLimit = degreeLeaf;
this->root = NULL;
}
int getMaxIntChildLimit();
int getMaxLeafNodeLimit()
{
return maxLeafNodeLimit;
}
void search(int key);
void insert(int key, FILE* filePtr);
};
#endif
Search and Insert code
The error im getting is
C:\Users\admin\AppData\Local\Temp\cctqZ0YA.o:insert.cpp:(.text$_ZN4NodeC1Ev[__ZN4NodeC1Ev]+0x20): undefined reference to `Node::ptr::ptr()'
collect2.exe: error: ld returned 1 exit status
I'm not so sure what Node::ptr::ptr() is could someone help out

The error message you get after deleting those declared but undefined constructor and destructor points to the actual problem. Why unions might need a constructor and destructor is better explained elsewhere, e.g. here and here.
You can get your code compiling by providing a trivial empty implementation.
ptr() {};
~ptr() {};

Related

Xcode errors with 2 duplicate symbols

I am still in the process of revising my program however the only issue I am receiving when trying to build is that 2 duplicate symbols for architecture x84_64. I have not had this issue in the past and I am running xcode 14.0.1 on Mac OSX monterey.
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <ctime>
#include <algorithm>
#include <sstream>
#include "Linked.hpp"
using namespace std;
time_t t = time(0);
tm* now = localtime(&t);
int main(){
LinkedList l;
Node* head = nullptr;
string line;
unsigned int sys_time = 0;
fstream myfile ("myfile.txt");
if (myfile.is_open()){
cout << "ready to proceed..." << endl;
}
ofstream outputFile ("output.txt");
if (outputFile.is_open()){
cout << "ready to proceed.." << endl;
}
outputFile << "Job_ID " << std::setfill('0') << std::setw(4) << "Priority_Value " << std::setfill('0') << std::setw(4) << "Arrival_Time" << std::setfill('0') << std::setw(4) << " Processing_Time" << endl;
while(!myfile.eof()){
std::replace(line.begin(), line.end(), ',', ' ');
stringstream ss(line);
getline(myfile, line);
string date;
int job_ID;
int priority_value;
int arrival_time;
int processing_time;
ss >> job_ID;
ss >> priority_value;
ss >> arrival_time;
ss >> processing_time;
l.enqueue(&head,job_ID, priority_value,arrival_time,processing_time);
}
return 0;
}
`
#ifndef Linked_hpp
#define Linked_hpp
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <ctime>
#include <algorithm>
#include <sstream>
using namespace std;
class Node {
public:
Node *next;
int jobID;
int priority_num;
int arrival_time;
int priority_value;
int wait_time;
Node(int jd, int pv, int at, int wt);
};
class LinkedList{
public:
Node *head;
static Node* firstNode(int jd, int pv, int at, int wt);
static int peek(Node** head);
static void enqueue(Node **head,int jd, int pv, int at, int wt);
static void dequeue(Node **head);
static int getLength(Node* head);
static bool isEmpty(Node* head);
static void display(Node* head);
LinkedList();
};
#endif /* LinkedList_hpp */
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <ctime>
#include <algorithm>
#include <sstream>
#include "Linked.hpp"
time_t t = time(0);
tm* now = localtime(&t);
using namespace std;
Node::Node(int jd, int pv, int at, int wt){
jobID = jd;
priority_value = pv;
arrival_time = at;
wait_time = wt;
next = nullptr;
}
Node* LinkedList::firstNode(int jd, int pv, int at, int wt){
Node *newNode = new Node(jd, pv, at, wt);
newNode->jobID = jd;
newNode->priority_value = pv;
newNode->arrival_time = at;
newNode->wait_time = wt;
return newNode;
}
LinkedList::LinkedList(){
head = NULL;
}
int LinkedList::peek(Node** head){
return (*head)->jobID;
}
void LinkedList::dequeue(Node** head){
Node* newNode = *head;
(*head) = (*head)->next;
free(newNode);
}
void LinkedList::enqueue(Node **head,int jd, int pv, int at, int wt){
Node* startNode = (*head);
Node* tempNode = firstNode(jd, pv, at, wt);
//This if statement will assign the head node the first item that is inserted into the linked list in order to begin the queue
if(head == NULL){
Node* newNode = firstNode(jd, pv, at, wt);
}
// If the head node's priority is greater than the next node then they are swapped.
else if((*head)->priority_value > pv){
tempNode->next = *head;
(*head) = tempNode;
}
else{
// If the head node is not null and its priority is less than the current node's priority that was just passed through the function then the head node stays as the highest priority while the the node that was just passed into this function gets compared to other nodes in the list.
while (startNode->next != NULL && startNode->next->priority_value < pv){
startNode = startNode->next;
}
// Either at the ends of the list
// or at required position
tempNode->next = startNode->next;
startNode->next = tempNode;
}
}
// This checks to see how many nodes are in the list and then returns that value
int LinkedList::getLength(Node* head){
Node *list = head;
int count = 0;
// the count variable is used to count the number of nodes while the while loop goes through each node in the list until it reaches the nullptr
while(list){
list = list->next;
count += 1;
}
return count;
}
//This boolean function checks to see if the queue is empty and returns either true or false back to main
bool LinkedList::isEmpty(Node* head){
return head == nullptr;
}
//This function displays the job's id, date, and its level of priority in the queue
void LinkedList::display(Node* head){
ofstream outputFile ("output.txt");
Node* list = head;
outputFile << "Job ID " << setw(10) << "Arrival Time " << setw(10) << "Priority ID " << endl;
while(list){
if (head == nullptr){
isEmpty(list);
}
else{
outputFile << list->jobID << " " << setw(10) << (now->tm_year + 1900) << "-" << (now->tm_mon +1) << "-" << now->tm_mday << setw(5) << list->priority_value << endl;
list = list->next;
}
}
}
I have tried going to the build settings to see if there was anything that wasn't set properly but all the settings are defaulted to C++.
OK figured it out (would have been faster with the error message).
Here's the first cpp file
time_t t = time(0);
tm* now = localtime(&t);
and here's the second cpp file
time_t t = time(0);
tm* now = localtime(&t);
Both t and now are defined globally in both cpp files. So you get a duplicate symbol error.
Since you only seem to be using those variables in the second cpp file, just deleting them from the first should solve your problem.

#ifndef not letting my files see what's in the header (C++)

So I created a Binary tree class and I want to separate the class definition from its member function definition by putting the class def in the .h file and the function definitions in the .cpp file. Then I would include the .h file into the .cpp file. Now I got this to all work and it works fine. the problem is when I want to put the name including guards. Because I need to include the .h file in the member function .cpp file and in another .cpp that uses the binary tree class, I have to include these guards. But for some reason, once I include them both .cpp files don't seem to "see" the contents of the header file. I'm new to using to ifndef so I'm so sure what I'm doing wrong. thank you
Here's the header file called node.h:
#ifndef NODE_H
#define NODE_H
#include <iostream>
#include <string>
#include <vector>
#include <stdbool.h>
using std::cout;
using std::endl;
typedef std::vector<std::string> vectorString;
class BST
{
vectorString data;
BST *left, *right;
public:
// Default constructor.
BST();
// Parameterized constructor.
BST(std::string);
// Insert function.
BST* Insert(BST*, std::string);
// Inorder traversal.
void Inorder(BST*);
// PreOrder Traversal.
void PreOrder(BST*);
// PostOrder Traversal
void PostOrder(BST*);
// string slicer
std::string strSlice(std::string);
// boolean isDuplicate
bool isDuplicate(std::string, vectorString);
// print vector
void printVector(vectorString);
};
#endif
and here's the member definition file called node.cpp
#include <iostream>
//#include "node.h"
#include <string>
#include <vector>
using std::cout;
using std::endl;
// Default Constructor definition.
BST ::BST()
: data(0)
, left(NULL)
, right(NULL)
{
}
// Parameterized Constructor definition.
BST ::BST(std::string value)
{
if(data.empty()){
data.push_back(strSlice(value));
}
data.push_back(value);
left = right = NULL;
}
// String slicing function definition
std::string BST ::strSlice(std::string word){
std::string word2 = "";
word2 += word[0];
word2 += word[1];
return word2;
}
// print vector function definition
void BST ::printVector(std::vector<std::string> dataVector){
for(int i = 0; i < dataVector.size(); i ++){
cout << dataVector.at(i) << " ";
}
}
// Insert function definition.
BST* BST ::Insert(BST* root, std::string value)
{
if (!root)
{
// Insert the first node, if root is NULL.
return new BST(value);
}
// Insert data.
if (strSlice(value).compare(root->data.at(0)) > 0)
{
// Insert right node data, if the 'value'
// to be inserted is greater than 'root' node data.
cout << value << " is being put in the right node " << value << " > " << root->data.at(0) << endl;
// Process right nodes.
root->right = Insert(root->right, value);
} else if (strSlice(value).compare(root->data.at(0)) == 0) {
cout << value << " is being put in the same node " << value << " = " << root->data.at(0) << endl;
root->data.push_back(value);
}
else
{
// Insert left node data, if the 'value'
// to be inserted is greater than 'root' node data.
cout << value << " is being put in the left node " << value << " < " << root->data.at(0) << endl;
// Process left nodes.
root->left = Insert(root->left, value);
}
// Return 'root' node, after insertion.
// cout << "after insert root is " << root << endl;
return root;
}
// Inorder traversal function.
// This gives data in sorted order.
void BST ::Inorder(BST* root)
{
if (!root) {
return;
}
Inorder(root->left);
printVector(root->data);
cout << endl;
Inorder(root->right);
}
void BST::PreOrder(BST* root){
if(!root){
return;
}
root->printVector(root->data);
cout << endl;
PreOrder(root->left);
PreOrder(root->right);
}
void BST::PostOrder(BST* root){
if(!root){
return;
}
PostOrder(root->left);
PostOrder(root->right);
root->printVector(root->data);
cout << endl;
}
errors:
C:\Users\14jjo\C++ Projects\Project 0\node.cpp:12:1: error: 'BST' does not name a type
BST ::BST()
^~~
C:\Users\14jjo\C++ Projects\Project 0\node.cpp:20:1: error: 'BST' does not name a type
BST ::BST(std::string value)
^~~
and here's the class that is trying to implement the binary tree class called P0.cpp:
#include <iostream>
//#include "tree.h"
#include "cleanString.h"
#include "node.h"
#include <fstream>
#include <string>
using std::cout;
using std::endl;
int main(int argc, char** argv) {
std::ifstream fileRead;
std::string word;
fileRead.open(argv[1]);
if(!fileRead){
cout << "this is not a file\n";
} else { cout << "this is a file\n"; }
fileRead >> word;
word = cleanString(word);
BST tree, *root = nullptr;
root = tree.Insert(root, word);
while (fileRead >> word) {
word = cleanString(word);
tree.Insert(root, word);
}
tree.Inorder(root);
fileRead.close();
return 0;
}
errors:
C:/Users/14jjo/C++ Projects/Project 0/P0.cpp:22: undefined reference to `BST::BST()'
C:/Users/14jjo/C++ Projects/Project 0/P0.cpp:23: undefined reference to `BST::Insert(BST*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
just #include "node.h" and make sure to compile all cpp files

How do you initialize template class members that uses other template classes?

I'm having trouble correctly setting up and accessing my member functions of a class. This node class is being used to build a Max Heap Tree. However, when the tree is being initialized, I'm getting garbage data and not what I am initializing it to.
#ifndef HEAPNODE_H_INCLUDED
#define HEAPNODE_H_INCLUDED
#include <iostream>
#include <cstdlib>
#include <array>
using namespace std;
template <class Type> class HeapNode {
private:
int key;
Type value;
public:
HeapNode(int key, Type const &value) {
this->key = key;
this->value = value;
}
// Returns the key of the node
int getKey() {
return key;
}
// Returns the value of the node
Type getValue() {
return value;
}
// Displays the node
void displayNode() {
cout << "Key: " << key << "\tValue: " << value << endl;
}
};
#endif
Here is the class that builds my Heap Tree. I've tried setting the initializations in the constructor every which way, and I'm still getting junk data. In addition, I set the constructor to take an integer, but when I'm creating a tree in my driver program, it won't let me put an argument for it which initiates an array of that size.
#ifndef MAXHEAPTREE_H_tINCLUDED
#define MAXHEAPTREE_H_INCLUDED
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include "HeapNode.h"
using namespace std;
template <class Type> class MaxHeapTree {
private:
HeapNode<Type> *array;
HeapNode<Type> *root;
int elementSize;
int height;
int leafCounter;
public:
// Constructor
MaxHeapTree(int n = 10) : elementSize(0), height(0), leafCounter(0) {
this->elementSize = elementSize;
this->height = height;
this->leafCounter = leafCounter;
HeapNode<Type> *array = new HeapNode<Type>[n];
}
// Destructor
~MaxHeapTree();
void arrayDisplay() {
cout << "Original array size: " << sizeof(array)/4 << endl;
}
// Returns the number of elements in the tree
int getSize() {
return elementSize;
}
// Returns the height of the tree
int getHeight() {
return height;
}
// Returns the number of leaves in the tree
int leaves() {
return leafCounter;
}
int countLines(const string fileName) {
string line;
int lineCount = 0;
ifstream myFile (fileName.c_str());
if (myFile.is_open()) {
while (getline(myFile, line)) {
lineCount++;
}
}
else {
cout << "Error opening file" << endl;
}
myFile.close();
return lineCount;
}
// Reads structure from a text file and builds a max heap
void buildTree(const string fileName) {
string line;
string key;
string value;
int lines = countLines(fileName);
int i = 0;
cout << "Lines: " << lines << endl;
HeapNode<Type> *newArray[lines];
cout << "Size of newArray: " << sizeof(newArray)/4 << endl;
ifstream myFile (fileName.c_str());
if (myFile.is_open()) {
while (getline(myFile, line)) {
key = line.substr(0, 1);
int x = atoi(key.c_str());
value = line.substr(1);
HeapNode<Type> *hNode = new HeapNode<Type>(x, value);
newArray[i] = hNode;
cout << "newArray[" << i << "] = ";
newArray[i]->displayNode();
i++;
}
}
else {
cout << "2 - Error opening file." << endl;
}
myFile.close();
}
};
#endif
How do you initialize template class members that uses other template classes?
In the same way you initialize members of non templates that don't use other templates.
when the tree is being initialized, I'm getting garbage data and not what I am initializing it to.
I was using MaxHeap<string> *heapTree1;
Well, there's your problem. Apparently you never created an instance of MaxHeap<string>.

Stuck on a linked list multiple class implementation

I have been working on this project for several days. This project contains 3 classes. The first is a DNA class that stores a DNA object. The second is a database class that reads a file and parses commands and data and deals with it accordingly. The last is a DNA list class that is a linked list of nodes that have pointers to DNA objects.
I've completed my linked list building method. It is required to be a push_back method that adds nodes at the end of the list. My problem arises when I try to search the list for a certain node. This has to be a method that returns a DNA* if a DNA object with id exists in the list; otherwise it returns NULL.
My plan is to use this method to print and also delete the node. I can't seem to get this method to work. Obviously I'm a little shaky with pointers. It took me several hours to implement my push_back method. Here is my code. Any guidance or help is appreciated.
DNA.h
#ifndef DNA_H
#define DNA_H
#include <string>
class DNA{
public:
// overloaded constructor for DNA class
DNA(std::string, int, std::string, int, int);
// print function
void print();
int getID();
private:
std::string m_label; // variable to hold label
int m_id; // variable to hold id
std::string m_sequence; // variable to hold sequence
int m_length; // variable to hold length
int m_index; // variable to hold index
};
#endif
DNA implementation
#include "DNA.h"
#include <iostream>
#include <string>
using namespace std;
DNA::DNA(string label, int id, string sequence, int length, int index){
m_label = label;
m_id = id;
m_sequence = sequence;
m_length = length;
m_index = index;
}
void DNA::print(){
cout << "DNA:" << '\t' << "label: " << m_label << '\t' << "ID: " << m_id << '\t' << "Sequence: " << m_sequence << endl << "Length: " << m_length << '\t' << "cDNAStartIndex: " << m_index << endl << endl;
}
int DNA::getID(){
return m_id;
}
Database class
#ifndef SEQUENCEDATABASE_H
#define SEQUENCEDATABASE_H
#include <string>
#include <fstream>
#include "DNA.h"
#include "DNAList.h"
class SequenceDatabase {
public:
SequenceDatabase();
// function to import the data file, parse the data, and perform the required output
void importEntries(std::string);
private:
DNAList list;
};
#endif
Database implemenation
#include "SequenceDatabase.h"
#include "DNA.h"
#include "DNAList.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
SequenceDatabase::SequenceDatabase(){
DNAList list;
}
// function reads in the filename creates a data stream and performs the requested actions
void SequenceDatabase::importEntries(string inputFile){
ifstream dnaFile(inputFile);
char command;
string label, sequence;
int id, length, index;
while(dnaFile >> command){
DNA* p;
if(command == 'D'){
dnaFile >> label >> id >> sequence >> length >> index;
DNA data(label, id, sequence, length, index);
p = new DNA(label, id, sequence, length, index);
list.push_back(p);
}
if(command == 'P'){
dnaFile >> id;
cout << "Printing " << id << " ..." << endl << endl;
p = list.findId(id);
if(p == nullptr)
cout << "Can not find item " << "(" << id << ")!" << endl << endl;
else
p-> print();
}
}
dnaFile.close();
}
Finally my list class
#ifndef DNALIST_H
#define DNALIST_H
#include "DNA.h"
#include "sequenceDatabase.h"
struct DNANode{
DNA* data;
DNANode* next;
DNANode* prev;
};
class DNAList{
public:
DNAList();
DNAList(DNA* newDNA);
void push_back(DNA* newDNA);
DNA* findId(int);
void obliterate(int id);
int size();
private:
DNANode* head;
int list_size;
};
#endif
List implementation
#include "DNA.h"
#include "sequenceDatabase.h"
#include "DNAList.h"
#include <iostream>
using namespace std;
DNAList::DNAList(){
head = new DNANode;
head->next = nullptr;
list_size = 0;
}
DNA* DNAList::findId(int id){ // this function is my problem
DNANode* current;
current = head;
while(current->next != nullptr){
if(current->data->getID() == id){
return current->data;
}
current = current->next;
}
return nullptr;
}
int DNAList::size(){
return list_size;
}
void DNAList::push_back(DNA* newDNA){
DNANode* current;
DNANode* last;
DNANode* p;
p = new DNANode;
p->data = newDNA;
last = nullptr;
current = head;
cout << "Adding " << newDNA->getID() << " ..." << endl << endl;
while(current != nullptr){
last = current;
current = current->next;
}
if(current == head->next){
p->next = nullptr;
p->prev = head;
head->next = p;
}
else{
p->next = current;
p->prev = last;
last->next = p;
}
list_size++;
}
I wasn't sure if I should post the whole code, but i felt it was needed to understand the problem. My problem arises when i try to call the find function to print the data in the node.
Your head member variable of DNAList is initialized with new DNANode. Since DNANode doesn't have an explicit constructor, its compiler generated one will not initialize the pointers data, next and prev. next is initialized on the next line, but data is left as a garbage value.
Inside findId, this line is executed:
if (current->data->getID() == id){
However the first time around the loop, current is pointing head. This means you are trying to look at the garbage value, which will possibly crash.
One solution is to change the findId function to start at head->next, another is to initialise the data pointer in head to nullptr and check that data is not nullptr before you access it.
A better solution might be to just have head as nullptr to start with, rather than having a dummy DNANode at the top. This would involve changing some of the code in push_back, but might make it easier to understand.
Aha. I think what is causing the problem is that towards the end of your SequenceDatabase::importEntries() method you are setting if(p=nullptr) instead of making the comparison if(p == nullptr). This is no doubt causing the error you see. This is a common mistake.

Binary Tree insert function not working correctly C++

I'm working on a program that uses a binary tree. The program reads from a text file, storing each word in a binary tree alphabetically and finds how many times the word appeared in the file.
The problem I'm having is that my insert function is not working (the program crashes when attempting to run it). I don't know what's exactly wrong, but I suspect it has to do with my else statement towards the end of the function that deals with the right side of the tree.
Any help with fixing it would be appreciated.
Header File
#include <iostream>
#include <string>
using namespace std;
#ifndef TREE_H
#define TREE_H
class Tree
{
public:
Tree();
Tree(string str);
void traversal (Tree *);
void read_file();
void insert(string str);
~Tree();
private:
Tree *left;
Tree *right;
string word;
int count;
};
#endif // TREE_H
Cpp File
#include <iostream>
#include <string>
#include <fstream>
#include "tree.h"
using namespace std;
Tree::Tree()
{
left = NULL;
right = NULL;
count = 0;
}
Tree::Tree(string s)
{
word = s;
}
Tree::~Tree() { }
void Tree::read_file()
{
ifstream myfile;
myfile.open("input.txt", ios::out | ios::in | ios::binary);
if(myfile.is_open()){
while(myfile.good()) {
string buffer;
while(true) {
char c = myfile.get();
if(c == '-' || c == '\'' || isalpha(c) ){
if(isupper(c)) c = tolower(c);
buffer+=c;
}
else break;
}
if(buffer.length() >= 4){
insert(buffer);
}
}
myfile.close();
traversal(this);
}
else { cout << "Unable to open file!" << endl; }
}
void Tree::insert(string str) {
if(str.empty()){ // Also I'm debating whether I need this or not since the string
// cannot possibly be empty as it's part of the condition before
//insert is even called.
this->word = str;
count++;
}
else if(this->word == str) count++;
else if(str < this->word){
if(this->left == NULL) this->left = new Tree(str);
else this->left->insert(str);
}
else {
if(this->right == NULL) this->right = new Tree(str);
else this->right->insert(str);
}
}
void Tree::traversal(Tree *T) {
if(T != NULL) {
traversal(T->left);
cout << T->word << " (" << count << ")" << endl;
traversal(T->right);
}
}
Main
#include <iostream>
#include "tree.h"
using namespace std;
int main()
{
Tree tree;
tree.read_file();
return 0;
}
the problem is that you have 2 constructors, and the second one doesn't initialize pointers left/right to NULL.
edit you are showing properties from different objects: use
cout << T->word << " (" << T->count << ")" << endl;
since the recursive procedure doesn't works calling the member function of the received T. You could do it static, or change it
void Tree::traversal() {
if(this) {
traversal(left);
cout << word << " (" << count << ")" << endl;
traversal(right);
}
}
Personally, I do prefer this last 'style'.
Tree::Tree()
{
word.clear();
left = NULL;
right = NULL;
count = 0;
}
Tree::Tree(string s)
{
word = s;
left = NULL;
right = NULL;
count = 0;
}