更改cin的分隔符(c++)

changing the delimiter for cin (c++)

本文关键字:c++ 分隔符 cin 更改      更新时间:2023-10-16

我已经重定向"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) {}
};

干杯!