Search code examples
c++parsingpointersboosthashmap

How can I parse a char pointer string and put specific parts it in a map in C++?


Lets say I have a char pointer like this:

const char* myS = "John 25 Lost Angeles";

I want to parse this string and put it in a hashmap, so I can retrieve the person's age and city based on his name only. Example:

std::map<string, string> myMap;

john_info = myMap.find("John");

How can I do this to return all of John's info in an elegant way ? I come from a Java background and I really want to know how this is properly done in C++. That would also be cool if you can show me how to do this using a boost map (if it is easier that way). Thank you.


Solution

  • I'm going to show you one way to do it using Boost:

    Live On Coliru

    #include <map>
    #include <boost/fusion/adapted.hpp>
    #include <boost/spirit/home/x3.hpp>
    #include <iostream>
    namespace x3 = boost::spirit::x3;
    
    using Name = std::string;
    struct Details {
        unsigned age;
        std::string city;
    };
    
    using Map   = std::map<Name, Details>;
    using Entry = Map::value_type;
    
    BOOST_FUSION_ADAPT_STRUCT(Details, age, city)
    
    int main() {
        Map persons;
    
        std::string_view myS = //
            "John 25 Lost Angeles\n"
            "Agnes 22 Minion Appolis";
    
        auto name    = x3::lexeme[+x3::graph];
        auto age     = x3::uint_;
        auto city    = x3::raw[*(x3::char_ - x3::eol)];
        auto details = x3::rule<struct details_, Details>{} = age >> city;
        auto line    = name >> details;
        auto grammar = x3::skip(x3::blank)[line % x3::eol];
    
        if (x3::parse(myS.begin(), myS.end(), grammar, persons)) {
            for (auto& [name, details] : persons)
                std::cout << name << " has age " << details.age << "\n";
            for (auto& [name, details] : persons)
                std::cout << name << " lives in " << details.city << "\n";
        }
    
        // lookup:
        std::cout << "John was " << persons.at("John").age << " years old at the time of writing\n";
    }
    

    Prints

    Agnes has age 22
    John has age 25
    Agnes lives in Minion Appolis
    John lives in Lost Angeles
    John was 25 years old at the time of writing
    

    To use a hash-map, just replace

    using Map   = std::map<Name, Details>;
    

    with

    using Map   = std::unordered_map<Name, Details>;
    

    Now the output will be in implementation-defined order.

    CAVEAT

    If this is home-work, please don't use this (kind of) approach. It will be very clear it was copy-pasted. Never use code you don't fully understand.