虽然不是先验明显,但有一种相对简单的方法可以更改流认为是空白的内容。做到这一点的方法是imbue() 带有std::locale 对象的流,其std::ctype<char> facet 被替换以将所需的字符视为空格。 imbue()、locale、ctype - 嗯?!?好的,好吧,这些不一定是您日常使用的东西,所以这里有一个简单的示例,它设置 std::cin 以使用逗号和换行符作为间隔:
#include <locale>
template <char S0, char S1>
struct commactype_base {
commactype_base(): table_() {
this->table_[static_cast<unsigned char>(S0)] = std::ctype_base::space;
this->table_[static_cast<unsigned char>(S1)] = std::ctype_base::space;
}
std::ctype<char>::mask table_[std::ctype<char>::table_size];
};
template <char S0, char S1 = S0>
struct ctype:
commactype_base<S0, S1>,
std::ctype<char>
{
ctype(): std::ctype<char>(this->table_, false) {}
};
实际上,std::ctype<char> 的这个特定实现实际上可以用来使用一个或两个任意的chars 作为空格(适当的 C++2011 版本可能允许任意数量的参数;另外,不要t 真的必须是模板参数)。无论如何,有了这个,只需在 main() 函数的开头添加以下行即可:
std::cin.imbue(std::locale(std::locale(), new ::ctype<',', '\n'>));
请注意,这实际上只将, 和\n 视为空格字符。这也意味着没有其他字符作为空格被跳过。 ...当然,多个逗号字符的序列被认为只是一个分隔符,而不是可能创建一堆空字符串。另请注意,上面的std::ctype<char> facet 删除了所有其他字符分类。如果您想解析字符串以外的其他对象,您可能希望保留其他字符分类并仅更改空格。这是一种可以做到的方法:
template <char S0, char S1>
struct commactype_base {
commactype_base(): table_() {
std::transform(std::ctype<char>::classic_table(),
std::ctype<char>::classic_table() + std::ctype<char>::table_size,
this->table_,
[](std::ctype_base::mask m) -> std::ctype_base::mask {
return m & ~(std::ctype_base::space);
});
this->table_[static_cast<unsigned char>(S0)] |= std::ctype_base::space;
this->table_[static_cast<unsigned char>(S1)] |= std::ctype_base::space;
}
std::ctype<char>::mask table_[std::ctype<char>::table_size];
};
遗憾的是,这与我系统上的 gcc 版本崩溃(显然 std::ctype<char>::classic_table() 产生一个空指针。用当前版本的 clang 编译它不起作用,因为 clang 不支持 lambda。使用两个警告上面的代码应该是正确的,虽然......