重载运算符>>()用于未知的输入长度/结构

问题描述 投票:0回答:1

我正在尝试读取包含个人信息的文件。每行包含一个人的数据,可以这样说:

First(s) Last ID SSN
Peter Barker 1234 5678
James Herbert Bond 007 999
Barack Hussein Obama 2007 14165

所以我想使用std::copy读取每一行并将其复制到(std::vector<Person>)中,如下所示:

struct Person
{
    std::string firstName_s;
    std::string lastName;
    int ID;
    int SSD;
}

我认为为此重载提取运算符会很方便:

std::istringstream& operator>>(std::istringstream& in, struct Person& person)
{
    struct Person tmp;
    in  >> tmp.firstName_s 
        >> tmp.lastName 
        >> tmp.ID 
        >> tmp.SSN;
    person = std::move(tmp);
    return in;
}

但是,我遇到的问题是我不知道该人将拥有多少个名字

我曾想过将全名读成一个字符串,直到遇到一个数字,然后他们将姓氏从包含名字的字符串中分离出来,这很好用,但看起来很丑。如果有人有更好的建议,或者我可以看的链接,但我似乎自己找不到东西,那将是很棒的!谢谢。

c++ istream c++20
1个回答
0
投票

[如果您有可变长的行(就字数而言),您可以简单地读取整行并从右侧进行处理,或者缓存所有字并使用偏移量。下面的示例执行后一个。

int to_int(std::string_view str)
{
    int val = 0;
    std::from_chars(str.data(), str.data() + str.size(), val);
    return val;
}

std::istream& operator>>(std::istream& in, Person& person)
{
    std::string line;
    std::vector<std::string_view> words;

    // read whole line
    if (std::getline(in, line))
    {
        // split line into words
        std::string_view text = line;
        for (auto pos = text.find_first_of(' '); pos != std::string_view::npos; pos = text.find_first_of(' '))
        {
            words.push_back(text.substr(0, pos));
            text.remove_prefix(pos + 1);
        }
        words.push_back(text);

        // join first names
        std::stringstream ss;
        for (std::size_t i = 0; i < words.size() - 3; i++)
            ss << ' ' << words[i];

        person.firstName_s = ss.str().substr(1);
        person.lastName = words[words.size() - 3];
        person.ID = to_int(words[words.size() - 2]);
        person.SSN = to_int(words[words.size() - 1]);
    }

    return in;
}

我认为代码是不言自明的。 Here是一个完整的示例。

© www.soinside.com 2019 - 2024. All rights reserved.