Я хочу разбить строку на определенные символы, не игнорируя их.
Например, если у меня есть строка:
"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"
Вы должны использовать std::getline
с пользовательским аргументом разделителя, за которым следует вызов (или больше) с по умолчанию '\n'
. Если вы не разделяете с нами полную проблему, это все еще самое простое и эффективное решение.
Затем вы можете проверить любой случай, который хотите обработать. Будет сложно справиться с чем-то вроде этого:
some_tag
=
some_tag = some_value
Это похоже на случай, который вы, возможно, захотите обработать, хотя это очень зависит от того, что вы хотите проанализировать.
Обновление. В моем последнем примере не учитывались другие случаи, которые вы хотели обработать. Я тестировал их все, и они, похоже, работают с этим примером:
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 '='
}