Gavin Le
Gavin Le

Reputation: 11

How to split string by multiple bracket types but still keep the brackets in C++?

Is there a way to split a string into small part and store into vector.

For example:

A string: str = "(a b c) d e f [[g h i]]". The output expected is:

(a b c)
d e f
[[g h i]]

Sample code:

vector<string> token;
string str = "(a b c)d e f[[g h i]]";
string bracketS = "()[]";
istringstream ss(str);
string section;
string tok;

while (getline(ss,section)) {
    size_t start = 0;
    size_t end = section.find_first_of(bracketS);
    while (end != string::npos) {
        tok = section.substr(start, end - start);
        token.push_back(tok);
        start = end + 1;
        end = section.find_first_of(bracketS, start);
    }
}

And output is without the brackets:

      a b c
      d e f
      g h i 

Tried to adjust my section.substr(start-1, end - start+2) Then my output is:

(a b c)
) d e f [
[g h i]

Why the middle vector is wrong.

Also tried do strtok. But the output is the same as the first one.

Is there any other way to do it?

Upvotes: 0

Views: 778

Answers (1)

mostsignificant
mostsignificant

Reputation: 322

This is a possible solution with a stack for parsing and throwing a parsing_error if there are opening brackets missing closing brackets or the closing bracket mismatches the opening one.

#include <iostream>
#include <stack>
#include <string>
#include <vector>

const auto Brackets = { std::make_pair('(', ')'), std::make_pair('[', ']') };

const auto is_opening_bracket = [](const char c) {
    return std::find_if(Brackets.begin(), Brackets.end(),
            [c](const auto& p) { return p.first == c; } ) != Brackets.end();
};
const auto is_closing_bracket = [](const char c) {
    return std::find_if(Brackets.begin(), Brackets.end(),
            [c](const auto& p) { return p.second == c; } ) != Brackets.end();
};

const auto get_opening_bracket = [](const char c) {
    const auto p = std::find_if(Brackets.begin(), Brackets.end(), [c](const auto& p) { return p.second == c; });
    if (p == Brackets.end())
        return '0';

    return p->first;
};

struct parsing_error {};

int main() {
    const std::string str = "(a b c)d e f[[g h i]]";

    std::stack<char> brackets;
    std::vector<std::string> tokens;
    std::string token;

    for (const auto c : str) {
        if (is_opening_bracket(c)) {
            if (!token.empty() && brackets.empty()) {
                tokens.push_back(token);
                token.clear();
            }

            brackets.push(c);
            token += c;
        } else if (is_closing_bracket(c)) {
            if (brackets.top() != get_opening_bracket(c))
                throw parsing_error();

            brackets.pop();
            token += c;

            if (brackets.empty()) {
                tokens.push_back(token);
                token.clear();
            }
        } else {
            token += c;
        }

    }

    if (!brackets.empty())
        throw parsing_error();

    for (const auto& token : tokens)
        std::cout << token << '\n';

    return 0;
}

Upvotes: 1

Related Questions