I am making a program that reads a .CSV file and loads it into binary search trees to sort its content, since I managed to load the .CSV and implement the tree however the content of the file is:
1, Peter, 230151515
5, Merrick, 25551561
7, Lucky, 4301616199
2, luis, 2589191919
16, Alfredo, 25891919
8, Linda, 129616919
I am using the first data of each row as a key and with the code that I carry, it orders it correctly, however I want it to show the rest of the row, not just the key, someone could tell me how I could do that, to show all the data of each key ordered.
output:
1
2
5
7
8
16
What I want to print would be something like:
1 Peter 230151515
2 Luis 2589191919
5 Merrick 25551561
7 Lucky 4301616199
8 Linda 129616919
16 Alfredo 25891919
Someone to help me correct my mistake please.
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
struct node {
int key;
string name;
int num;
struct node *left, *right;
};
vector<node> persons;
struct node *newNode(int item)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->key = item;
temp->left = temp->right = NULL;
return temp;
}
void inorder(struct node *root)
{
if (root != NULL)
{
//cout<<"\t";
inorder(root->left);
printf("\t%d\n", root->key);
inorder(root->right);
}
}
struct node* insert(struct node* node, int key)
{
/* If the tree is empty, return a new node */
if (node == NULL) return newNode(key);
/* Otherwise, recur down the tree */
if (key < node->key)
node->left = insert(node->left, key);
else if (key > node->key)
node->right = insert(node->right, key);
/* return the (unchanged) node pointer */
return node;
}
struct node * minValueNode(struct node* node)
{
struct node* current = node;
/* loop down to find the leftmost leaf */
while (current && current->left != NULL)
current = current->left;
return current;
}
int main()
{
struct node *root = NULL;
ifstream fin("data.txt");
if (!fin)
{
cout << "File not open\n";
return 1;
}
string line;
const char delim = ',';
while (getline(fin, line))
{
istringstream ss(line);
node person;
ss >> person.key; ss.ignore(10, delim);
getline(ss, person.name,delim);
ss >> person.num;
if (ss)
persons.push_back(person);
}
for (unsigned int i=0; i< persons.size(); i++)
{
cout << setw(5) << persons[i].key<< setw(20) << persons[i].name<< setw(15) << persons[i].num << '\n';
root = insert(root, persons[i].key);
insert(root, persons[i].key);
}
cout << "\n\nInorder:\n";
// cout<<node.name;
inorder(root);
/*/cout<<"\nDelete 50\n";
root = deleteNode(root, 50);
cout<<"Inorder traversal of the modified tree \n";
inorder(root);/*/
/*
insert(root, 80);*/
return 0;
}
When you are printing out the key, you can also print out the other information of each node. Here's a solution using cout:
void inorder(struct node *root)
{
if (root != NULL)
{
inorder(root->left);
std::cout << root->key << " " << root->name << " " << root->num << "\n";
inorder(root->right);
}
}
There were some main problems and some other problems. The main problems were that you didn't store and print all data. I did the following:
Clean up includes
Remove using namespace std;
Rename struct node to Node
Add a struct for Person next to the struct for Node
Add a constructor for Person to Node
Make insert a method
Use smart pointers. One problem of dynamic memory allocation is that you have to clean up but you didn't
#include <iostream>
#include <iomanip>
#include <fstream>
#include <memory>
#include <string>
#include <sstream>
#include <vector>
struct Person {
int key;
std::string name;
int num;
};
struct Node : Person {
Node(const Person &person) : Person(person) {}
std::unique_ptr<Node> left, right;
void insert(const Person &person);
};
void Node::insert(const Person &person) {
/* recur down the tree */
if (key > person.key) {
if (left)
left->insert(person);
else
left = std::make_unique<Node>(person);
} else if (key < person.key) {
if (right)
right->insert(person);
else
right = std::make_unique<Node>(person);
}
}
std::vector<Person> persons;
void inorder(Node *root) {
if (root) {
// cout<<"\t";
inorder(root->left.get());
std::cout << '\t' << root->key << ' ' << root->name << ' ' << root->num << '\n';
inorder(root->right.get());
}
}
Node *minValueNode(Node *node) {
Node *current = node;
/* loop down to find the leftmost leaf */
while (current && current->left) current = current->left.get();
return current;
}
int main() {
std::unique_ptr<Node> root;
std::ifstream fin("data.txt");
if (!fin) {
std::cout << "File not open\n";
return 1;
}
std::string line;
const char delim = ',';
while (std::getline(fin, line)) {
std::istringstream ss(line);
Person person;
ss >> person.key;
ss.ignore(10, delim);
std::getline(ss, person.name, delim);
ss >> person.num;
if (ss) persons.push_back(person);
}
for (unsigned int i = 0; i < persons.size(); i++) {
std::cout << std::setw(5) << persons[i].key << std::setw(20)
<< persons[i].name << std::setw(15) << persons[i].num << '\n';
if (!root) root = std::make_unique<Node>(persons[i]);
else root->insert(persons[i]);
}
std::cout << "\n\nInorder:\n";
// cout<<node.name;
inorder(root.get());
/*/cout<<"\nDelete 50\n";
root = deleteNode(root, 50);
cout<<"Inorder traversal of the modified tree \n";
inorder(root);/*/
/*
insert(root, 80);*/
return 0;
}
Related
I'm trying to add data to a binary tree, however when I run a method that prints the data of the binarytree in order, nothing prints, and the program exits when it should be printing. I've tested it to see if data is actually being added by having the name and weight values of the rootNode print themselves inside the add method everytime its called, but I cannot get the same results inside of the inOrder method. I believe my issue has something to do with the node being passed.
#include <iostream>
using namespace std;
struct node {
int weight;
string name;
node *left, *right;
};
struct node* newNode(int dataw, string datan)
{
struct node* node = (struct node*)malloc(sizeof(struct node));
node->weight = dataw;
node->name = datan;
node->left = NULL;
node->right = NULL;
return (node);
}
void add(node *rootNode, int dataw, string datan)
{
int lowest_weight;
if (rootNode == NULL )
{
rootNode = newNode(dataw,datan);
lowest_weight = dataw;
}
else
{
if (datan < rootNode->name)
{
if (rootNode->left == NULL)
{
rootNode->left = newNode(dataw,datan);
}
else
{
add(rootNode->left,dataw,datan);
}
}
else
{
if (rootNode->right == NULL)
{
rootNode->right = newNode(dataw,datan);
}
else
{
add(rootNode->right, dataw, datan);
}
}
}
}
void inOrder(node *next)
{
if (next!=NULL)
{
inOrder(next->left);
cout << next->name << " " << next->weight << endl;
inOrder(next->right);
}
}
int main()
{
node *rootNode = NULL;
int height {}, leaves {}, weight {};
string name;
do
{
cout << "Enter name: ";
cin >> name;
if (name == "-1")
break;
cout << "Enter weight: ";
cin >> weight;
add(rootNode, weight, name);
} while (name!="-1");
inOrder(rootNode);
return 0;
}
Resolved it, had to assign the rootNode declaration to a new node method call so the data is not always NULL
node *rootNode = newNode(weight,name);
I am checking data of head node in constructor and its ok, but when i am checking it in the function then its gone. Why is it such a ghost this pointer ?
header for queue
#ifndef QUEUE_H
#define QUEUE_H
#include "Node.h"
#include "LinkedList.h"
class Queue
{
public:
Queue();
~Queue();
void addTail(Node* newNode);
Node* deleteHead();
int isEmpty();
void PrintQueue(char* outName);
protected:
private:
Node* head;
Node* tail;
LinkedList* myList;
};
#endif // QUEUE_H
queue class
#include "Queue.h"
Queue::Queue()
{
//constructor
myList = new LinkedList();
head = myList->getHead();
std::cout<<" head here is " << head->getData()<<std::endl; //
std::cout<<" next after head is " << head->getNext()->getData()<<std::endl; //
tail = myList->getTail();
}
void Queue::addTail(Node* newNode)
{
std::cout<<"inserting before tail (queue)"<<std::endl;
std::cout<<"new node is " << newNode->getData() <<std::endl;
std::cout<<" head here is " << myList->getHead()->getData() <<std::endl;
myList->insertLast(newNode);
}
Node* Queue::deleteHead()
{
if(isEmpty()){
std::cout<<"Queue is empty. Cannot remove anything anymore. Add more data to the queue!"<<std::endl;
return head;
}
return myList->removeFirst();
}
int Queue::isEmpty()
{
return myList->isEmpty();
}
void Queue::PrintQueue(char* outName)
{
Node* cur = head->getNext(); //store current node to keep track. Set it to one after the head
std::ofstream outfile;
outfile.open(outName, std::ios::app);
outfile << "Printing the values of the queue: ";
std::cout<<"Printing the values of the queue: "<<std::endl;
while(cur != tail)
{
std::cout<< cur->getData()<<", "<<std::endl; //print to the console
outfile << cur->getData() <<", "; //print to file
}
outfile.close();
}
Queue::~Queue()
{
//destructor
delete myList;
}
Main function
#include <iostream>
#include <fstream>
#include <string>
#include "Stack.h"
//#include "Stack.cpp"
#include "LinkedList.h"
//#include "LinkedList.cpp"
#include "Node.h"
//#include "Node.cpp"
#include "HashTable.h"
//#include "HashTable.cpp"
using namespace std;
int main( int argc, char* argv[] )
{
//specifying the in and out files
char* inFileName = argv[1];
char* outFileName = argv[2];
std::fstream infile (inFileName) ; // input file
//open the input file and find largest integer
int num;
int largest = 0;
Stack * myStack = new Stack();
char buffer[33]; //create a buffer for using with itoa
std::ofstream outfile;
outfile.open(outFileName);
if ( !infile.is_open() ) //check if input file is open
cout<<"Could not open file\n";
else {
while (infile >> num) { // read file int by int and check if current is not the largest
if(num > largest) largest = num;
Node *newNode= new Node(itoa(num,buffer,10));
myStack->push(newNode);
}
}
std::cout<< std::endl;
infile.close(); //close files that you read to avoid memory leaks
myStack->PrintStack(outFileName);
HashTable* hashBrown = new HashTable();
int currentDigit = 0;
int currentTable = 0;
int numOfDig =0; //stores number of digits of the largest number
string maxNum = itoa(largest,buffer,10);
numOfDig = maxNum.length();
std::cout<< "Num of digits " << numOfDig << std::endl;
Node* current;
while(!myStack->isEmpty())
{
current = myStack->pop();
std::cout<< "pop from stack element " << current->getData() << std::endl;
string str = current->getData();
int index = atoi(&str.back());
std::cout<< "insert at index " << index << std::endl;
std::cout<< "inserting data: "<< current->getData()<< " at index:" << index << std::endl;
hashBrown->myQueues[index].addTail(current);
}
hashBrown->printHashTable(outFileName);
delete myStack;
delete hashBrown;
outfile.close();
std::cout<< "finishing program " << std::endl;
return 0;
}
Linked List
#include "LinkedList.h"
#include "Node.h"
LinkedList::LinkedList()
{
//constructor
head = new Node("head"); //dummy variable
tail = new Node("tail"); //dummy variable
head->setNext(tail);
}
void LinkedList::insertNode(Node* newNode, Node *position)
{
newNode->setNext(position->getNext()); // set its pointer to position
position->setNext(newNode);
}
void LinkedList::insertFirst(Node* newNode)
{
std::cout<<"head here is "<< head->getData() <<std::endl; //
insertNode(newNode, head);
}
void LinkedList::insertLast(Node* newNode)
{
std::cout<<"inserting before tail (LinkedList)"<<std::endl; //
Node* cur = head;
std::cout<<"outside the loop "<< cur->getData() <<std::endl; //
std::cout<<"current node is "<< cur->getData() <<std::endl; //
while(cur->getNext() != tail) //iterate until you reach one before tail
{
std::cout<<"current node is "<< cur->getData() <<std::endl; //
cur = cur->getNext();
}
std::cout<<"inserting before tail"<<std::endl; //
insertNode(newNode, cur); //insert at the end before the dummy tail
}
Node* LinkedList::removeFirst()
{
if(isEmpty())
{
return head;
}
Node* result = head->getNext(); //store pointer to Node that you need to return
head->setNext(result->getNext());
return result;
}
Node* LinkedList::getTail()
{
return tail;
}
Node* LinkedList::getHead()
{
return head;
}
int LinkedList::isEmpty()
{
return head->getNext() == tail;
}
std::string LinkedList::printList(){
Node *current = head;
std::string str;
//append pieces of string to create new line
while(current != tail){
str.append (" --> (");
str.append ( current->getData());
str.append (",");
str.append (current->getNext()->getData());
str.append (")") ;
current = current->getNext();
}
std::cout<<str<<std::endl; //display new
return str; //return string containing next line that will be written to a file in main
}
LinkedList::~LinkedList()
{
//destructor
Node *current = head;
while( current->getNext() != tail ) { //go through whole linked list and delete each node to free memory
Node* next = current->getNext();
delete current;
current = next;
}
delete current;
delete tail;
}
So everything works fine until it tries to access the head or its data in the addTail() function of Queue.
You can use gdb to debug your program, find the bugs and fix them. If the program cored, you can use backtrace to see what caused the core.
Set breakpoint at the lines you think program behavior wired, you can also let the program run step by step.
Run the program and print variable value to see whether the variable value is expected. If the variable is a pointer, you can also print the content it referenced.
A brief gdb tutorial
I need to make it so the user can put in words until they hit enter 'xxx'. this part is already done, but then i need the list to always be in alphabetical order. I cant figure out how to do this part. I have to make it in alphabetical order in the function that adds a new node, not the function that prints the nodes to the screen. this is because it is for a class and is required.
Node header file:
struct Node
{
string word;
struct Node *next;
};
The function prototype header file:
Node *add_node(Node *list, const string &s);
Node *del_node(Node *list, const string &s);
void deallocate(Node *list);
void print(Node *list);
The code that gets compiled:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
#include "Node.h"
#include "funcs.h"
int main()
{
struct Node *list = 0; // list is a pointer to struct Node
cout << "please enter a few words (xxx to terminate list):\n";
string s; // s is a string object
while (cin >> s) // read a string into s
{
if (s == "xxx")
{
break; // terminate loop when string is equal to "xxx"
}
// add s to list in alphabetical order
list = add_node(list, s);
cout << "\nlist:\n";
print(list);
cout << '\n';
}
cout << "\nhere is the list:\n";
print(list);
cout << '\n';
cout << "please enter word words to delete from the list (xxx to terminate):\n";
while (cin >> s)
{
if (s == "xxx")
{
break; // terminate loop when string is equal to "xxx"
}
// delete first node containing string s
//list = del_node(list, s);
cout << "\nlist:\n";
print(list);
cout << '\n';
}
cout << "\nthe final list:\n";
print(list);
cout << '\n';
// deallocate the linked list
cout << "\ndeallocating the list:\n";
deallocate(list);
cout << "\nall done!\n";
return 0;
}
The code with the functions:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
#include "Node.h"
Node *add_node(Node *list, const string &s)
{
struct Node *n = new struct Node;
n->word = s; // copy string s to word
n->next = list;
// add node n to the list
// the list should always be in ascending alphabetical order
list = n;
return list; // returning pointer to beginning of the list
}
Node *del_node(Node *list, const string &s)
{
// delete node in the list that contains s
// the list should always be in ascending alphabetical order
// if s does not appear in the list, there is nothing to do
// if s appears multiple times in the list, delete the first occurrence
Node *lastp = 0;
Node *p = list;
for (; p; p = p->next)
{
if (p->word == s)
{
lastp->next = p->next;
delete p;
break;
}
lastp = p;
}
return list; // returning pointer to beginning of the list
}
void deallocate(Node *list)
{
for (struct Node *p = list; p;)
{
struct Node *tmp = p; // remember current pointer
p = p->next; // advance p to the next node
delete tmp; // deallocate tmp
// OK to print pointers tmp and p
cout << "deallocated\t" << tmp << "\tnext is\t" << p << '\n';
}
}
void print(Node *list)
{
for (struct Node *p = list; p; p = p->next)
{
cout << p << '\t' << setw(8) << p->word
<< '\t' << "next:" << '\t' << p->next << '\n';
}
}
All the code probably isnt required to answer the question but i figured i'd include it.
Try the following function add_node shown in the demonstrative program below. Take into account that you need to define one more function that will free all allocated memory in the list.
#include <iostream>
#include <string>
struct Node
{
std::string word;
struct Node *next;
};
Node *add_node( struct Node *list, const std::string &s )
{
struct Node *prev = nullptr;
struct Node *current = list;
while ( current && !( s < current->word ) )
{
prev = current;
current = current->next;
}
if ( prev == nullptr )
{
list = new Node { s, list };
}
else
{
prev->next = new Node { s, prev->next };
}
return list;
}
void print_list( const struct Node *list )
{
for ( ; list != nullptr; list = list->next ) std::cout << list->word << ' ';
}
int main()
{
struct Node *list = nullptr;
// for ( const std::string &s : { "B", "X", "A", "C", "F", "G" } )
for ( const char *s : { "B", "X", "A", "C", "F", "G" } )
{
list = add_node( list, s );
}
print_list( list );
std::cout << std::endl;
return 0;
}
The output is
A B C F G X
The problem lies in the insert method with two parameters.
The function, insert(char letter, string code), calls insert(TreeNode *node, char letter, char code). However it does not assign the left or right child as the node. The insert method with three parameters should create a new node. Then this node should be assigned as either a left or a right child.
#include "tree.h"
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
BinaryTree::BinaryTree() {
root = nullptr;
}
BinaryTree::~BinaryTree() {
empty_tree(root);
}
void BinaryTree::empty_tree(TreeNode *node) {
if (root) {
if (node->left) {
return empty_tree(node->left);
}
if (node->right) {
return empty_tree(node->right);
}
delete node;
}
}
void BinaryTree::insert(char letter, string code) {
TreeNode *node = root;
TreeNode *temp = nullptr;
if (node) {
for (string::size_type i = 0; i < code.length(); i++) {
//temp = node;
if (code[i] == '.') {
if (node->left) {
node = node->left;
}
else {
insert(temp, letter, code[i]);
node->left = temp;
}
}
else {
if (node->right) {
node = node->right;
}
else {
return insert(temp, letter, code[i]);
node->right = temp;
}
}
}
}
/*else {
return insert();
}*/
}
void BinaryTree::insert() {
if (!root) {
root= new TreeNode();
root->letter = '*';
root->left = nullptr;
root->right = nullptr;
root->code = "*";
}
}
void BinaryTree::insert(TreeNode *node, char letter, char code) {
if (!node) {
node = new TreeNode();
node->letter = letter;
node->left = nullptr;
node->right = nullptr;
node->code += code;
}
}
void BinaryTree::print_tree() {
return print_tree(root);
}
void BinaryTree::print_tree(TreeNode *tree) {
if (tree) {
if (tree->left) {
print_tree(tree->left);
}
if (tree->right) {
print_tree(tree->right);
}
cout << "Node is " << tree->letter << " and in Morse Code is " << tree->code << endl << endl;
}
}
Below is the file containing main. The morse-code.txt file just has the alphabet letters in order from a to z. Each line has one letter, followed by a space, followed by the morse code.
#include "tree.h"
#include <iostream>
#include <fstream>
#include <string>
using std::cout;
using std::endl;
int main() {
std::string code;
std::ifstream infile;
char letter;
BinaryTree tree;;
infile.open("morse-code.txt");
if (!infile) {
std::cout << "File unable to open" << std::endl;
}
else {
cout << "morse-code.txt\n\n";
tree.insert();
while (std::getline(infile, code)) {
tree.insert(code[0], code.substr(2, code.length()-2));
cout << code << endl;
}
cout << "\n******Tree Representation******\n\n";
tree.print_tree();
}
system("pause");
}
text file
a .-
b -...
c -.-.
d -..
e .
f ..-.
g --.
h ....
i ..
j .---
k -.-
l -.--
m --
n -.
o ---
p .--.
q --.-
r .-.
s ...
t -
u ..-
v ...-
w .--
x -..-
y -.--
z --..
tree.h
#ifndef _TREE_H
#define _TREE_H
//#include <iostream>
//#include <fstream>
#include <string>
using std::string;
class BinaryTree {
private:
struct TreeNode {
char letter;
string code;
TreeNode *left;
TreeNode *right;
}; TreeNode *root;
public:
BinaryTree();
~BinaryTree();
void insert();
void insert(TreeNode *new_node, char letter, char code);
void insert(char letter, string code);
void empty_tree(TreeNode *node);
void print_tree(TreeNode *node);
void print_tree();
};
#endif
I think that insert isn't the only problems you have with your code. Your empty_tree is incorrect (will not free all of the memory, since you return prematurely. The specific part of the code you have wrong is the following line of your code: "return insert(temp, letter, code[i]);"
The rest of your code looks fine.
It should look something like this instead:
void BinaryTree::empty_tree(TreeNode *node) {
if (!node) return;
delete node;
empty_tree(node->left );
empty_tree(node->right);
/* See Jerry's solution below. */
}
void BinaryTree::insert(char letter, string code) {
TreeNode *node = root;
if (!root) /* do something*/;
for (string::size_type i = 0; i < code.length(); i++) {
if (code[i] == '.') {
if (node->left)
insert(&node->left, letter, code[i]);
node = node->left;
}
else {
if (!node->right)
insert(&node->right, letter, code[i]);
node = node->right
}
}
}
void BinaryTree::insert(TreeNode **node, char letter, string code) {
*node = new TreeNode();
(*node)->letter = letter;
(*node)->left = nullptr;
(*node)->right = nullptr;
(*node)->code = code;
}
In tree.h:
typedef struct _TreeNode {
char letter;
string code;
struct _TreeNode *left;
struct _TreeNode *right;
} TreeNode; TreeNode *root;
I *compiled the following code:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
typedef struct _TreeNode {
char letter;
string code;
struct _TreeNode *left;
struct _TreeNode *right;
} TreeNode;
class BinaryTree {
private:
TreeNode *root;
public:
BinaryTree();
~BinaryTree();
void insert();
void insert(TreeNode **new_node, char letter, string code);
void insert(char letter, string code);
void empty_tree(TreeNode *node);
void print_tree(TreeNode *node);
void print_tree();
};
BinaryTree::BinaryTree() {
root = nullptr;
}
BinaryTree::~BinaryTree() {
empty_tree(root);
}
void BinaryTree::empty_tree(TreeNode *node) {
if (!node) return;
delete node;
empty_tree(node->left );
empty_tree(node->right);
}
void BinaryTree::insert(char letter, string code) {
TreeNode *node = root;
if (!root) insert();
for (string::size_type i = 0; i < code.length(); i++) {
if (code[i] == '.') {
if (!node->left)
insert(&node->left, letter, code.substr(0,i));
node = node->left;
} else {
if (!node->right)
insert(&node->right, letter, code.substr(0,i));
node = node->right;
}
}
}
void BinaryTree::insert() {
root = new TreeNode();
root->letter = '*';
root->left = nullptr;
root->right = nullptr;
root->code = "*";
}
void BinaryTree::insert(TreeNode **node, char letter, string code) {
*node = new TreeNode();
(*node)->letter = letter;
(*node)->left = nullptr;
(*node)->right = nullptr;
(*node)->code = code;
}
void BinaryTree::print_tree() {
return print_tree(root);
}
void BinaryTree::print_tree(TreeNode *tree) {
if (tree) {
if (tree->left ) print_tree(tree->left );
cout << "Node is " << tree->letter << " and in Morse Code is "
<< tree->code << endl << endl;
if (tree->right) print_tree(tree->right);
}
}
int main() {
string code;
ifstream infile;
char letter;
BinaryTree tree;
infile.open("morse-code.txt");
if (!infile) {
cout << "File unable to open" << endl;
}
else {
cout << "morse-code.txt\n\n";
tree.insert();
while (std::getline(infile, code)) {
tree.insert(code[0], code.substr(2, code.length()-2));
cout << code << endl;
}
cout << "\n******Tree Representation******\n\n";
tree.print_tree();
}
system("pause");
}
So the problem was in my tree_driver.cpp file. Most of the problems contained in that file were in the insert function with two parameters. Below is the working code.
tree_driver.cpp
#include "tree.h"
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
BinaryTree::BinaryTree() {
root = nullptr;
}
BinaryTree::~BinaryTree() {
empty_tree(root);
}
void BinaryTree::empty_tree(TreeNode *node) {
if (!node) {
if (node->left) {
empty_tree(node->left);
}
if (node->right) {
empty_tree(node->right);
}
delete node;
}
}
//The following member function contains the most alterations
void BinaryTree::insert(char letter, string code) {
if (!root) {
insert(root, letter, code, true);
}
else {
TreeNode *node = root;
for (string::size_type i = 0; i < code.length(); i++) {
if (code[i] == '.') {
if (!node->left) {
if (i == code.length() - 1) {
insert(node->left, letter, code.substr(0, i + 1), true);
}
else {
insert(node->left, letter, code.substr(0, i + 1), false);
}
}
node = node->left;
if (node->left) {
if (i == code.length() - 1) {
node->letter = letter;
}
}
if (!node->left) {
if (i == code.length() - 1) {
node->letter = letter;
}
}
}
else if (code[i] == '-') {
if (!node->right) {
if (i == code.length() - 1) {
insert(node->right, letter, code.substr(0, i + 1), true);
}
else {
insert(node->right, letter, code.substr(0, i + 1), false);
}
}
node = node->right;
if (node->right) {
if (i == code.length() - 1) {
node->letter = letter;
}
}
if (!node->right) {
if (i == code.length() - 1) {
node->letter = letter;
}
}
}
}
}
}
void BinaryTree::insert(TreeNode *&node, char letter, string code, bool last) {
if (last) {
node = new TreeNode();
node->letter = letter;
node->right = nullptr;
node->left = nullptr;
node->code = code;
}
if (!last) {
node = new TreeNode();
node->letter = '\0';
node->right = nullptr;
node->left = nullptr;
node->code = code;
}
}
void BinaryTree::print_tree() {
print_tree(root);
}
void BinaryTree::print_tree(TreeNode *tree) {
if (tree) {
if (tree->left) {
print_tree(tree->left);
}
cout << "Node is " << tree->letter << " and in Morse Code is " << tree->code << endl << endl;
if (tree->right) {
print_tree(tree->right);
}
}
}
tree_tester.
#include "tree.h"
#include <iostream>
#include <fstream>
#include <string>
using std::cout;
using std::endl;
int main() {
std::string code_main;
std::ifstream infile;
BinaryTree tree;;
infile.open("morse-code.txt");
if (!infile) {
std::cout << "File unable to open" << std::endl;
}
else {
cout << "morse-code.txt\n\n";
tree.insert('0', "*");
while (std::getline(infile, code_main)) {
tree.insert(code_main[0], code_main.substr(2, code_main.length()-2));
cout << code_main << endl;
}
infile.close();
cout << "\n******Tree Representation******\n\n";
tree.print_tree();
}
system("pause");
return 0;
}
tree.h
#ifndef _TREE_H
#define _TREE_H
#include <string>
using std::string;
class BinaryTree {
private:
struct TreeNode {
string letter;
string code;
TreeNode *left;
TreeNode *right;
}; TreeNode *root;
public:
BinaryTree();
~BinaryTree();
/*void insert();*/
void insert(TreeNode *&new_node, char letter, string code, bool last);
void insert(char letter, string code);
void empty_tree(TreeNode *node);
void print_tree();
void print_tree(TreeNode *node);
};
#endif
I'm using a linked list to implement a concordance program. I am getting the following compiler error when trying to compile the program with g++:
concordancetest.cpp: In function 'void build_list(std::ifstream&, char*)':
concordancetest.cpp:65: error: no matching function for call to ‘Concordance::insert(char*&, int&)'
concordance.h:22: note: candidates are: void Concordance::insert(char (&)[9], int&)
Below is the code I have written:
Header File:
#ifndef CONCORDANCE_H
#define CONCORDANCE_H
#include <iostream>
#include <cstdlib>
const int MAX = 8;
class Concordance
{
public:
//typedef
typedef char Word[MAX+1];
//constructor
Concordance();
//destructor
~Concordance();
//modification member functions
void insert(Word& word, int& n);
void remove(Word& word);
int get_count(Word& word);
//constant member functions
int length() const;
//friend member functions
friend std::ostream& operator << (std::ostream& out_s, Concordance& c);
private:
struct Node
{
Word wd;
int count;
Node *next;
};
Node *first;
Node* get_node(Word& word, int& count, Node* link);
};
#endif
Implementation Code:
//class definition
#include "concordance.h"
#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
Concordance::Concordance()
{
first = NULL;
}
Concordance::~Concordance()
{
Node *temp;
while(first != NULL)
{
temp = first;
first = first -> next;
delete temp;
}
}
void Concordance::insert(Word& word, int& n)
{
Node *prev;
if(first == NULL || strcmp(first -> wd, word) > 0)
first = get_node(word, n, first);
else
{
prev = first;
while(prev -> next != NULL && strcmp(prev -> next -> wd, word) > 0)
prev = prev -> next;
prev -> next = get_node(word, n, prev -> next);
}
}
void Concordance::remove(Word& word)
{
Node *prev, *temp;
prev = temp;
if(prev -> wd == word)
{
first = first -> next;
delete prev;
}
else
{
while(strcmp(prev -> next -> wd, word) > 0)
prev = prev -> next;
temp = prev -> next;
prev -> next = temp -> next;
delete temp;
}
}
int Concordance::get_count(Word& word)
{
while(strcmp(first -> wd, word) != 0)
first = first -> next;
return first -> count;
}
int Concordance::length() const
{
Node *cursor;
int len;
len = 0;
for(cursor = first; cursor != NULL; cursor = cursor -> next )
len++;
return len;
}
Concordance::Node* Concordance::get_node (Word& word, int& count, Node* link)
{
Node *temp;
temp = new Node;
strcpy(temp-> wd, word);
temp-> next = link;
temp -> count = count+1;
return temp;
}
ostream& operator << (ostream& out_s, Concordance& c)
{
Concordance::Node *cursor;
out_s << "Word" << setw(10) << " " << "Count" << endl;
out_s << "--------------------" << endl;
for(cursor = c.first; cursor != NULL && cursor->next != NULL; cursor = cursor-> next )
out_s << cursor-> wd << setw(10) << " " << cursor -> count << endl;
if(cursor != NULL)
out_s << cursor-> wd << setw(10) << " " << cursor -> count << endl;
out_s << "--------------------" << endl;
return out_s;
}
Test Program:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include "concordance.h"
using namespace std;
void read_word(ifstream& in_file, char array[]);
void build_list(ifstream& in_file, char array[]);
int main()
{
char file_name[100];
ifstream in_file;
char array[MAX+1];
cout << "Enter a file name: ";
cin >> file_name;
in_file.open(file_name);
build_list(in_file, array);
in_file.close();
return EXIT_SUCCESS;
}
void read_word(ifstream& in_file, char array[])
{
char ch;
int i = 0;
in_file.get(ch);
while(isalpha(ch) && !isspace(ch))
{
if(i > MAX-1)
{
while(!isspace(ch))
in_file.get(ch);
break;
}
ch = tolower(ch);
array[i] = ch;
i++;
in_file.get(ch);
}
for(int j = 0; j < i; j++)
cout << array[j];
cout << endl;
}
void build_list(ifstream& in_file, char array[])
{
Concordance c;
int count = 0;
while(!in_file.eof())
{
read_word(in_file, array);
c.insert(array, count);
}
cout << c;
}
The type of char array[] is char *, so when it looks for a matching function, none is found. You can fix this by using typedef char* Word; and enforcing your max length inside the functions that require it.