Есть ли способ разбить строку на небольшую часть и сохранить в векторе.
Например:
Строка: 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::stack
и знать, когда можно использовать topush
и pop
, и тогда нет необходимости в strtok. Ваша попытка синтаксического анализа методом «грубой силы» - наивный подход.
@PaulMcKenzie К счастью, OP вообще не использует strtok()
в своем коде, или я что-то пропустил?
@ πάνταῥεῖ ОП упомянул strtok
в своем сообщении.
Непонятно, что вы хотите делать с вложенными скобками. Например, что будет в результате (a b c) (d [e f] g)
?
@JimMischel именно так! Мой проект токенизирует строку. Например, когда моя строка находится там, мой проект определит, что строка внутри круглой скобки будет КОМАНДОЙ, строка внутри двойной квадратной скобки будет LINK, а другая будет TEXT. Итак, когда я распечатаю, это будет: Команда: (a b c) Текст: d e f Ссылка: [[g h i]]
Значит, строки всегда имеют форму (COMMAND) TEXT [[LINK]]
? Могут ли скобки существовать где угодно, кроме как разделителей? То есть будет ли this [ is a bracket
допустимой строкой TEXT
?
@JimMischel Это будет любая форма. Но концепция останется прежней. КОМАНДА всегда начинается с '(и заканчивается') ', так же, как LINK, все, что находится вне скобок, является ТЕКСТОМ. Но это займет только первую скобку. Например, если найдено '(' после, '[', пропустит эту пару (), перейдите к следующему ']'.
Я предлагаю вам записать формальное определение ваших правил, прежде чем вы попытаетесь написать код, который будет анализировать ваши строки. То, что вы предоставили до сих пор, и ваша попытка кодирования показывают, что вы не полностью понимаете проблему, которую пытаетесь решить.
Это возможное решение со стеком для синтаксического анализа и выдачи ошибки 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;
}
Это хорошее усилие, однако, когда ответы публикуются, лучше немного узнать, как работает решение (краткое изложение алгоритма, ссылки для дальнейшего чтения и т. д.), Чем просто опубликовать код.
А как насчет простого использования
std::regex
?