Jishan
Jishan

Reputation: 1684

Parse String Between Brackets

I have a string that goes like this:

Room -> Subdiv("X", 0.5, 0.5) { sleep | work } : 0.5

I need to somehow extract the 2 strings between {} , i.e. sleep and work. The format is strict, there can be just 2 words between the brackets, the words can change though. The text before and after the brackets can also change. My initial way of doing it was:

string split = line.substr(line.find("Subdiv(") + _count_of_fchars);
split = split.substr(4, axis.find(") { "));
split = split.erase(split.length() - _count_of_chars);

However, I do realised that this is no going to work if the strings in side the brackets are changed o anything with a different length.

How can this be done? Thanks!

Upvotes: 2

Views: 7825

Answers (3)

muXXmit2X
muXXmit2X

Reputation: 2765

Even though you said that the amount of words to find is fixed I made a little more flexible example using a regular expression. However you could still achieve the same result using Мотяs answer.

std::string s = ("Room -> Subdiv(\"X\", 0.5, 0.5) { sleep | work } : 0.5")
std::regex rgx("\\{((?:\\s*\\w*\\s*\\|?)+)\\}");
std::smatch match;

if (std::regex_search(s, match, rgx) && match.size() == 2) {
    // match[1] now contains "sleep | work"
    std::istringstream iss(match[1]);
    std::string token;
    while (std::getline(iss, token, '|')) {
        std::cout << trim(token) << std::endl;  
    }
}

trim removes leading and trailing spaces and the input string could easily be expanded to look like this: "...{ sleep | work | eat }...".

Here is the complete code.

Upvotes: 1

WhiZTiM
WhiZTiM

Reputation: 21576

Without hard-coding any numbers:

  • Find A as the index of the first "{" from the end of the string, search backward.
  • Find B as the index of the first "|" from the position of "{", search forward.
  • Find C as the index of the first "}" from the position of "|", search forward.

The substring between B and A gives you the first string. While the substring between C and B gives you the first string. You can include the spaces in your substring search, or take them out later.

std::pair<std::string, std::string> SplitMyCustomString(const std::string& str){
    auto first = str.find_last_of('{');
    if(first == std::string::npos) return {};

    auto mid = str.find_first_of('|', first);
    if(mid == std::string::npos) return {};

    auto last = str.find_first_of('}', mid);
    if(last == std::string::npos) return {};

    return { str.substr(first+1, mid-first-1), str.substr(mid+1, last-mid-1) };
}

For Trimming the spaces:

std::string Trim(const std::string& str){
    auto first = str.find_first_not_of(' ');
    if(first == std::string::npos) first = 0;

    auto last = str.find_last_not_of(' ');
    if(last == std::string::npos) last = str.size();

    return str.substr(first, last-first+1);
}

Demo

Upvotes: 3

Matt
Matt

Reputation: 1308

Something like:

unsigned open = str.find("{ ") + 2;
unsigned separator = str.find(" | ");
unsigned close = str.find(" }") - 2;
string strNew1 = str.substr (open, separator - open);
string strNew2 = str.substr (separator + 3, close - separator);

Upvotes: 2

Related Questions