std :: locale для разделения строки по определенному символу без его игнорирования

0

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

Например, если у меня есть строка:

"some_tag = some_value"

Я могу использовать этот язык (скопированный/адаптированный из cppreference), чтобы разбить его на токены:

struct split_by_equal : std::ctype<char>
{
    static const mask* make_table()
    {
        static std::vector<mask> v(classic_table(), classic_table() + table_size);
        v['='] |=  space;
        return &v[0];
    }

    split_by_equal() : ctype(make_table()){}
};

...

std::stringstream stream("some_tag = some_value");
stream.imbue(std::locale(std::locale::classic(), new split_by_equal));

std::string token;
while(stream>>token)
{
    std::cout<<token<<std::endl;
}

Это работает, за исключением того, что я не могу знать, был ли "=" один раз, несколько раз или он отсутствовал. Знать эту информацию очень важно для проверки входной строки.

Можно ли остановить синтаксический анализ символа без его извлечения из потока?

PS: Я хочу использовать std :: locale, потому что реальная проблема не так проста, как разделение строки, используя только '=' в качестве разделителя :)

РЕДАКТИРОВАТЬ:

Я хотел бы иметь возможность анализировать так же, как строки:

"some_tag=some_value"
"some_tag
=
some_value"
"some_tag = some_value"

и иметь возможность сообщать об ошибке для следующих:

"some_tag some_value"
"some_tag == some_value"
Теги:
string
c++11
stream

2 ответа

0

Вы должны использовать std::getline с пользовательским аргументом разделителя, за которым следует вызов (или больше) с по умолчанию '\n'. Если вы не разделяете с нами полную проблему, это все еще самое простое и эффективное решение.

Затем вы можете проверить любой случай, который хотите обработать. Будет сложно справиться с чем-то вроде этого:

some_tag
=
some_tag = some_value

Это похоже на случай, который вы, возможно, захотите обработать, хотя это очень зависит от того, что вы хотите проанализировать.

0

Обновление. В моем последнем примере не учитывались другие случаи, которые вы хотели обработать. Я тестировал их все, и они, похоже, работают с этим примером:

template<char c>
std::istream& strip_until(std::istream& is)
{
    auto& ctype = std::use_facet<std::ctype<char>>(is.getloc());
    int val = std::char_traits<char>::to_int_type(c);
    bool b;

    while ((b = ctype.is(ctype.space, is.peek())) && is.peek() != val)
        is.ignore();

    if (!b && is.peek() != val)
        is.setstate(std::ios_base::failbit);

    return is;
}

...

while (stream >> token >> strip_until<'='>)
{
    // stream.peek() is '='
}
  • 0
    У меня проблема с "some_tag = some_value". Это будет читаться как одна строка без фасета.
  • 0
    @Felics Дайте мне знать, если мое обновление поможет, пожалуйста.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню