Member Avatar for sakura_fujin

need help! what's wrong with my code? it compiles but outputs nothing. it requires the user to create a "word.txt" text file for it to start counting the frequency of occurrence of words. i'm a newbie here in daniweb and a novice in C++ programming. i really appreciate any help. thanks!:)


using namespace std;

#define MAX_SIZE 1000//maximum length of inputted line

struct BSTNode{
       char *word;//pointer to the word that is being stored
       int count;//variable used to count the number of times the word encounter
       struct BSTNode *left;//points to the left subtree
       struct BSTNode *right;//points to the right subtree
void print(struct BSTNode *);//function to print the tree
int isNonword(char *p);//function to determine if it is a word or not
struct BSTNode *allocate(char *word){//create a node
       struct BSTNode *newNode= new BSTNode;//pointer to new node
       newNode->word= word;
struct BSTNode *insert(struct BSTNode *root1, char *word){//insert a word into
     int compare;//binary tree, variable used to get the result from strcmp
     if((compare= strcmp(word,root1->word))==0){//if it is equal to zero it means
                  root1->count++;//the two words are equal
     else if(compare>0){//if it is less than zero then the word pointed to by
          root1->right=insert(root1->right,word);//word is greater than to the word
          }//pointed to by root1
     else{//if it is less than zero then 
          root1->left=insert(root1->left,word);//then the word pointed to by 
          }//word is less than to the word pointedto by root1
     return (root1);//return the pointer to the root of the tree
}//end of the function

int main(){//main program
    char line[MAX_SIZE];//variable for inputted line
    char word[MAX_SIZE];//variable for word
    int lines=0;//variable for current line number
    char *p;//variable for current line position
    char *w;//variable that is used for loading a line
    struct BSTNode *root;//the root of the tree
    ifstream inWordFile("words.txt",ios::in);//opens a file to read
                    cerr<<"File could not be opened,"<<endl;
    while(inWordFile>>(fgets(line, 100, stdin))){//read the file a line
                       lines++;//at a time
                       while(*p){//loops until the end of the line
                                 while(*p && (isNonword(p)!=1))//omit leading 
                                      p++;                     //non-word
                                 w= word;//stop at word, then put it into word[]
                                      *w++= *p++;
                                 *w= '\0';
                                 if(word[0])//inserting it into the tree
                                    root= insert(root, word);
     print(root);//print the word
     return 0;//indicate that program exited cleanly
}//end of main program

void print(struct BSTNode *root1){//struct BSTNode *root1 is the root of the tree
     if(root1==NULL)//if there is no treee it means nothing to print
     print(root1->left);//prints the left subtree
     cout<<"\n"<<root1->count<<" "<<root1->word<<endl;
     print(root1->right);//prints the right subtree
}//end of print funtion

int isNonword(char *p){//checks if it is a character or functuation mark
    if((*p=='.')||(*p==',')) return 1;//returns 1 if it is a functuation mark
    else if((*p=='!')||(*p=='?')) return 1;
    else return 0;//else return 0 if character/letter
}//end of isNonword function

This line looks weird to me:

while(inWordFile>>(fgets(line, 100, stdin))){//read the file a line

If you were using the std::string class instead of c-strings (char*), you could just do something along these lines:

string word;
while(inWordFile >> word) {
  if(!notWord(word)) // though I'd change it to if(isWord(word))
    root = insert(root, word);

There'd be some smaller changes in your other code, but I think it'd do about what you're aiming for...

Member Avatar for sakura_fujin

i still don't get what's wrong...

i don't know how to use classes..

this line

while(inWordFile>>(fgets(line, 100, stdin)))

is roughly saying:

while( read in a word from inWordFile and store it in 
                (read in 100 chars from stdin and save it in the variable line))

That won't work, since you need to save the word in a variable. Hence this:

while( inWordFile >> word)
//while ( read in a word and save it in a variable called word)

For this to work, though, you'll need to use the std::string type (#include <string>). The string type will handle arbitrary size strings, so you don't have to worry about buffer overflows. And the whole business of copying pointers won't be an issue either.

Now that I'm thinking about it, it doesn't look like you were copying data before either. So all of your BSTNodes would have ended up with the same string, since all of their pointers would point to the same memory. Here's how that would happen:
- you'd put the new word in the character array called word.
- you'd add that to the tree, and the new node would point at the char array
- you'd read a new word into the char array. This would change the word for the first one as well, since they point to the same memory.
- you'd add the new word to the tree. Since it would have the same value as the old one, you'd just increment the counter.
- repeat as necessary
At the end, you've got a single node with the last word and a count of all the words. This is one of the problems that a lot of people have when they first use char* types. Did that make any sense to you?

>For this to work, though, you'll need to use the std::string type (#include <string>).

...really? I've used ifstream before with C strings and never had a problem. From what I know, it's simply derived from the same stream object as cin, as the only difference between them is where they're getting the input from. Of course, you're still having the problem that the C strings are statically sized, but as far as I know, there's nothing stopping you from using a C string for input from ifstream.

Secondly, std::string is also defined (or included, I'm not sure) in iostream , so you don't have to explicity #include <string> if you're only using the strings for storage.

This is C++ so the only place you need the keyword struct in this program is on line 10. I don't know that it's wrong, illegal, or creates ambiguity to use it the other places you have, but it's certainly more typing.

Member Avatar for sakura_fujin

i think i'm starting to understand what infarction was saying... that every pointer i had points to the same memory so that it replaces whatever the memory contains until it reaches the last word... hmm.... but i still don't know how to use classes since our professor never taught us that one...

do you guys think i should rewrite the whole program again? (i think i should... :( )

Although your header files and your stream use can only be used with C++, the style/flow of your coding is C, whcih is fine in C++, too. You'll have to use at least one struct declaration to do this project no matter what. If you really wanted to use classes instead of a C style struct, the interface could look something like this, using your function declarations:

struct BSTNode
    char * word;
    int count;
    BSTNode * left;
    BSTNode * right;

struct BSTree
     BSTNode * root;
     void print();
     int isNonWord(char *);
     BSTNode * allocate(char *);
     BSTNode * insert(char *);

However, since you haven't been instructed in use of classes and how you can group associated functions within the class/struct declaration, etc, it's probably best to keep it in the style you have with the corrections suggested.

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.