如何将 C++ 输入流定界符包含到结果标记中
how to include C++ input stream delimiters into result tokens
C++ 标准库支持几种为输入流引入自定义定界符的方法,据我所知,推荐的方法是使用新的语言环境和 ctype 对象:
第一种方式(继承自 ctype 特化):
struct csv_whitespace : std::ctype<char>
{
bool do_is(mask m, char_type c) const
{
if ((m & space) && c == ' ') {
return false; // space will NOT be classified as whitespace
}
if ((m & space) && c == ',') {
return true; // comma will be classified as whitespace
}
return ctype::do_is(m, c); // leave the rest to the parent class
}
};
// for cin stream :
cin.imbue(std::locale(cin.getloc(), new csv_whitespace));
第二种方式(参数化 ctype 专业化):
// getting existing table for ctype<char> specialization
const auto temp = std::ctype<char>::classic_table();
// create a copy of the table in vector container
std::vector<std::ctype<char>::mask> new_table_vector(temp, temp + std::ctype<char>::table_size);
// add/remove stream separators using bitwise arithmetic.
// use char-based indices because ascii codes here are equal to indices
new_table_vector[' '] ^= ctype_base::space;
new_table_vector['\t'] &= ~(ctype_base::space | ctype_base::cntrl);
new_table_vector[':'] |= ctype_base::space;
// A ctype initialized with new_table_vector would delimit on '\n' and ':' but not ' ' or '\t'.
// ....
// usage of the mask above.
cin.imbue(locale(cin.getloc(), new std::ctype<char>(new_table_vector.data())));
但是有没有办法在结果标记中包含分隔符?例如
aaa&bbb*ccc%ddd&eee
哪里
& * %
是使用上述方法之一定义的分隔符。
结果字符串将是:
aaa
&bbb
*ccc
%ddd
&eee
所以你看 - 分隔符包含在结果字符串中。
这是一个问题 - 如何配置(这可能吗?)输入流?
谢谢
简短的回答是不,istream
不提供提取和保留分隔符的固有方法。 istream
s提供以下提取方法:
operator>>
- 丢弃定界符
get
- 根本不提取 a 分隔符
getline
- 丢弃 a 分隔符
read
- 不考虑分隔符
readsome
- 不考虑分隔符
但是,假设您将 istream
吞入 string foo
,那么您可以使用这样的正则表达式来标记:
((?:^|[&*%])[^&*%]*)
这可以像这样与 regex_token_iterator
一起使用:
const regex re{ "((?:^|[&*%])[^&*%]*)" };
const vector<string> bar{ sregex_token_iterator(cbegin(foo), cend(foo), re, 1), sregex_token_iterator() };
C++ 标准库支持几种为输入流引入自定义定界符的方法,据我所知,推荐的方法是使用新的语言环境和 ctype 对象:
第一种方式(继承自 ctype 特化):
struct csv_whitespace : std::ctype<char>
{
bool do_is(mask m, char_type c) const
{
if ((m & space) && c == ' ') {
return false; // space will NOT be classified as whitespace
}
if ((m & space) && c == ',') {
return true; // comma will be classified as whitespace
}
return ctype::do_is(m, c); // leave the rest to the parent class
}
};
// for cin stream :
cin.imbue(std::locale(cin.getloc(), new csv_whitespace));
第二种方式(参数化 ctype 专业化):
// getting existing table for ctype<char> specialization
const auto temp = std::ctype<char>::classic_table();
// create a copy of the table in vector container
std::vector<std::ctype<char>::mask> new_table_vector(temp, temp + std::ctype<char>::table_size);
// add/remove stream separators using bitwise arithmetic.
// use char-based indices because ascii codes here are equal to indices
new_table_vector[' '] ^= ctype_base::space;
new_table_vector['\t'] &= ~(ctype_base::space | ctype_base::cntrl);
new_table_vector[':'] |= ctype_base::space;
// A ctype initialized with new_table_vector would delimit on '\n' and ':' but not ' ' or '\t'.
// ....
// usage of the mask above.
cin.imbue(locale(cin.getloc(), new std::ctype<char>(new_table_vector.data())));
但是有没有办法在结果标记中包含分隔符?例如
aaa&bbb*ccc%ddd&eee
哪里
& * %
是使用上述方法之一定义的分隔符。 结果字符串将是:
aaa
&bbb
*ccc
%ddd
&eee
所以你看 - 分隔符包含在结果字符串中。 这是一个问题 - 如何配置(这可能吗?)输入流?
谢谢
简短的回答是不,istream
不提供提取和保留分隔符的固有方法。 istream
s提供以下提取方法:
operator>>
- 丢弃定界符get
- 根本不提取 a 分隔符getline
- 丢弃 a 分隔符read
- 不考虑分隔符readsome
- 不考虑分隔符
但是,假设您将 istream
吞入 string foo
,那么您可以使用这样的正则表达式来标记:
((?:^|[&*%])[^&*%]*)
这可以像这样与 regex_token_iterator
一起使用:
const regex re{ "((?:^|[&*%])[^&*%]*)" };
const vector<string> bar{ sregex_token_iterator(cbegin(foo), cend(foo), re, 1), sregex_token_iterator() };