patterncppMinor
Converting a string to a list of key-value pairs
Viewed 0 times
pairsvalueconvertingliststringkey
Problem
I'm trying to convert a string (here after called
The string in question can contain whitespaces. A comma (
A sample string (also in the code could be:
Any improvement is most welcome.
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
Notice that you don't have to perform any checks on the stream this way. Once
Next, use can use
After that use can use this index to extract two substrings - your key and your value:
Notice that you can omit the second argument of
Tie all this together and you'll get a small and readable solution:
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.