我想按特定字符分割字符串,而不忽略它们。
例如,如果我有字符串:
"some_tag = some_value"
我可以使用这个区域设置(从cppreference复制/改编)将其拆分为token:
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
这似乎是您可能想要处理的情况,尽管这非常依赖于您想要解析的内容。
Update:我的上一个示例没有考虑到您想要处理的其他情况。我已经测试了它们,它们似乎可以在这个例子中工作:
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 '='
}