Как извлечь токены из строки? - PullRequest
2 голосов
/ 06 августа 2020

Изменить: Может ли кто-нибудь добавить решение для регулярных выражений? Я искал следующее регулярное выражение:

[\(\)!*-+^]

У меня была функция, которая извлекает токены из текста в соответствии со специальными символами, которые я объявил в его теле.

Есть 2 проблемы в функции:

1) Он не печатает специальные символы.

2) Выводится неправильно, когда два специальных символа находятся рядом друг с другом

Итак, я внес изменение, которое устранило проблему 1 (как я видел по результатам некоторых тестов), но не исправляет номер 2, какая-либо помощь?

Примечание : Я использую стандарт C ++ 11 и не хочу использовать ускорение

Пример: Учитывая: a+(b*c) Я ожидаю: a,+,(,b,*,c,)

Учитывая: a+b Я ожидаю: a,+,b

Дано: ab+ Я ожидаю: ab,+

Дано: a b+ Я ожидаю: a b,+

Ответы [ 2 ]

1 голос
/ 06 августа 2020

Вот решение для регулярного выражения, которое должно анализировать нужные вам токены:

void find(std::string str)
{
    static const std::regex r(R"(\+|\^|-|\*|!|\(|\)|([\w|\s]+))");
    std::copy( std::sregex_token_iterator(str.begin(), str.end(), r, 0),
               std::sregex_token_iterator(),
               std::ostream_iterator<std::string>(std::cout, "\n"));
}

Вот демонстрация .

Вот объяснение .

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

0 голосов
/ 06 августа 2020

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

#include <sstream>
#include <string>
#include <vector>
#include <cassert>

using std::string;
using std::stringstream;
using std::vector;

namespace {

// Parse a string into a vector of tokens by special characters.
auto find(string str) -> vector<string> {
    auto result = vector<string>{};
    auto pos = string::size_type{};
    auto last_pos = string::size_type{};

    while ((pos = str.find_first_of("+^-*!()", last_pos)) != string::npos) {
        // Is there a token before the special character?
        if (pos - last_pos > 0) {
            result.push_back(str.substr(last_pos, pos - last_pos));
        }

        last_pos = pos + 1;

        // Add the special character as a token.
        result.push_back(str.substr(pos, 1));
    }

    auto last = str.substr(last_pos);

    // Is there a trailing token after the last found special character?    
    if (!last.empty()) {
        result.push_back(str.substr(last_pos));
    }

    return result;
}

// Helper routine.
// Join a vector of strings together using a given separator.
auto join(vector<string> const& v, string sep) -> string {
    auto ss = stringstream{};
    auto first = true;

    for (auto const& s : v) {
        if (first) {
            ss << s;
            first = false;
        } else {
            ss << sep << s;
        }
    }

    return ss.str();
}

// Helper routine.
// Returns a string representing the tokenized string.
auto check(string s) -> string {
    auto v = find(s);
    auto result = join(v, ",");
    return result;
}

} // anon

int main() {
    // Unit tests to check that the string parses and tokenizes into the expected string.
    assert(check("a+(b*c)") == "a,+,(,b,*,c,)");
    assert(check("a+b") == "a,+,b");
    assert(check("ab+") == "ab,+");
    assert(check("a b+") == "a b,+");
    assert(check("a") == "a");
    assert(check("aa") == "aa");
    assert(check("+") == "+");
    assert(check("++") == "+,+");
    assert(check("a+") == "a,+");
    assert(check("+a") == "+,a");
    assert(check("") == "");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...