【问题标题】:Using multiple delimiters in while loop for fstream c++在fstream c ++的while循环中使用多个分隔符
【发布时间】:2014-12-18 06:02:09
【问题描述】:

我正在尝试使用ifstream. 读取.dat 文件当我读取问题时,我的问题是我需要设置2 个分隔符。 第一个是',' 第二个是'\n'

我的文件格式是这样的, 第 1 项,第 2 项,第 3 项 第 4 项,第 5 项,第 6 项

我的问题是用我现在的方式添加“\n”。 我目前正在像这样在我的while循环中添加','作为分隔符

 while (std::getline(infile, line, ','))

但是得到'\n'让我很生气。所以在while循环中我尝试了这样的东西,

    std::getline(infile, inp.item.group, ',' );
    std::getline(infile, inp.item.total_pay, ',' );
    std::getline(infile, inp.item.quantity, '\n' );

但显然我不明白如何访问我的每一项并给他们自己的分隔符。

我是否应该无法像使用新行作为分隔符那样读取整行,然后像在 while 循环中尝试那样将所有内容拆分?

我的相关代码如下,

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>

struct Input
{
    friend std::istream& operator >>(std::istream& inp, Input& item);
    friend std::ostream& operator <<(std::ostream& outp, Input const& item);

    std::string group;
    std::string total_pay;
    float quantity;

    // default constructor. sets up zero-elements
    Input() : group(), total_pay(), quantity()
    {
    }

    Input(std::string groupIn, std::string total_payIn, float quantityIn) :
    group(std::move(groupIn)),
    total_pay(total_payIn),
    quantity(quantityIn)
    {
    }

    // Accessors
    std::string const& getGroup() const { return group; }
    std::string getTotalPay() const { return total_pay; }
    float getQuantity() const { return quantity; }
};

// global free function for extracting an Input item from an input stream
std::istream& operator >>(std::istream& inp, Input& item)
{
    return (inp >> item.group >> item.total_pay >> item.quantity);
}

// global operator for inserting to a stream
std::ostream& operator <<(std::ostream& outp, Input const& item)
{
    outp
    << item.getGroup() << ", "
    << item.getTotalPay() << ", "
    << item.getQuantity();
    return outp;
}

struct ctype : std::ctype<char>
{
    static mask* make_table()
    {
        static std::vector<mask> table(classic_table(),
                                       classic_table() + table_size);
        table[','] |= space;
        return &table[0];
    }

    ctype() : std::ctype<char>(make_table()) { }
};

int main() {

    std::ifstream infile("employee.dat");

    // one line per item enforced.
    std::vector<Input> data;
    std::string line;

    while (std::getline(infile, line))
    {

        std::istringstream iss(line);
        Input inp;
        infile.imbue(std::locale(iss.getloc(), new ctype));
        std::vector<Input> data((std::istream_iterator<Input>(std::cin)), {});

        if (iss >> inp) // calls our extraction operator >>
            data.push_back(inp);
        else
            std::cerr << "Invalid input line: " << line << '\n';
    }

    // dump all of them to stdout. calls our insertion operator <<
    std::copy(data.begin(), data.end(),
              std::ostream_iterator<Input>(std::cout,"\n"));

    return 0;
}

【问题讨论】:

  • 快速修复。使用带有第一个分隔符的 getline。然后在生成的字符串(使用 stringstream)上再次获取第二个分隔符。
  • 感谢快速修复。但我真的很想了解我在哪里搞砸了,所以我了解未来。我的思维过程不合逻辑吗?

标签: c++


【解决方案1】:

您可以使用自定义std::ctype 构面设置分隔符。然后你的格式化提取器会处理剩下的事情:

struct ctype : std::ctype<char>
{
    static mask* make_table()
    {
        static std::vector<mask> table(classic_table(),
                                       classic_table() + table_size);
        table[','] |= space;
        return &table[0];
    }

    ctype() : std::ctype<char>(make_table()) { }
};

// ...
int main()
{
    // ...
    infile.imbue(std::locale(iss.getloc(), new ctype));
    std::vector<Input> data((std::istream_iterator<Input>(std::cin)), {});
}

【讨论】:

  • 所以你说通过使用自定义 std::ctype 方面,如你所展示的,它将 , 作为一个空格,然后恢复为默认分隔符 '\n' 并且只需添加即可正常工作你提供的新结构?
  • @NDiaz 格式提取器使用空格作为分隔符。默认情况下,换行符 ('\n') 和空格被流的默认 std::ctype 分面归类为空白。此代码修改了 facet,因此,除了换行符之外,它还将逗号 , 归类为空格。因此,流找到, 的任何地方都会将其视为空白字符。 imbue() 调用是将构面安装到流的语言环境中,因此流上从该点开始的任何地方都将逗号分类为附加空格。
  • 您可以从所有空格分类字符中删除标志space,并将其设置为“,”和“\n”。一个问题将持续存在:每行中的每个数据集是否包含预期数量的元素?
  • @DieterLücking 预期的元素数量与原始问题有什么关系?此外,此示例旨在添加一个额外的空白字符。其他角色的分类,我不打算带走。
  • 是的,它们具有所有预期值。我一辈子都无法让它发挥作用。 gr。当我实现您的示例时,每个条目都会引发无效行错误。我用所有代码和添加示例的方式更新了我的问题。
猜你喜欢
  • 2011-08-09
  • 2021-12-15
  • 1970-01-01
  • 2010-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多