为什么从 std::istream 读取记录结构字段失败,我该如何解决? [英] Why does reading a record struct fields from std::istream fail, and how can I fix it?

查看:46
本文介绍了为什么从 std::istream 读取记录结构字段失败,我该如何解决?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有以下情况:

  • 一个记录结构体声明如下

  • A record struct is declared as follows

struct Person {
    unsigned int id;
    std::string name;
    uint8_t age;
    // ...
};

  • 记录使用以下格式存储在文件中:

  • Records are stored in a file using the following format:

    ID      Forename Lastname Age
    ------------------------------
    1267867 John     Smith    32
    67545   Jane     Doe      36
    8677453 Gwyneth  Miller   56
    75543   J. Ross  Unusual  23
    ...
    

  • 应该读入文件以收集任意数量的上述Person记录:

    The file should be read in to collect an arbitrary number of the Person records mentioned above:

    std::istream& ifs = std::ifstream("SampleInput.txt");
    std::vector<Person> persons;
    
    Person actRecord;
    while(ifs >> actRecord.id >> actRecord.name >> actRecord.age) {
        persons.push_back(actRecord);
    }
    
    if(!ifs) {
        std::err << "Input format error!" << std::endl;
    } 
    

    问题:
    我该怎么做才能读入将它们的值存储到一个 actRecord 变量字段中的单独值?

    Question:
    What can I do to read in the separate values storing their values into the one actRecord variables' fields?

    上面的代码示例以运行时错误告终:

    The above code sample ends up with run time errors:

    Runtime error    time: 0 memory: 3476 signal:-1
    stderr: Input format error!
    

    推荐答案

    这是我想出的一个操纵器的实现,它通过每个提取的字符计算分隔符.使用您指定的分隔符数量,它将从输入流中提取单词.这是一个工作演示.

    Here's an implementation of a manipulator I came up with that counts the delimiter through each extracted character. Using the number of delimiters you specify, it will extract words from the input stream. Here's a working demo.

    template<class charT>
    struct word_inserter_impl {
        word_inserter_impl(std::size_t words, std::basic_string<charT>& str, charT delim)
            : str_(str)
            , delim_(delim)
            , words_(words)
        { }
    
        friend std::basic_istream<charT>&
        operator>>(std::basic_istream<charT>& is, const word_inserter_impl<charT>& wi) {
            typename std::basic_istream<charT>::sentry ok(is);
    
            if (ok) {
                std::istreambuf_iterator<charT> it(is), end;
                std::back_insert_iterator<std::string> dest(wi.str_);
    
                while (it != end && wi.words_) {
                    if (*it == wi.delim_ && --wi.words_ == 0) {
                        break;
                    }
                    dest++ = *it++;
                }
            }
            return is;
        }
    private:
        std::basic_string<charT>& str_;
        charT delim_;
        mutable std::size_t words_;
    };
    
    template<class charT=char>
    word_inserter_impl<charT> word_inserter(std::size_t words, std::basic_string<charT>& str, charT delim = charT(' ')) {
        return word_inserter_impl<charT>(words, str, delim);
    }
    

    现在你可以这样做:

    while (ifs >> actRecord.id >> word_inserter(2, actRecord.name) >> actRecord.age) {
        std::cout << actRecord.id << " " << actRecord.name << " " << actRecord.age << '
    ';
    }
    

    现场演示

    这篇关于为什么从 std::istream 读取记录结构字段失败,我该如何解决?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆