Как разбить строку на несколько типов скобок, но при этом сохранить скобки в C++?

Есть ли способ разбить строку на небольшую часть и сохранить в векторе.

Например:

Строка: str = "(a b c) d e f [[g h i]]". Ожидаемый результат:

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

Образец кода:

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);
    }
}

И вывод без скобок:

      a b c
      d e f
      g h i 

Пытался настроить свой section.substr(start-1, end - start+2) Тогда мой результат:

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

Почему средний вектор неправильный.

Также пробовал делать стрток. Но результат такой же, как и у первого.

Есть ли другой способ сделать это?

А как насчет простого использования std::regex?

πάντα ῥεῖ 26.09.2018 21:06

Если вы ничего не знали о регулярных выражениях, но немного разбирались в элементарных структурах данных, вы могли бы попробовать std::stack и знать, когда можно использовать topush и pop, и тогда нет необходимости в strtok. Ваша попытка синтаксического анализа методом «грубой силы» - наивный подход.

PaulMcKenzie 26.09.2018 21:26

@PaulMcKenzie К счастью, OP вообще не использует strtok() в своем коде, или я что-то пропустил?

πάντα ῥεῖ 26.09.2018 21:28

@ πάνταῥεῖ ОП упомянул strtok в своем сообщении.

PaulMcKenzie 26.09.2018 21:29

Непонятно, что вы хотите делать с вложенными скобками. Например, что будет в результате (a b c) (d [e f] g)?

Jim Mischel 28.09.2018 17:37

@JimMischel именно так! Мой проект токенизирует строку. Например, когда моя строка находится там, мой проект определит, что строка внутри круглой скобки будет КОМАНДОЙ, строка внутри двойной квадратной скобки будет LINK, а другая будет TEXT. Итак, когда я распечатаю, это будет: Команда: (a b c) Текст: d e f Ссылка: [[g h i]]

Gavin Le 29.09.2018 05:24

Значит, строки всегда имеют форму (COMMAND) TEXT [[LINK]]? Могут ли скобки существовать где угодно, кроме как разделителей? То есть будет ли this [ is a bracket допустимой строкой TEXT?

Jim Mischel 29.09.2018 07:11

@JimMischel Это будет любая форма. Но концепция останется прежней. КОМАНДА всегда начинается с '(и заканчивается') ', так же, как LINK, все, что находится вне скобок, является ТЕКСТОМ. Но это займет только первую скобку. Например, если найдено '(' после, '[', пропустит эту пару (), перейдите к следующему ']'.

Gavin Le 29.09.2018 16:37

Я предлагаю вам записать формальное определение ваших правил, прежде чем вы попытаетесь написать код, который будет анализировать ваши строки. То, что вы предоставили до сих пор, и ваша попытка кодирования показывают, что вы не полностью понимаете проблему, которую пытаетесь решить.

Jim Mischel 29.09.2018 20:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
375
1

Ответы 1

Это возможное решение со стеком для синтаксического анализа и выдачи ошибки parsing_error, если в открывающих скобках отсутствуют закрывающие скобки или закрывающая скобка не соответствует открывающей.

#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;
}

Это хорошее усилие, однако, когда ответы публикуются, лучше немного узнать, как работает решение (краткое изложение алгоритма, ссылки для дальнейшего чтения и т. д.), Чем просто опубликовать код.

PaulMcKenzie 26.09.2018 22:40

Другие вопросы по теме