[RESOLVED] Trees (Maps) problem
Hello, I am trying to use a red-black tree, STL Map, to read in a file that counts the words while ignoring punctuation and converting all words to lowercase. My problem occurs when I try to print and nothing outputs to the screen. I think it has something to do with my for loop in my print function. I have looked over it many times along with some of my fellow students and everyone seems to think it too should be working. I probably have done something stupid and really would appreciate an expert or someone who knows this more than I do to point out my mistake, anything, thanks.
Header file
Code:
#ifndef MAP_H
#define MAP_H
#include <iostream>
#include <map>
#include <string>
using namespace std;
class Map
{
public:
//map<string, int> words;
void inputFile(char inputfile[]);// read file
void insertTree(string new_word, map<string, int> &tree);//insert
void print(map<string, int> &tree);// print
};
#endif
Implementations
Code:
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include "Map.h"
using namespace std;
void Map::inputFile(char inputfile[])// read file
{
ifstream infile;
infile.open(inputfile);
int j;
char lowercase;
map<string, int> words;
string str_1, str_2;
while(infile >> str_1)
{
for(int i = 0, a = 0; i < str_1.length(); i++)
{
char &letter = str_1[i];
if(letter < 'A' || (letter > 'Z' && letter < 'a') || letter >'z') // only alphabet characters
{
for(int j = 0; j < str_1.length(); j++)
{
str_1[j] = tolower(str_1[j]); // make all lowercase
}
str_2 = str_1.substr(a, i - a);
a = i +1;
if(str_2.length() > 0)
{
insertTree(str_2, words); // insert into the tree
}
}
}
}
infile.close();
}
void Map::insertTree(string new_word, map<string, int> &tree)
{
// cout << "Insert" << endl;
if(tree.find(new_word) == tree.end()) //Word is not currently in the tree
{
tree[new_word] = 1;
}
else //Word is in the tree
{
tree[new_word] = tree[new_word] + 1;
}
}
void Map::print(map<string, int> &tree)// print
{
// cout << "Out print" << endl;
for (map<string, int>::iterator print_it = tree.begin(); print_it != tree.end(); ++print_it)
{
// cout << "printing" << endl;
cout << print_it -> first << " => " << print_it -> second << '\n'; //.first is the data member, .second is the data.
}
}
Driver
Code:
#include <iostream>
#include <map> //Map
#include <string> //String
#include "Map.h"
using namespace std;
//void incrementTree(string new_word, map<string, int> &tree);
//void printTree(map<string, int> &tree);
int main() {
int choice;
char inputfile[100];
//The key (index for the tree) is a string value, the data we store in the tree is an integer value.
//Note that unlike the example from class, we are distinguishing here between the key and data.
map<string, int> words;
Map mapper;
Menu:
cout << "********Menu********" << endl;
cout << "1.) Please enter a file for input. " << endl;
cout << "2.) Print" << endl;
cout << "3.) Exit" << endl;
cout << "Please make a choice: ";
cin >> choice;
while(choice <= 3 || choice >= 1)
{
switch(choice)
{
case 1 : cout << "Filename: ";
cin >> inputfile;
mapper.inputFile(inputfile);
break;
case 2 : mapper.print(words);
break;
case 3 : cout << "Exiting." << endl;
goto Exit;
break;
default: cout << "ERROR!...Re-prompting input." << endl;
break;
}
goto Menu;
}
// incrementTree("the", words);
//incrementTree("quick", words);
// incrementTree("brown", words);
//incrementTree("fox", words);
//incrementTree("jumped", words);
//incrementTree("over", words);
//incrementTree("the", words);
//incrementTree("lazy", words);
//incrementTree("dog", words);
//printTree(words);
Exit:
return 0;
}
/*
void incrementTree(string new_word, map<string, int> &tree) {
//Word is not currently in the tree
if(tree.find(new_word) == tree.end()) {
tree[new_word] = 1;
}
//Word is in the tree
else {
tree[new_word] = tree[new_word] + 1;
}
}
void printTree(map<string, int> &tree) {
for (map<string, int>::iterator print_it=tree.begin(); print_it!=tree.end(); ++print_it)
//.first is the data member, .second is the data.
cout << print_it->first << " => " << print_it->second << '\n';
}*/
Thanks to all in advance.
Re: [RESOLVED] Trees (Maps) problem
When something doesn't work as it should rather than trying to guess the problem and just trying things 'to see if they work', use the debugger to trace through the code to see where it deviates from what was expected. You should become as familiar with the debugger as writing/compiling programs. Debugging programs is a skill that has to be learnt. Some of us who have been around programming for a long time seem to spend half our life in the debugger!
Re: [RESOLVED] Trees (Maps) problem
There are a few issues with your code:
1) Although this does not affect your program, you
should not put "using namespaec std;" in your
header file. It can cause name clash problems.
You should fully qualify the variable type. Example:
Code:
void print(std::map<std::string, int> &tree);// print
2) print() does not modify any variable in the Map class.
Therefore it should be a const function:
Code:
void print(std::map<std::string, int> &tree) const; // print
3) additionally, print does not modify the passed argument,
so you should pass by const reference, not by reference.
You would need to use const_iterator instead of iterator
in the function.
Code:
void print(const std::map<std::string, int> &tree) const; // print
4) in main, you call:
Code:
mapper.print(words);
But words is a local variable to main that is never modified.
That is why you did not see any output.
5) in your header, you comment out the line:
Code:
//map<string, int> words;
And instead you have "words" a local variable in the inputfile
function. I think you should keep the member variable words
and remove the local variable from inputfile. You would not
need to pass the map to print() and insertTree. Just make
sure those functions use the member variable, words.
6) There is nothing wrong with the way you coded insertTree,
but it can be simplified to one line (but it requires a little
more advanced knowledge on how operator [] works for std::map).