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

发布于 2024-12-02 22:53:23 字数 142 浏览 6 评论 0 原文

我已重定向“cin”以从文件流中读取cin.rdbug(inF.rdbug()) 当我使用提取运算符时,它会读取直到到达空白字符。

是否可以使用其他分隔符?我浏览了 cplusplus.com 中的 api,但没有找到任何东西。

I've redirected "cin" to read from a file stream cin.rdbug(inF.rdbug())
When I use the extraction operator it reads until it reaches a white space character.

Is it possible to use another delimiter? I went through the api in cplusplus.com, but didn't find anything.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

攒眉千度 2024-12-09 22:53:23

可以更改 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";
  }
}

It is possible to change the inter-word delimiter for cin or any other std::istream, using std::ios_base::imbue to add a custom ctype facet.

If you are reading a file in the style of /etc/passwd, the following program will read each :-delimited word separately.

#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";
  }
}
三五鸿雁 2024-12-09 22:53:23

对于字符串,您可以使用 std::getline 重载来使用不同的分隔符读取。

对于数字提取,分隔符实际上并不是“空格”,而是数字中的任何无效字符。

For strings, you can use the std::getline overloads to read using a different delimiter.

For number extraction, the delimiter isn't really "whitespace" to begin with, but any character invalid in a number.

苍景流年 2024-12-09 22:53:23

这是对 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 的数组不仅定义了分隔符,还定义了字母、数字、符号和流式处理所需的其他一些垃圾。 (Ben Voigt 的回答涉及到这一点。)所以我们真正想做的是修改< /em> 一个掩码,而不是从头开始创建一个。

可以这样完成:

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 之间切换 ,行为将在中途改变:

cin.imbue(locale(cin.getloc(), new ctype<char>(foo)));

如果您需要返回默认行为,只需执行以下操作:

cin.imbue(locale(cin.getloc(), new ctype<char>));

直播示例

This is an improvement on Robᵩ's answer, because that is the right one (and I'm disappointed that it hasn't been accepted.)

What you need to do is change the array that ctype looks at to decide what a delimiter is.

In the simplest case you could create your own:

const ctype<char>::mask foo[ctype<char>::table_size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ctype_base::space};

On my machine '\n' is 10. I've set that element of the array to the delimiter value: ctype_base::space. A ctype initialized with foo would only delimit on '\n' not ' ' or '\t'.

Now this is a problem because the array passed into ctype defines more than just what a delimiter is, it also defines leters, numbers, symbols, and some other junk needed for streaming. (Ben Voigt's answer touches on this.) So what we really want to do is modify a mask, not create one from scratch.

That can be accomplished like this:

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;

A ctype initialized with bar would delimit on '\n' and ':' but not ' ' or '\t'.

You go about setting up cin, or any other istream, to use your custom ctype like this:

cin.imbue(locale(cin.getloc(), new ctype<char>(data(bar))));

You can also switch between ctypes and the behavior will change mid-stream:

cin.imbue(locale(cin.getloc(), new ctype<char>(foo)));

If you need to go back to default behavior, just do this:

cin.imbue(locale(cin.getloc(), new ctype<char>));

Live example

落墨 2024-12-09 22:53:23

这是对 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) {}
};

干杯!

This is an improvement on Jon's answer, and the example from cppreference.com. So this follows the same premise as both, but combines them with parameterized delimiters.

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) {}
};

Cheers!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文