iterate over ini file on c++, probably using boost::property_tree::ptree?

前端 未结 2 2251
执念已碎
执念已碎 2021-02-10 16:09

My task is trivial - i just need to parse such file:

Apple = 1
Orange = 2
XYZ = 3950

But i do not know the set of available keys. I was parsing

相关标签:
2条回答
  • 2021-02-10 16:16

    For the moment, I've simplified the problem a bit, leaving out the logic for comments (which looks broken to me anyway).

    #include <map>
    #include <fstream>
    #include <iostream>
    #include <string>
    
    typedef std::pair<std::string, std::string> entry;
    
    // This isn't officially allowed (it's an overload, not a specialization) but is
    // fine with every compiler of which I'm aware.
    namespace std {
    std::istream &operator>>(std::istream &is,  entry &d) { 
        std::getline(is, d.first, '=');
        std::getline(is, d.second);
        return is;
    }
    }
    
    int main() {
        // open an input file.
        std::ifstream in("myfile.ini");
    
        // read the file into our map:
        std::map<std::string, std::string> dict((std::istream_iterator<entry>(in)),
                                                std::istream_iterator<entry>());
    
        // Show what we read:
        for (entry const &e : dict) 
            std::cout << "Key: " << e.first << "\tvalue: " << e.second << "\n";
    }
    

    Personally, I think I'd write the comment skipping as a filtering stream buffer, but for those unfamiliar with the C++ standard library, it's open to argument that would be a somewhat roundabout solution. Another possibility would be a comment_iterator that skips the remainder of a line, starting from a designated comment delimiter. I don't like that as well, but it's probably simpler in some ways.

    Note that the only code we really write here is to read one, single entry from the file into a pair. The istream_iterator handles pretty much everything from there. As such, there's little real point in writing a direct analog of your function -- we just initialize the map from the iterators, and we're done.

    0 讨论(0)
  • 2021-02-10 16:29

    To answer your question directly: of course iterating a property tree is possible. In fact it's trivial:

    #include <boost/property_tree/ptree.hpp>
    #include <boost/property_tree/ini_parser.hpp>
    
    int main()
    {
        using boost::property_tree::ptree;
        ptree pt;
    
        read_ini("input.txt", pt);
    
        for (auto& section : pt)
        {
            std::cout << '[' << section.first << "]\n";
            for (auto& key : section.second)
                std::cout << key.first << "=" << key.second.get_value<std::string>() << "\n";
        }
    }
    

    This results in output like:

    [Cat1]
    name1=100 #skipped
    name2=200 \#not \\skipped
    name3=dhfj dhjgfd
    [Cat_2]
    UsagePage=9
    Usage=19
    Offset=0x1204
    [Cat_3]
    UsagePage=12
    Usage=39
    Offset=0x12304
    

    I've written a very full-featured Inifile parser using boost-spirit before:

    • Cross-platform way to get line number of an INI file where given option was found

    It supports comments (single line and block), quotes, escapes etc.

    (as a bonus, it optionally records the exact source locations of all the parsed elements, which was the subject of that question).

    For your purpose, though, I think I'd recomment Boost Property Tree.

    0 讨论(0)
提交回复
热议问题