Заполнить объект из текстового файла C ++ - PullRequest
1 голос
/ 10 апреля 2020

Я пишу программу, которая требует загрузки базы данных из текстового файла. Класс базы данных содержит вектор записей, а записи являются классом.

пример

vector<People> lib;
class People {
 string name;
 string occupation;
 int cats_age[2]
 int age;
//code here
}

Как заполнить базу данных из текстового файла, содержащего записи в формате

marry wang-dog walker-0-17-78

Я пытался использовать

file.read((char*)& entry, sizeof(entry))

но это не сработало

Я также рассмотрел перегрузку оператора >> однако некоторые поля являются строками, которые содержат пробелы. Как мне заполнить объект, прочитав все, что находится между символом "-"?

-Спасибо

1 Ответ

1 голос
/ 10 апреля 2020

Вы не можете сделать необработанный read из файла в People объект. People содержит нетривиальный тип (std::string), и каждая запись в файле должна иметь одинаковый размер для работы необработанных операций чтения, что не имеет место в вашем файле.

Что люди часто добавляют перегрузку для operator>> для поддержки форматированного ввода из любого std::istream (например, std::ifstream или std::cin).

Поскольку переменные-члены private, вам необходимо добавьте operator>> a friend, чтобы он мог обращаться к переменным private.

Вы можете использовать std::getline для чтения, пока не будет найден определенный символ (например, ваш разделитель -). Он удалит разделитель из потока, но не включит его в переменную, в которой хранится результат.

std::getline возвращает ссылку на istream, из которого было дано чтение, чтобы вы могли связать несколько std::getline s.

Я бы также переименовал ваш класс в Person, поскольку он содержит информацию только об одном человеке.

Пример:

#include <iostream>
#include <string>
#include <vector>

#include <sstream>

class Person {
    std::string name;
    std::string occupation;
    int cats_age[2];
    int age;

    friend std::istream& operator>>(std::istream&, Person&);
    friend std::ostream& operator<<(std::ostream&, const Person&);
};

// read one Person from an istream
std::istream& operator>>(std::istream& is, Person& p) {
    using std::getline;
    char del; // for reading the delimiter '-'
    std::string nl_eater; // for removing the newline after age

    // chaining getline:s and >>:s
    return getline(getline(getline(is, p.name, '-'), p.occupation, '-') >>
                       p.cats_age[0] >> del >> p.cats_age[1] >> del >> p.age, nl_eater);
}

// write one Person to an ostream
std::ostream& operator<<(std::ostream& os, const Person& p) {
    return os << p.name << '-' << p.occupation << '-' << p.cats_age[0] << '-'
              << p.cats_age[1] << '-' << p.age << '\n';
}

int main() {
    // example of an istream - it could just as well had been a std::ifstream
    std::istringstream is(
        "marry wang-dog walker-0-17-78\n"
        "foo bar-unemployed-1-2-3\n"
    );

    std::vector<Person> people;

    Person temp;
    while(is >> temp) { // loop for as long as extraction of one Person succeeds
        people.push_back(temp);
    }

    // print all the collected Persons
    for(const Person& p : people) {
        std::cout << p;
    }
}

Вывод:

marry wang-dog walker-0-17-78
foo bar-unemployed-1-2-3

Я предлагаю выбрать другой разделитель полей, чем -. Многие имена содержат -, как и отрицательные числа. Используйте символ, который вряд ли будет включен ни в одно из полей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...