HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Converting a string to a list of key-value pairs

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
pairsvalueconvertingliststringkey

Problem

I'm trying to convert a string (here after called input) into a vector of key-value pairs, all in C++03 (cannot use C++11, cannot use Boost libs).

The string in question can contain whitespaces. A comma (,) delimits key-value pairs and the equals sign (=) separates the key from the value.
A sample string (also in the code could be: "ab=xy z,time a=1s". Notice the lack of a final ,.

Any improvement is most welcome.

#include 
#include 
#include 
#include 
#include 

struct Flag_name_value {
    std::string name;
    std::string value;
};

std::istringstream& operator>>(std::istringstream& iss, Flag_name_value& fnv)
{
    char ch; 
    std::ostringstream oss;

    while (iss >> std::noskipws >> ch) {
        std::cout  flags;
    while (true) {
        Flag_name_value f;
        iss >> f;
        flags.push_back(f);
        if (!iss) break;
    }

    return 0;

}

Solution

First, you can use std::getline to extract key-value pairs from the original string. This can be done by passing , as a delimiter to std::getline:

while (std::getline(iss, token, ',')) { ... }


Notice that you don't have to perform any checks on the stream this way. Once std::getline will reach the end of the stream it will set the eofbit on it, so the loop condition will evaluate to false on next iteration.

Next, use can use std::string::find to find an index of the occurrence of the = character in strings filled by std::getline:

size_t pos = token.find('=');


After that use can use this index to extract two substrings - your key and your value:

flag.name    = token.substr(0, pos);
flag.value   = token.substr(pos + 1);


Notice that you can omit the second argument of std::string::substr, since it has the default value of std::string::npos. This value is very huge (in fact, it equals to the maximum value that can be represented by a size type of std::string), but std::string::substr never reads past the end of line, so everything will be good.

Tie all this together and you'll get a small and readable solution:

std::string input("ab=xy z,time a=1s");
std::istringstream iss(input);

std::vector flags;

std::string token;
Flag_name_value flag;
while (std::getline(iss, token, ',')) {
    size_t pos   = token.find('=');
    flag.name    = token.substr(0, pos);
    flag.value   = token.substr(pos + 1);
    flags.push_back(flag);
}

Code Snippets

while (std::getline(iss, token, ',')) { ... }
size_t pos = token.find('=');
flag.name    = token.substr(0, pos);
flag.value   = token.substr(pos + 1);
std::string input("ab=xy z,time a=1s");
std::istringstream iss(input);

std::vector<Flag_name_value> flags;

std::string token;
Flag_name_value flag;
while (std::getline(iss, token, ',')) {
    size_t pos   = token.find('=');
    flag.name    = token.substr(0, pos);
    flag.value   = token.substr(pos + 1);
    flags.push_back(flag);
}

Context

StackExchange Code Review Q#107899, answer score: 7

Revisions (0)

No revisions yet.