更改cin的分隔符(c++)
changing the delimiter for cin (c++)
我已经重定向"cin"从文件流cin.rdbug(inF.rdbug())
读取当我使用提取操作符时,它会一直读取,直到到达空白字符。
是否可以使用其他分隔符?我浏览了cplusplus.com的api,但没有找到任何东西。
可以更改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";
}
}
对于字符串,您可以使用std::getline
重载来使用不同的分隔符进行读取。
对于数字提取,分隔符不是真正的"空白"开始,而是数字中无效的任何字符。
这是对Rob的答案的改进,因为这是正确的答案(我很失望它没有被接受)
您需要做的是更改ctype
查看的数组,以确定分隔符是什么。
在最简单的情况下,你可以创建自己的:
const ctype<char>::mask foo[ctype<char>::table_size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ctype_base::space};
在我的机器上'n'
是10。我将数组的该元素设置为分隔符值:ctype_base::space
。用foo
初始化的ctype
只能在'n'
上定界,而不能在' '
或't'
上定界。
现在这是一个问题,因为传入ctype
的数组不仅定义了分隔符是什么,它还定义了字母、数字、符号和流所需的其他一些垃圾。(本•沃伊特的回答触及到了这一点。)所以我们真正想做的是修改一个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;
用bar
初始化的ctype
可以分隔'n'
和':'
,但不能分隔' '
和't'
。
你去设置cin
,或任何其他istream
,使用自定义的ctype
,像这样:
cin.imbue(locale(cin.getloc(), new ctype<char>(data(bar))));
您也可以在ctype
s之间切换,并且行为将在中途改变:
cin.imbue(locale(cin.getloc(), new ctype<char>(foo)));
如果您需要恢复默认行为,只需这样做:
cin.imbue(locale(cin.getloc(), new ctype<char>));
<<p> 生活例子/kbd> 这是对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) {}
};
干杯!
- 当用户键入分隔符时,停止getline()输入
- 为什么在逗号分隔符上下文中将预增量的结果强制转换为void
- 如何在 c++ 中使用 ',' 作为 getline 分隔符
- 带有多个字符分隔符的正则表达式
- 使用 char 分隔符解析C++中的字符串,但将可重复的字符保留为每个解析的子字符串 (C++ STL) 中的分隔符
- 字符串开头的分隔符
- 尝试将 c 字符串数组与分隔符连接起来
- 正则表达式以匹配数字的重复模式,后跟任何类型的分隔符?
- 根据新的行分隔符从字符串中删除子字符串
- 同一分隔符之间的多个子字符串
- 通过分隔符分隔包含 UTF-16 BE 文本的uint8_t数组
- 字符串流分隔符
- 如何在 std::getline 中自定义分隔符
- getline() 上的分隔符无法正常工作
- 示例代码中使用分隔符将 std::string 拆分为 std::vector 的范围问题
- C++使用分隔符读取文件
- 使用连续分隔符和空最后一个字符进行拆分
- 到达分隔符时跳到文本文件的下一行
- 使用空格分隔符从文本文件将对象读入数组
- 使用正则表达式c++从单词和分隔符之间的字符串中提取所有子字符串