#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
usingnamespace std;
// File descriptors
ifstream infile;
ofstream outfile;
typedef string tType; // Variable to hold each word
class tNode // Node class within the tree class
{
public:
// Member Variables
tType value; // Holds each word
tNode* left; // Points to left tree node
tNode* right; // Points to right tree node
int counter; // Counts instance of each word
// Construct / Destruct
tNode(tType v);
~tNode(void);
};
class tTree // Actual tree class
{
private:
// Member Variables
tNode* root; // Tree root pointer
// Private Member Functions
void destroy(tNode* current); // Apparently, this prevents memory leaks
void rInsert(tNode** current, tNode* newNode); // Inserts words into the tree
void rPrint(tNode* current); // Prints out the tree
public:
// Construct / Destruct
tTree(void);
~tTree(void);
// Public Member Functions
// Modifiers
void clear(void); // Clears the tree
void insert(tType newValue);// Inserts into the tree
// Accessors
void print(void); // Prints the tree
};
// Function prototypes
int open_output();
int open_input();
void print_header();
tType clean_up(tType x);
float totalCounter = 0; // Counts total number of words in input file
string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
//Main program
int main(void)
{
open_output();
open_input();
print_header();
tTree myTree; // Create a tree
string con_word; // Create a variable to hold each word
// Print out header
cout << setw(30) << "WORD" << setw(10) << "ABSOLUTE" << setw(10) << "RELATIVE" << endl << endl;
infile >> con_word; // Get first word of input file
while (infile) // While still in input file
{
myTree.insert(clean_up(con_word));// Add word to the list
totalCounter++; // Add to total counter
infile >> con_word; // Get next word
}
myTree.print(); // Print out the tree
cout << fixed;
cout << endl << "Total number of words: " << setprecision(0) << totalCounter << endl;
return 0;
}
//***************************************************************
// tNode Functions
// Construct / Destruct
tNode::tNode(tType v)
{
value = v;
left = NULL;
right = NULL;
counter = 0;
}
//***************************************************************
tNode::~tNode(void)
{
// We don't have to do anything
// But it has come to my attention that these are important.
}
//***************************************************************
//tTree Functions
// Construct / Destruct
tTree::tTree(void)
{
root = NULL; // Very important
}
//***************************************************************
tTree::~tTree(void)
{
destroy(root);
}
//***************************************************************
// Private member functions
void tTree::destroy(tNode* current)
{
if (current->left) destroy(current->left);
if (current->right) destroy(current->right);
delete current;
}
//***************************************************************
void tTree::rInsert(tNode** current, tNode* newNode)
{
if (!*current) // If there is no tree yet
{
*current = newNode; // Create first node
(*current)->counter++; // Increment counter for that word
}
elseif (newNode->value < (*current)->value) // If there is a tree
{
rInsert(&(*current)->left, newNode); // If smaller value, place in left tree node
}
elseif (newNode->value > (*current)->value)
{
rInsert(&(*current)->right, newNode); // If larger value, place in right tree node
}
elseif(newNode->value == (*current)->value) // If words are the same
{
(*current)->counter++; // Increment counter for that word
}
}
//***************************************************************
void tTree::rPrint(tNode* current)
{
// The location of the cout will change the order
// that the words are printed. This is alphebetically.
if (current->left) // Prints the left side of the tree
{
rPrint(current->left);
}
// Prints out formatted output
cout << fixed;
cout << setw(30) << current->value << setw(8) << current->counter
<< setw(10) << setprecision(3) << (current->counter/totalCounter)*100 << "%" << endl;
// Now print the right half of the tree
if (current->right)
rPrint(current->right);
}
//***************************************************************
// Public member function definitions
void tTree::clear(void)
{
destroy(root); // Destroy the tree
root = NULL; // Set the root back to NULL
}
//***************************************************************
void tTree::print(void)
{
if (root) rPrint(root); // Print out the tree
}
//***************************************************************
void tTree::insert(tType newValue)
{
tNode* newNode = new tNode(newValue);
if (!root) // If tree does not exist yet
{
root = newNode; // Create first node in tree
}
else rInsert(&root, newNode); // If tree exists, insert new word
}
//***************************************************************
tType clean_up(tType x)
{
// Convert word to lowercase
int i = 0; // Used to step through each word
int temp = x.length(); // Holds value of each word's length
while (i < temp) // As long as we are in each word
{
if (alphabet.find(x[i] )!= string::npos) // If char found is within string 'alphabet'
/* ((x[i] >= 'A' && x[i] <= 'Z' )||(x[i] >= 'a' && x[i] <= 'z' ))*/
{
if(isupper(x[i])) // If it is a capital letter
{
x[i] = tolower(x[i]); // Convert letter to lowercase
}
i++; // Move to next letter in word
}
else // If char found is not found within string 'alphabet'
{
x.erase(i, 1); // Erase that char from the string
temp--; // Decrement the length of the word
}
}
return x; // Return stripped word to insert
}
infile >> con_word; // Get first word of input file
while (infile) // While still in input file
{
myTree.insert(clean_up(con_word));// Add word to the list
totalCounter++; // Add to total counter
infile >> con_word; // Get next word
}
Why do you get the first word without also counting it with totalCounter? Why are you using while (infile) instead of while (!infile.eof())? As for the spaces, I don't just happen to have a constitution laying around, but the spaces in the file should be ignored. I didn't see anything in your tree that popped out at me, so I don't believe there is anything there. How do you know there is spaces? Are they counted? Are they added to your total words counter?
Do you have what the correct output is supposed to be? But I'm glad that you're almost done. Must feel good, and it'll only feel better once you get this done.
Edit: One thing I just thought about, and I'm still learning trees/nodes, but the tree should look something like a tree, right? So at the nodes at the very end of the tree, would they possibly be holding spaces in them? Could they be messing up your answer?
To clarify, the little twigs on your trees have no more nodes coming off of them, so what's at the tip of them if it's not supposed to be a node? A NULL node?
Why do you get the first word without also counting it with totalCounter?
Because I thought before you can ask to be sure you are IN the input file, you have to be in it. And then I pass that word to the insert function, so it does get counted.
Why are you using while (infile) instead of while (!infile.eof())?
What's the difference? I thought it was the same thing, and this is easier, so that's how I always do it.
How do you know there is spaces? Are they counted? Are they added to your total words counter?
I know because, yes, they are counted. Hmmm, but I don't think they are added to my total words counter, actually. Since I don't have the correct output, I popped the Constitution file into Word and did a word count. The count DOES match my count here in the program. But that first line in the output file shows 105 blanks. At least I think they are blanks, but maybe you're right and they are NULLs from the leaves in the tree?
Ugh, I just typed this long thing up for you, and my browser crashed -.-
Anyways, maybe the 105 is periods or returns or the "NULL" leaves. I also don't believe there is the word "d" or "httpwww..." in the Constitution.
I suggest that if you don't want to use .eof(), use .good(). When I look over old code and see .eof() in a while loop I automatically know I'm reading til the end of a file. but if I just see a variable, my first assumption is to think it's a bool.
As for when I asked you about reading in your first word, I was trying to suggest putting it in the while loop. Right now, I don't believe that you're actually counting your last word.
The last suggestion I have is to try typing up a short .txt file and see if your tree reads it correctly. If not, then you know to look at your tree. If it does, then you know there is an issue in the .txt file.
To clarify, the little twigs on your trees have no more nodes coming off of them, so what's at the tip of them if it's not supposed to be a node? A NULL node?
Exactly. The tNode constructor makes the left and right nodes NULL (which is defined as 0). So when functions use if (current->left) this only is true if a node has been inserted there.
rPrint() is only called with valid nodes. Note that print() ensures that root exists.