SmRndGuy
SmRndGuy

Reputation: 1819

C++: How to make a simple dictionary?

I'm trying to make a dictionary with 2-character words but not so much success Here's my code:

#include <cstdlib>
#include <iostream>
#include <map>
using namespace std;

int main(int argc, char *argv[]){
    map<char*,int> m;
    //input 5 two-lengthed words 
    for (int i=0;i<5;i++){
        char s[3];
        cin>>s;
        s[2] = '\0';
        m[s]=1; //add a key
    }
    //checking if a word exists.

    cout<<"Word you want to check whether it exists:"<<endl;
    char chck[3];
    cin>>chck;
    chck[2]='\0';
    //I heard this is how you check whether a key exists:
    bool exists = m.find(chck)==m.end(); 
    cout<<((exists)?"Yes!":"No.")<<endl;
    system("pause"); //Yea, system, I know.
    return 0;
}

Whenever I enter the words, and then when I want to check whether a word is in a dictionary, I always get printed "No."?
I come from Java so I got used to references, not pointers, so that's where I'm probably wrong. I want to learn how to properly use the maps so can you please what am I supposed to do here?

Thanks

Upvotes: 4

Views: 29370

Answers (3)

juanchopanza
juanchopanza

Reputation: 227390

//I heard this is how you check whether a key exists:
bool exists = m.find(chck)==m.end(); 

Yes, but the condition is true if the element does not exist. You should call your vaviable notExists:

bool notExists = m.find(chck)==m.end();

Now, if all you want to do is check if a work exists, you can use an std::set<std::string>. If you want the word to be a key to something else, then you need std::map<std::string, SomeThingElse>.

Forget about those char*. Use std::strings.

Upvotes: 8

Jonathan Wakely
Jonathan Wakely

Reputation: 171263

    m[s]=1; //add a key

Each time you "add a key" you're actually just getting the same element, with the same key. The key is the address of the array s, not the value of the string entered.

Try printing out the size of the container and you'll see a single element:

   std::cout << m.size() << '\n';

When you put a char* in a container and use the default comparison function they only compare equal when they are the same pointer, not the same string:

 char s1[] = "foo";
 char s2[] = "foo";
 assert( s1 == s2 );   // FAILS!

To push string values into the container use std::string keys, not char*

std::string s1 = "foo";
std::string s2 = "foo";
assert( s1 == s2 );   // passes

This avoids the whole problem of comparing pointers and of the array going out of scope leaving a dangling pointer in the map.

Upvotes: 2

Andre Kostur
Andre Kostur

Reputation: 780

Let's look at your code a bit:

You have a std::map<char *, int>. That first "char*" is suspicious as a key to the map. Storing pointers as the key isn't often what you really want to do. But we keep reading. Inside your loop you have a local array s that you populate. Then you use that variable to index into the map. Remember that the key to the map is a char*. The address of the array s is likely to be the same on every loop iteration. As a result, you are probably putting only one item into your map, and it only holds the most recent value of what you put into s. But wait, it gets worse. As soon as your loop is done, s goes out of scope and it is now Undefined Behaviour to dereference the pointer that's currently stored in the map (as the key to the one and only element in that map. Output m.size() to verify).

Redefine your map to be std::map<std::string, int> to not have all of these problems.

Upvotes: 2

Related Questions