yot*_*moo 42 c++ whitespace stream cin delimiter
我已经重定向"cin"来从文件流中读取cin.rdbug(inF.rdbug())
当我使用提取操作符时,它会读取它直到它到达空格字符.
是否可以使用另一个分隔符?我在cplusplus.com上浏览了api,但没有找到任何东西.
Rob*_*obᵩ 42
使用添加自定义可以更改字间分隔符cin
或任何其他分隔符.std::istream
std::ios_base::imbue
ctype
facet
如果您正在以/ etc/passwd样式读取文件,则以下程序将分别读取每个:
分隔的单词.
#include <locale>
#include <iostream>
struct colon_is_space : std::ctype<char> {
colon_is_space() : std::ctype<char>(get_table()) {}
static mask const* get_table()
{
static mask rc[table_size];
rc[':'] = std::ctype_base::space;
rc['\n'] = std::ctype_base::space;
return &rc[0];
}
};
int main() {
using std::string;
using std::cin;
using std::locale;
cin.imbue(locale(cin.getloc(), new colon_is_space));
string word;
while(cin >> word) {
std::cout << word << "\n";
}
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*Mee 15
这是Robᵩ的答案的改进,因为这是正确的(我很失望,它没有被接受.)
您需要做的是更改ctype
查看的数组以确定分隔符是什么.
在最简单的情况下,您可以创建自己的:
const ctype<char>::mask foo[ctype<char>::table_size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ctype_base::space};
Run Code Online (Sandbox Code Playgroud)
在我的机器上'\n'
是10.我已将数组的元素设置为分隔符值:ctype_base::space
.一个ctype
与初始化foo
只会划上'\n'
没有' '
或'\t'
.
现在这是一个问题,因为传入的数组ctype
定义的不仅仅是分隔符,还定义了leters,数字,符号和流式传输所需的其他垃圾.(Ben Voigt的答案触及了这一点.)所以我们真正想做的是修改 a mask
,而不是从头开始创建.
这可以这样完成:
const auto temp = ctype<char>::classic_table();
vector<ctype<char>::mask> bar(temp, temp + ctype<char>::table_size);
bar[' '] ^= ctype_base::space;
bar['\t'] &= ~(ctype_base::space | ctype_base::cntrl);
bar[':'] |= ctype_base::space;
Run Code Online (Sandbox Code Playgroud)
一个ctype
与初始化bar
将划上'\n'
和':'
,但不会' '
还是'\t'
.
您可以像以下一样设置cin
或istream
使用您的自定义ctype
:
cin.imbue(locale(cin.getloc(), new ctype<char>(data(bar))));
Run Code Online (Sandbox Code Playgroud)
你也可以在ctype
s 之间切换,行为将在中途改变:
cin.imbue(locale(cin.getloc(), new ctype<char>(foo)));
Run Code Online (Sandbox Code Playgroud)
如果您需要返回默认行为,请执行以下操作:
cin.imbue(locale(cin.getloc(), new ctype<char>));
Run Code Online (Sandbox Code Playgroud)
这是对 Jon 的答案以及cppreference.com的示例的改进。因此,这遵循与两者相同的前提,但将它们与参数化分隔符结合起来。
struct delimiter_ctype : std::ctype<char> {
static const mask* make_table(std::string delims)
{
// make a copy of the "C" locale table
static std::vector<mask> v(classic_table(), classic_table() + table_size);
for(mask m : v){
m &= ~space;
}
for(char d : delims){
v[d] |= space;
}
return &v[0];
}
delimiter_ctype(std::string delims, ::size_t refs = 0) : ctype(make_table(delims), false, refs) {}
};
Run Code Online (Sandbox Code Playgroud)
干杯!