-5

This code prompts the user asking their name and the school they attend. Storing both into a map(the names into vector). I then want to print out the school and the name of every person that attended that school in this format.

School : name, name , name. /new line School : name, name , name etc. . . .

I first did in java and am trying to convert to c++ not sure if I am doing this correctly, also not sure how to convert the for loop at bottom to c++ (is there something similar to map.keySet() from java in c++ ?)

I keep getting errors for the emplace() is there something that I am doing wrong or need to #include?

int main() {

//Program that takes in users school that they attend and prints out the people that go there

string name;
string school;

//create the map
map<string, vector<string> > sAtt;



do {

    cout << "PLEASE ENTER YOUR NAME: (type \"DONE\" to be done" << endl;
    cin >> name;
    cout << "PLEASE ENTER THE SCHOOL YOU ATTEND:" << endl;
    cin >> school;

    if(sAtt.find(school)) {//if school is already in list

        vector<string> names = sAtt.find(school);
        names.push_back(name);
        sAtt.erase(school); //erase the old key
        sAtt.emplace(school, names); //add key and updated value

    } else { //else school is not already in list so add i

        vector<string> names;
        names.push_back(name);
        sAtt.emplace(school, names);

    }

}while(!(name == "done"));
sAtt.erase("done");

cout << "HERE ARE THE SCHOOLS ATTENDED ALONG WITH WHO GOES THERE: " << endl;


for (string s: sAtt.keySet()) { //this is the java way of doing it not sure how to do for c++
    cout << "\t" << s << sAtt.find(s) << endl;

    //should be School: name, name, name, etc. for each school

}

}

Msarn21
  • 11
  • 1
  • 6
  • Possible duplicate of [C++ Loop through Map](https://stackoverflow.com/questions/26281979/c-loop-through-map) – Fureeish Dec 08 '18 at 22:03
  • Are you sure you get compiler errors at `emplace` and not at `vector names = sAtt.find(school);`? emplace usage looks fine for me. – Yksisarvinen Dec 08 '18 at 22:05
  • 2
    And sorry, but learning C++ by converting code from Java is bound to be a huge headache. For example, `if(sAtt.find(school))` is always true, no matter what is in `school` and in `sAtt`. I recommend [a good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) to learn C++ from basics. – Yksisarvinen Dec 08 '18 at 22:07
  • @Yksisarvinen for the if statement would if( sAtt.count(school)) work instead – Msarn21 Dec 08 '18 at 22:11
  • IMO, the more C++ *-ish* way is to compare it with `end` iterator: `if(sAtt.find(school) != sAtt.end())`. `count` will work, as it returns 1 or 0 always, but it looks strange. – Yksisarvinen Dec 08 '18 at 22:14
  • @Yksisarvinen I will rather not read a C++ book. – Det Feb 22 '20 at 18:08

2 Answers2

2

You should be getting numerous errors with this code. Overall, this project looks like this is something you should code from scratch in C++, not simply try to translate line-for-line from Java. Think about what you want to do, not how to replicate Java.

For example, what is the following code snippet supposed to do?

if(sAtt.find(school)) {//if school is already in list

    vector<string> names = sAtt.find(school);
    names.push_back(name);
    sAtt.erase(school); //erase the old key
    sAtt.emplace(school, names); //add key and updated value

} else { //else school is not already in list so add i

    vector<string> names;
    names.push_back(name);
    sAtt.emplace(school, names);

}

You could explain this line-by-line, but the overall process is to add name to the end of the vector associated with school, creating that vector if needed. Now take a look at std::map::operator[]. It returns (a reference to) the value associated with a given key, creating that value if needed. So a simpler way to do the above is:

sAtt[school].push_back(name);

One line, and no problems associated with trying to convert iterators to booleans or value types.

As for getting the values out of the map, you would iterate through the map, rather than constructing a helper set of values and iterating through that. A starting point (not exactly what you wanted) is:

for ( auto & mapping : sAtt ) {           // Loop through all school -> vector pairs, naming each pair "mapping".
    cout << mapping.first << ":";         // The first element in the pair is the school name.
    for ( auto & name : mapping.second )  // Loop through the associated vector of names.
        cout << '\t' << name;             // Using tabs instead of commas.
    cout << endl;                         // End the school's line.
}

Basically, you should keep in mind that a std::map contains pairs, with .first being the key and .second being the value.

JaMiT
  • 14,422
  • 4
  • 15
  • 31
0

In C++, you can use an iterator to go through your map.

For example:

cout << "HERE ARE THE SCHOOLS ATTENDED ALONG WITH WHO GOES THERE: " << endl;

// Create iterator
map<string, vector<string> >:: iterator itr;

// Iterator
for (itr = sAtt.begin(); itr != sAtt.end(); ++itr){

         // Print school name
         cout << "School Name: " << itr -> first << endl;


         // Code that would go through vector and print contents

}

If you'd like to learn more about maps in C++, this is a good resource to use: https://www.geeksforgeeks.org/map-associative-containers-the-c-standard-template-library-stl/

Sam Moran
  • 1
  • 2
  • better to use `auto` over `map >:: iterator`. Better to use *range based for* instead of traditional loop. And even better to use structured bindings, if `C++17` is an option – Fureeish Dec 08 '18 at 22:18
  • how would you print the values to go along with the keys – Msarn21 Dec 09 '18 at 00:38