tags:

views:

166

answers:

2

I'm trying to read in a list of words and save them in a C++ STL hash_map along with their position in the alphabetically sorted file. The idea is later I'll need to be able to tell if a string is a word and whether it comes before or after a different word.

ifstream f_dict ("dictionary.txt");
__gnu_cxx::hash_map <const char*, int> dictionary;
string temp_str;
int counter = 0;
while (!f_dict.eof()) {
    f_dict >> temp_str;
    dictionary.insert(make_pair(temp_str.c_str(), counter++));
}

The problem I'm having is that it isn't saving the actual word. The for loop below prints out a selection of the words, but iter->first is always empty. What am I missing?

__gnu_cxx::hash_map<const char*, int>::iterator iter;
int i = 0;
for (iter = dictionary.begin(); iter != dictionary.end() && i < 150; iter++) {
    cout << "word: " << iter->first << " index: " << iter->second << "\n";
    i++;
}
+3  A: 

You are trying to store the same const char * for each word because your never creating any new memory for the word pulled from the file. If you print out the pointer being returned from temp_str.c_str(), it will be the same for every call within your first loop. In your second loop you're printing out the same char * for every record in your map (note there is only 1 b/c map does not allow dups) which has been set to empty string either within the 1st loop or between that and your for loop.

Here is example code that demonstrates the problem and a solution.

#include <fstream>
#include <iostream>
#include <map>

using namespace std;

int main (int argc, char **argv)
{
    ifstream file("test.txt");
    map<const char *, int> dictionary;
    map<string, int>       strDictionary;

    string temp_str;
    int counter = 0;
    while (!file.eof())
    {
        file >> temp_str;
        cout << "PARSED:    " << temp_str << "\n";
        cout << "INSERTING: " << (unsigned long) temp_str.c_str() << "\n";
        dictionary.insert(make_pair(temp_str.c_str(), counter));
        strDictionary.insert(make_pair(temp_str, counter));
        counter++;
    }

    cout << "Dictionary Size: " << dictionary.size() << "\n";
    cout << "Str Dictionary Size: " << strDictionary.size() << "\n";

    for (map<const char*, int>::const_iterator iter = dictionary.begin();
         iter != dictionary.end();
         ++iter)
    {
        cout << "CHAR * DICTINARY: " << iter->first << " -> " << iter->second << "\n";
    }

    for (map<string, int>::const_iterator iter = strDictionary.begin();
         iter != strDictionary.end();
         ++iter)
    {
        cout << "STR DICTIONARY: " << iter->first << " -> " << iter->second << "\n";
    }
    return 1;
}
RC
A: 

You want to use std::string as your key type, not const char *, otherwise the string won't get copied, and you'll end up with the same key on each insert.

Martin