Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
250 views
in Technique[技术] by (71.8m points)

unordered map - C++ map insert problem with objects containing another map

I have unordered map containers containing another maps.

using name = std::string;
using stop_o = std::pair<name, std::unordered_map<key,/**/ std::pair<name, std::unordered_map<key, std::pair<name, std::map<packed_time, std::pair<packed_time, std::pair < int, std::map<int, std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>>>>>>>>>>;
using platform_o = std::pair<name, std::unordered_map<key,/**/ std::pair<name, std::map<packed_time, std::pair<packed_time, std::pair < int, std::map<int, std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>>>>>>>>;
using platform_route_o = std::pair<name, std::map<packed_time,/**/ std::pair<packed_time, std::pair < int, std::map<int, std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>>>>>>;
using route_departure_o = std::pair<packed_time,/**/ std::pair < int, std::map<int, std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>>>>;
using trip_o = std::pair < int, std::map<int,/**/ std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>>>;
using trip_departure_o = std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>;

trip_o is just a pair of int and trip_departure_o. Then I am using containers:

using stop_container = std::unordered_map<key, stop_o>;
using platform_container = std::unordered_map<key, platform_o>;
using platform_route_container = std::unordered_map<key, platform_route_o>;
using route_departure_container = std::map<packed_time, route_departure_o>;
using trip_container = std::unordered_map < int, trip_o>;
using trip_departure_container = std::map<int, trip_departure_o>;

// main object - put something inside
class timetable {
    public:
    stop_container timetable_stops;
    trip_container timetable_trips;
};

My code is:

void read_timetable(timetable& tt, std::istream& ifs)
{
    std::string line, token;
    ifs.ignore(1000, '
');
    while (std::getline(ifs, line, '
'))
    {
        std::vector<std::string> v;
        std::stringstream entry(line);
        while (std::getline(entry, token, ''))
        {
            v.push_back(token);
        }
        std::vector<int> time;
        std::stringstream t(v[5]);
        while (std::getline(t, token, ':'))
        {
            time.push_back(stoi(token));
        }
        packed_time pt = pack_time(time[0], time[1]);

        if (tt.timetable_stops.find(v[4]) == tt.timetable_stops.end())
        {
            trip_departure_o td;
            td.first = stoi(v[2]);
            td.second.first = pt;
            td.second.second.first = v[4];
            td.second.second.second = &tt;

            trip_o tr;
            tr.first = stoi(v[1]);
            tr.second.insert({ stoi(v[1]), td });
            std::cout << tr.second.at(stoi(v[1])).first << std::endl;

            route_departure_o rd;
            rd.first = pt;
            rd.second = tr;
            std::cout << rd.second.first << std::endl;

            platform_route_o pr;
            pr.first = v[0];
            pr.second.insert({ pt, rd });
            std::cout << pr.second.at(pt).first << std::endl;

            platform_o p;
            p.first = v[3];
            p.second.insert({ v[3], pr });

            stop_o s;
            s.first = v[4];
            s.second.insert({ v[4], p });
            std::cout << s.second.at(v[4]).first << std::endl;

            tt.timetable_stops.insert({ v[4], s });

            std::cout << tt.timetable_stops.at(v[4]).second.at(v[3]).first;
            }
        }
... .. .

I split line from input to 6 tokens everytime. Then I convert last token(time) to hours and minutes and pack it to one int. Now goes the problem. I succesfully create trip_departure td, with test outputs I know that there are all variables in it. Then I initialize trip_o tr. First variable is there, but when I want to getthe second one which is in fact the previous object td, I get an error:

Unhandled exception at 0x00007FFCBF09D759 in jr.exe: Microsoft C++ exception: std::invalid_argument at memory location 0x0000007FF891D410.

The exception is thrown on this line:

std::cout << tt.timetable_stops.at(v[4]).second.at(v[3]).first;

It looks like it wasnt inserted to the map. But why?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem is in the second at, with v[3].

The first at returns a reference to the copy of s that was added to the timetable stops. That copy has an element at v[4], not v[3]. So you either want

tt.timetable_stops.at(v[4]).second.at(v[4])

or

tt.timetable_stops.at(v[4]).second.at(v[4]).second.at(v[3])
//                 ^ returns copy of s
//                                  ^ returns copy of { v[4], p } originally stored in s
// returns copy of p stored in ...                 ^

This would be easier to see and diagnose if you'd use proper structures with appropriately named members rather than a complicated mass of type aliases.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...