簡體   English   中英

從 cpp 中的文件中讀取對象

[英]Read in objects from file in cpp

我有一個人 class 和一個寵物 class。 人有名字和年齡。 寵物有動物和它的顏色

人 class 持有一個寵物向量

我正在嘗試從文件中讀取數據以填充人物對象的向量(每個對象都有自己的寵物向量)

文件結構如下:

sally 32
cat brown
-1

tom 49
dog white
dog brown
-1

sue 54
lizard green
-1

emily 18
cat white
cat brown
cat black
-1

-1 是條目完成的“標志”

我不知道如何解釋每個人的寵物數量的變化,更不用說如何在 -1 處停止

這是我到目前為止的代碼:(適用於線性/沒有寵物數量變化的數據文件)

void fillArray(vector<Person> &people){
    ifstream peopleFile("people.dat");
    string name;
    int age;
    string animal;
    string colour;

    while(!peopleFile.eof()){
        peopleFile>>name>>age;
        peopleFile>>animal>>colour;
        Person p(name,age);
        Pet pet(animal,colour);
        p.addPet(pet);
        people.push_back(p);
        ..
    }
}

它沒有那么復雜。 我們會把大問題分解成小問題,然后逐個解決。

我們將使用 iostream 提取器運算符從 stream 中獲取所有數據。 對於寵物 class,我們將首先閱讀完整的行,包括動物和顏色。 為此,我們將使用最常用的std::getline

我們總是先閱讀完整的行,以避免行尾出現問題。 然后我們將剛剛讀取的行填充到std::istringstream中。 這也是一個 stream,這樣,我們可以像從任何其他 stream 一樣從字符串中讀取。

從 stream 我們簡單地提取名稱和年齡。 沒那么復雜。

讀一個人有點復雜。 文件中的新條目可以以空行開頭。 所以我們將首先讀取空行並丟棄它們。

然后,我們再次將該行放入std::istringstream ,然后提取名稱和年齡。 簡單的。

接下來,可能有一個或多個寵物。 分隔符是包含 -1 的行。 因此,我們在 while 循環中讀取行,直到該行為 -1。 在 -1 的情況下,我們不會執行循環體。

如果它不是 -1,而是有效數據,我們再次將該行放入std::istringstream並從該 stream 中提取一個 Pet。 Pet pTemp; iss2 >> pTemp; Pet pTemp; iss2 >> pTemp; 將致電寵物提取器操作員。 然后我們將新寵物添加到我們內部的std::vector中。

基本上就是這樣。

主要是,我們打開文件並檢查它是否有效。

然后我們定義一個向量類型的變量(persons)並使用它的范圍構造函數來初始化它。 作為范圍構造函數的迭代器,我們將為 Person class 使用std::istream_iterator 這將簡單地調用 Person 提取器,直到讀取所有數據。 因此,我們將在最后使用一行來讀取所有數據。

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

struct Pet {
    std::string animal{};
    std::string color{};
};

// Define Extractor for a pet
std::istream& operator >> (std::istream& is, Pet& p) {

    // Read a line containing the animal name and the color
    if (std::string line{}; std::getline(is, line)) {

        // Now put line in istringstream, so that we can use iostream operations to extract data
        std::istringstream iss{ line };

        // Extract info for one pet
        iss >> p.animal >> p.color;
    }
    return is;
}

// Define Inserter for a pet for easier output
std::ostream& operator << (std::ostream & os, const Pet & p) {
    return os << "Pet:   \t" << p.animal << "\t\tAnimal: \t " << p.color << '\n';
}


struct Person {
    std::string name{};
    unsigned int age;
    std::vector<Pet> pets;
};

// Define a extractor for a person
std::istream& operator >> (std::istream& is, Person& p) {
    std::string line{};
    // Read empty strings and discard them
    while (std::getline(is, line) && line == "")
        ; 
    if (is) {
        // Read a line containing the name and the age
        // Now put line in istringstream, so that we can use iostream operations to extract data
        std::istringstream iss{ line };

        // Extract name and age
        iss >> p.name >> p.age;
        p.pets.clear();

        // Next, we want to read all pets, line by line, until we find -1
        while (std::getline(is, line) && line != "-1") {

            // Now put line in istringstream, so that we can use iostream operations to extract data
            std::istringstream iss2{ line };

            // Extract pet from this line. Call overwritten Extractor from Pet
            Pet pTemp; iss2 >> pTemp;

            // Add new pet to vector
            p.pets.push_back(std::move(pTemp));
        }
    }
    return is;
}

// Define Inserter for a person for easier output
std::ostream& operator << (std::ostream& os, const Person& p) {
    os << "\n\nName:\t" << p.name << "\t\tAge: \t" << p.age <<'\n';
    for (const Pet& pet : p.pets) os << pet;
    return os;
}

int main() {
    // Open file and check, if it could be opened
    if (std::ifstream datFileStream{ "r:\\people.dat" }; datFileStream) {

        // Read complete source file with the vectors range constructor
        std::vector persons(std::istream_iterator<Person>(datFileStream), {});

        // Show debug output
        for (const Person& p : persons) std::cout << p;
    }
    else
        std::cerr << "\n\n*** Error: Could not open source file\n";
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM