How can I break reading this text file (using ifstream)? C ++
I want to stop reading my text input file when the word "synonyms" appears. I am using ifstream and I have no idea how to break the loop. I tried using "synonyms" in the string stream, but it ended up with me deleting my bst. I've included all the project files below if you want to avoid typing.
An important part:
for(;;) /*here, I wanna break the cycle when it reads "synonyms"*/
{
inStream >> word;
if (inStream.eof()) break;
wordTree.insert(word);
}
wordTree.graph(cout);
dictionary.txt
1 cute
2 hello
3 ugly
4 easy
5 difficult
6 tired
7 beautiful
synonyms
1 7
7 1
antonyms
1 3
3 1 7
4 5
5 4
7 3
Project.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "MiBST.h"
using namespace std;
class WordInfo{
public:
//--id accesor
int id ()const {return myId; }
/* myId is the number that identifies each word*/
//--input function
void read (istream &in)
{
in>>myId>>word;
}
//--output function
void print(ostream &out)
{
out<<myId<<" "<<word;
}
//--- equals operator
bool operator==(const WordInfo & otherword) const
{ return myId == otherword.myId; }
//--- less-than operator
bool operator<(const WordInfo & otherword) const
{ return myId < otherword.myId; }
private:
int myId;
string word;
};
//--- Definition of input operator
istream & operator>>(istream & in, WordInfo & word)
{
word.read(in);
}
//---Definition of output operator
ostream & operator <<(ostream &out, WordInfo &word)
{
word.print(out);
}
int main(){
// Open stream to file of ids and words
string wordFile;
cout << "Enter name of dictionary file: ";
getline(cin, wordFile);
ifstream inStream(wordFile.data());
if (!inStream.is_open())
{
cerr << "Cannot open " << wordFile << "\n";
exit(1);
}
// Build the BST of word records
BST<WordInfo> wordTree; // BST of word records
WordInfo word; // a word record
for(;;) /*here, I wanna break the cycle when it reads "synonyms"*/
{
inStream >> word;
if (inStream.eof()) break;
wordTree.insert(word);
}
wordTree.graph(cout);
//wordTree.inorder(cout);
system ("PAUSE");
return 0;
}
MiBST.h (in case you want to run it)
#include <iostream>
#include <iomanip>
#ifndef BINARY_SEARCH_TREE
#define BINARY_SEARCH_TREE
template <typename DataType>
class BST
{
public:
/***** Function Members *****/
BST();
bool empty() const;
bool search(const DataType & item) const;
void insert(const DataType & item);
void remove(const DataType & item);
void inorder(std::ostream & out) const;
void graph(std::ostream & out) const;
private:
/***** Node class *****/
class BinNode
{
public:
DataType data;
BinNode * left;
BinNode * right;
// BinNode constructors
// Default -- data part is default DataType value; both links are null.
BinNode()
: left(0), right(0)
{}
// Explicit Value -- data part contains item; both links are null.
BinNode(DataType item)
: data(item), left(0), right(0)
{}
}; //end inner class
typedef BinNode * BinNodePointer;
/***** Private Function Members *****/
void search2(const DataType & item, bool & found,
BinNodePointer & locptr, BinNodePointer & parent) const;
/*------------------------------------------------------------------------
Locate a node containing item and its parent.
Precondition: None.
Postcondition: locptr points to node containing item or is null if
not found, and parent points to its parent.#include <iostream>
------------------------------------------------------------------------*/
void inorderAux(std::ostream & out,
BST<DataType>::BinNodePointer subtreePtr) const;
/*------------------------------------------------------------------------
Inorder traversal auxiliary function.
Precondition: ostream out is open; subtreePtr points to a subtree
of this BST.
Postcondition: Subtree with root pointed to by subtreePtr has been
output to out.
------------------------------------------------------------------------*/
void graphAux(std::ostream & out, int indent,
BST<DataType>::BinNodePointer subtreeRoot) const;
/*------------------------------------------------------------------------
Graph auxiliary function.
Precondition: ostream out is open; subtreePtr points to a subtree
of this BST.
Postcondition: Graphical representation of subtree with root pointed
to by subtreePtr has been output to out, indented indent spaces.
------------------------------------------------------------------------*/
/***** Data Members *****/
BinNodePointer myRoot;
}; // end of class template declaration
//--- Definition of constructor
template <typename DataType>
inline BST<DataType>::BST()
: myRoot(0)
{}
//--- Definition of empty()
template <typename DataType>
inline bool BST<DataType>::empty() const
{ return myRoot == 0; }
//--- Definition of search()
template <typename DataType>
bool BST<DataType>::search(const DataType & item) const
{
typename BST<DataType>::BinNodePointer locptr = myRoot;
typename BST<DataType>::BinNodePointer parent =0;
/* BST<DataType>::BinNodePointer locptr = myRoot;
parent = 0; */ //falta el typename en la declaracion original
bool found = false;
while (!found && locptr != 0)
{
if (item < locptr->data) // descend left
locptr = locptr->left;
else if (locptr->data < item) // descend right
locptr = locptr->right;
else // item found
found = true;
}
return found;
}
//--- Definition of insert()
template <typename DataType>
inline void BST<DataType>::insert(const DataType & item)
{
typename BST<DataType>::BinNodePointer
locptr = myRoot, // search pointer
parent = 0; // pointer to parent of current node
bool found = false; // indicates if item already in BST
while (!found && locptr != 0)
{
parent = locptr;
if (item < locptr->data) // descend left
locptr = locptr->left;
else if (locptr->data < item) // descend right
locptr = locptr->right;
else // item found
found = true;
}
if (!found)
{ // construct node containing item
locptr = new typename BST<DataType>::BinNode(item);
if (parent == 0) // empty tree
myRoot = locptr;
else if (item < parent->data ) // insert to left of parent
parent->left = locptr;
else // insert to right of parent
parent->right = locptr;
}
else
std::cout << "Item already in the tree\n";
}
//--- Definition of remove()
template <typename DataType>
void BST<DataType>::remove(const DataType & item)
{
bool found; // signals if item is found
typename BST<DataType>::BinNodePointer
x, // points to node to be deleted
parent; // " " parent of x and xSucc
search2(item, found, x, parent);
if (!found)
{
std::cout << "Item not in the BST\n";
return;
}
//else
if (x->left != 0 && x->right != 0)
{ // node has 2 children
// Find x inorder successor and its parent
typename BST<DataType>::BinNodePointer xSucc = x->right;
parent = x;
while (xSucc->left != 0) // descend left
{
parent = xSucc;
xSucc = xSucc->left;
}
// Move contents of xSucc to x and change x
// to point to successor, which will be removed.
x->data = xSucc->data;
x = xSucc;
} // end if node has 2 children
// Now proceed with case where node has 0 or 2 child
typename BST<DataType>::BinNodePointer
subtree = x->left; // pointer to a subtree of x
if (subtree == 0)
subtree = x->right;
if (parent == 0) // root being removed
myRoot = subtree;
else if (parent->left == x) // left child of parent
parent->left = subtree;
else // right child of parent
parent->right = subtree;
delete x;
}
//--- Definition of inorder()
template <typename DataType>
inline void BST<DataType>::inorder(std::ostream & out) const
{
inorderAux(out, myRoot);
}
//--- Definition of graph()
template <typename DataType>
inline void BST<DataType>::graph(std::ostream & out) const
{ graphAux(out, 0, myRoot); }
//--- Definition of search2()
template <typename DataType>
void BST<DataType>::search2(const DataType & item, bool & found,
BST<DataType>::BinNodePointer & locptr,
BST<DataType>::BinNodePointer & parent) const
{
locptr = myRoot;
parent = 0;
found = false;
while (!found && locptr != 0)
{
if (item < locptr->data) // descend left
{
parent = locptr;
locptr = locptr->left;
}
else if (locptr->data < item) // descend right
{
parent = locptr;
locptr = locptr->right;
}
else // item found
found = true;
}
}
//--- Definition of inorderAux()
template <typename DataType>
void BST<DataType>::inorderAux(std::ostream & out,
BST<DataType>::BinNodePointer subtreeRoot) const
{
if (subtreeRoot != 0)
{
inorderAux(out, subtreeRoot->left); // L operation
out << subtreeRoot->data << " "; // V operation
inorderAux(out, subtreeRoot->right); // R operation
}
}
//--- Definition of graphAux()
template <typename DataType>
void BST<DataType>::graphAux(std::ostream & out, int indent,
BST<DataType>::BinNodePointer subtreeRoot) const
{
if (subtreeRoot != 0)
{
graphAux(out, indent + 8, subtreeRoot->right);
out << std::setw(indent) << " " << subtreeRoot->data << std::endl;
graphAux(out, indent + 8, subtreeRoot->left);
}
}
#endif
source to share
You can do it like
/* here, it stops when reading "synonyms" or when failing to extract a word. */
while(inStream >> word && word != "synonym") {
wordTree.insert(word);
}
wordTree.graph(cout);
Note that when it cannot read a sequence of non-whitespace characters, it sets the stream fault bit. Then inStream evaluates to false. This is what the work cycle does. Be careful when using .eof();
It only returns true after you've tried to read outside of the file. So, for example, you will exit the loop and loop through the word tree 3:
1 house 2 garden 3 tree
Assuming there is no space after the tree. The same will happen, of course, if you have newlines between the word information and don't have a trailing newline after the last word. Usage if(inStream)
(which the while loop is implicit) is safe. In this case, it will still evaluate to true and only false if it reads nothing but white space.
source to share
@SoapBox:
I created this statement:
//--- equals operator for String
bool operator==(const string & aString) const
{ return word == aString; } // word is the WordInfo string field for 'real' word
And changed for (;;) to:
for(;;)
{
inStream >> word;
if (word=="synonyms") break;
wordTree.insert(word);
}
And the endless printing of the cycle ended:
"Item already in the tree"
Btw, I previoulsy checked the tree with an example dictionary like this and it worked.
dict2.txt
1 cute 2 hello 3 ugly 4 simple 5 difficult 6 tired 7 beautiful
source to share