Can someone explain to me how to use std::map?

I am having a hard time completely understanding the concept behind std::map.

From what i understand so far, std::map is a container (similar to an array/vector) and is capable of storing any type of variables.. but i can't really picture it in my mind... does it work similarly to how we store values in subscripts of an array?
Map is an associative container, making it fundamentally different to arrays and vectors. What a map does is store a list of keys in order, meaning the key type must have a < operator. What it does is associate a mapped value to each key, which means the keys have to be unique, although the mapped values can be similar. A simple std::map<std::string,int> can be thought of like a run-time enum. It associates an int with a string so that each object in the array now has a name (which is a string) and is accessed via map["string-here"], which returns an int. As it is an STL container (Standard Template Library), you are quite correct at thinking they can contain any type, as a mapped value, but only orderable types as key values.
Oh i think i understand now, so when we make a map like this..

 
std::map<std::string , char> grades;


then we have created an "array" but we haven't specified the size of the array. So in order for us to initialize a "subscript" in this "array" then we have to do this...

 
grades ["SomeAmazingGuy"] = 'F';


so now i have just initialized the first element of this map.. and to access this subscript, i have to use the string literal "SomeAmazingGuy" inside the brackets

I have one more question... is there a "faster" way to initialize ,lets say, 500 subscripts in a map?
The point of a map is that each mapped value has its own unique key value, so usually, you don't want to create things based on some pattern which you could put in a loop. In the example you used where you are linking a string and a letter (the string doesn't have to be a literal but it can be), unless there is a fixed pattern between key and mapped value and the key changes in a constant way, then no, you can't do that. Why do you want to create 500 "subscripts" (if I understand you correctly, I believe you mean elements).
Last edited on
Yes i meant to say elements. And the reason i want to make 500 elements is just to experiment with maps, i don't have a special reason on why i want to do that.

So i guess the only way to initialize the elements in a map is to manually do each one individually then ....
Technically you can use a loop to initialise a map based on predictable values, but this isn't usually what maps are used for. For example you could make a map which imitates an array std::map<int,std::string> You could then make a program that adds 500 randomly generating strings to the map, but when you are doing something like this, there is no point not just using an array.
Last edited on
You could use a loop to add unpredictable values?

First 10 of 1000 values:

Ababali Ucivu         A
Abehic Nasujev        E
Abosod Iwow           D
Abucuje Udunu         E
Abufi Qod             E
Abumaxuki Origet      B
Abunuvamole Juqoza    E
Aceboqi Umelo         D
Acerexesi Letumaf     E
Aciqen Saguzejoq      A


I wrote the function GenerateRandomName() to help with testing search routines; the generated "names" have a similar lengths and mix of vowels and consonants to real names, which is what mattered. (The way I chose the length of the names comes form a web site where it said X% of names are Y chars long, with the help of Excel to accumulate the values and scale them to round numbers.)

Andy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <cstdlib>
#include <ctime>
#include <cassert>

namespace Utils {

inline int Random(int min, int max) {
    assert(min <= max);
    double temp = static_cast<double>(rand()) / (static_cast<double>(RAND_MAX) + 1.0);
    return static_cast<int>(min + temp * (max - min + 1));
}

std::string GenerateRandomName();

} // end namespace Utils

int main() {
    std::srand(static_cast<unsigned>(std::time(0)));
    // for testing could use fixed seed

    std::cout << std::left;

    std::map<std::string, char> studentGrades;

    const int count = 1000;

    for(int i = 0; i < count; ++i) {
        std::string firstName = Utils::GenerateRandomName();
        std::string lastName  = Utils::GenerateRandomName();

        std::string name = firstName;
        name += " ";
        name += lastName;

        // assumes grade = A B C D E F
        int gradeOffset = Utils::Random(0, 5);
        char grade = static_cast<char>('A' + gradeOffset);
        //for debugging
        //std::cout << "Add : " << name << " " << grade << "\n";
        studentGrades.insert(make_pair(name, grade));
    }

    const int maxDisplayCount = 10;
    int displayCount = 0;

    std::cout << "First "
        << std::min(maxDisplayCount, static_cast<int>(studentGrades.size()))
        << " of " << studentGrades.size() << " values:\n\n";

    std::map<std::string, char>::iterator iter = studentGrades.begin();

    while((iter != studentGrades.end()) && (maxDisplayCount > displayCount)) {
        std::cout << std::setw(20) << (*iter).first << "  " << (*iter).second << "\n";
        ++iter;
        ++displayCount;
    }

    return 0;
}

namespace RandNameData {

static const char* vowels[]= { "a", "e", "i", "o", "u" };
static const size_t vowelCount = sizeof(vowels)/sizeof(vowels[0]);

static const char* consonants[] = { "b", "c", "d", "f", "g", "h", "j",
    "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "z" };
static const size_t consonantCount = sizeof(consonants)/sizeof(consonants[0]);

} // end namespace RandNameData

std::string Utils::GenerateRandomName() {
    using namespace RandNameData;

    std::string name;

    bool vowelWanted = (1 == Random(0, 1));

    size_t targetLen = 0;

    int temp = Random(1, 663);
    if(650 < temp) targetLen = 11;
    else if(615 < temp) targetLen = 10;
    else if(525 < temp) targetLen = 9;
    else if(525 < temp) targetLen = 8;
    else if(400 < temp) targetLen = 7;
    else if(225 < temp) targetLen = 6;
    else if( 80 < temp) targetLen = 5;
    else if( 12 < temp) targetLen = 4;
    else if(  1 < temp) targetLen = 3;
    else targetLen = 2;

    while(targetLen > name.length()) {
        if(vowelWanted) {
            int index = Random(0, vowelCount - 1);
            name += vowels[index];
            vowelWanted = false;
        } else {
            int index = Random(0, consonantCount - 1);
            name += consonants[index];
            vowelWanted = true;
        }
    }

    name[0] = static_cast<char>(toupper(name[0]));

    return name;
}

Last edited on
Topic archived. No new replies allowed.