I have used a binary search tree to read in a text file, storing each word as a node, and counting how many times that word is repeated in the text file. I have been able to successfully [I]cout[/I] that information, but for some reason have been unable to read out the information to an output file.

Reading similar threads, I thought I could just put the output information into my display function, but that has not been successful. I think the problem is that my file is being opened and closed in a way that is not permitting all the information to be written to file!

Any help would be greatly appreciated!

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

class node
{
public:
    node(string newitem)
    {
        data = newitem;
        counter = 1;
        right = NULL;
        left = NULL;
    };

    string data;
    int counter;
    node * left;
    node * right;
};

class binarySearchTree
{
private:
    node * root;

    void insert(string x, node * & r);
    void display(node * r);

public:

    binarySearchTree();

    //insert item into tree
    void addItem(string item);

    //remove given item from tree
    void deleteItem(string item);

    //show contents of tree
    void displayItems();

};

binarySearchTree::binarySearchTree()
{
    root = NULL;
}

void binarySearchTree::insert(string x, node * & r)
{
    if( r == NULL )
        r = new node(x);
    else if(r->data == x)
    {
      r->counter++;
    }
    else
    {
        if( x >= r->data )
            insert(x, r->right);
        if( x < r->data )
            insert(x, r->left);
    }
}

//insert item into tree
void binarySearchTree::addItem(string item)
{
    insert( item, root );
}

//remove given item from tree
void binarySearchTree::deleteItem(string item)
{

}

void binarySearchTree::display( node * r )
{
    ofstream sorted;
        sorted.open("storysort.txt");

    if( r != NULL )
    {

        display(r->left);

        cout << r->data << " ";
        cout << r->counter << endl;

                sorted << r->data << " ";
                sorted << r->counter << endl;

        display(r->right);

    }
        sorted.close();

}

//show contents of tree
void binarySearchTree::displayItems()
{
    display( root );
}

int main()
{
    // Open input and output files

    ifstream rawdata;
    rawdata.open("story.txt");

    binarySearchTree ourTree;

    while( ! rawdata.eof() )
    {
      string temp;
      rawdata >> temp;
      ourTree.addItem(temp);
    }

    ourTree.displayItems();

    return 0;
}

The ofstream sorted is local in the recursive member function display so you are trying to open file stream on every function call and close it by the sorted variable destructor on every return from display. Obviously, it's absolutely wrong and senseless effect.

There are two possible solutions. You may declare stream sorted as a member of the class binarySearchTree then open and close it before and after tree traversal. It's not a good design solution because ofstreams per se do not bear a relation to binary search trees.

The second solution looks better: add ofstream& parameter to display function and pass it throw all recursive calls chains.

void BlaBlaBla::displayItems(std::ostream os = std::cout)
{ display(root,os); }
void BlaBlaBla::display(const node* p, std::ostream& os = std::cout)
{
    // all the same except file open/close and os << ...
}
... // Using::
ofstream f("blablabla.txt");
yourTree.displayItems(f);
f.close();

cout is a global object. It isn't passed to the display function. It isn't declared within the display function. Therefore there is only one copy of it. On the other hand, your display() function does declare the ofstream object locally. Since display() is recursive, that means you are trying to delcare, open and associate multiple copies of the same ofstream object. The solution? Try openining the ofstream object in displayItems() before the call to display(), pass the ofstream to display() by reference and then closing the ofstream in displayItems() after return from display().

As an aside, don't use the return result of eof() to control a loop. Sooner or later it will end up causing an error by processing the body of the loop one too many times which often leads to duplicating the final item in the tree/array/list/etc. Instead, do something like this:

string temp; 
while(rawdata >> temp)
    ourTree.addItem(temp);

It's a good habit to close your streams (other than cin/cout) when you are done using them. In straightforward programs it's not such a big deal. But in more involved programs it can be the source of headaches if you try to open the same stream in code many lines away or in different modules, etc.

You opened file that already open

int main(){
//...
rawdata.open("story.txt");
//...
}
binarySearchTree(node *r){
//...
sorted.open("story.txt");
//...

My bad..Sorry..

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.