Неправильно считывается число из бинарного файла

class PizzeriaDB {
public:
    ~PizzeriaDB() = default;
    std::vector<Pizza> getPizzasAvailable() const;
    void addClient(std::string, std::string);
    void addEmployee(const std::string& name);
    void deleteEmployee(const std::string& s);
    void addPizza(const std::string& name, double price);
    void deletePizza(const std::string& s);
    void setAdminKey(const std::string& s);
    bool AdminIsValid(const std::string&) const;
    bool ClientIsValid(const std::string&, const std::string&) const;
    void newOrder(const Order& o);
    void complete_order();
    void GetDB();
    void SaveDB();
private:
    std::string AdminKey = "superadmin";
    std::vector<Pizza> availablePizzas;
    std::vector<Employee> workers;
    std::map<std::string, std::string> clientData;
    std::queue<Order> current_orders;
};

class Employee {
public:
    Employee() = default;
    Employee(const std::string& name, bool free = true);
    void doWork(const Order& o);
    bool isFree() const;
    std::string getName() const;
    void SetName(const std::string& n) {
        name = n;
    }

    void SetFree(bool f) {
        free = f;
    }

    // Методы для получения данных
    const std::string& GetName() const {
        return name;
    }

    bool IsFree() const {
        return free;
    }
private:
    std::string name;
    bool free = 1;
};

class Pizza {
public:
    Pizza() = default;
    ~Pizza() {};
    Pizza(const std::string& type, double price, int amount = 1);
    std::string getType() const;
    double getPrice() const;
    int getAmount() const;
    std::string getName() const;
    void SetPizzaType(const std::string& type) {
        pizza_type = type;
    }
    void SetPrice(double p) {
        price = p;
    }
    void SetAmount(unsigned int a) {
        amount = a;
    }
    const std::string& GetPizzaType() const {
        return pizza_type;
    }
    double GetPrice() const {
        return price;
    }
    unsigned int GetAmount() const {
        return amount;
    }
private:
    std::string pizza_type;
    double price = 1;
    unsigned int amount = 1;
};

void PizzeriaDB::SaveDB() {
    // Запись PizzaCatalogue
    out.open("PizzaCatalogue.bin", std::ios::binary | std::ios::out);
    if (!out) {
        std::cout << "Failed to open PizzaCatalogue.bin for writing." << std::endl;
        return;
    }
    size_t pizzaCount = availablePizzas.size();
    out.write((char*)&pizzaCount, sizeof(size_t));
    for (const auto& pizza : availablePizzas) {
        size_t typeLen = pizza.GetPizzaType().size();
        out.write((char*)&typeLen, sizeof(size_t));
        const std::string& pizzaType = pizza.GetPizzaType();
        out.write(pizzaType.c_str(), typeLen);
        double price = pizza.GetPrice();
        out.write((char*)&price, sizeof(double));
    }
    out.close();

    // Запись WorkersDB
    out.open("WorkersDB.bin", std::ios::binary | std::ios::out);
    if (!out) {
        std::cout << "Failed to open WorkersDB.bin for writing." << std::endl;
        return;
    }
    size_t workerCount = workers.size();
    out.write((char*)&workerCount, sizeof(size_t));
    for (const auto& worker : workers) {
        size_t nameLen = worker.GetName().size();
        out.write((char*)&nameLen, sizeof(size_t));
        out.write(worker.GetName().c_str(), nameLen);
    }
    out.close();
}

void PizzeriaDB::GetDB() {
    // Чтение PizzaCatalogue
    in.open("PizzaCatalogue.bin", std::ios::binary);
    if (!in) {
        std::cout << "Failed to open PizzaCatalogue.bin for reading." << std::endl;
        return;
    }
    if (in.peek() == std::ifstream::traits_type::eof()) {
        // Файл пуст, пропускаем чтение
        return;
    }
    size_t pizzaCount;
    in.read((char*)&pizzaCount, sizeof(size_t));
    availablePizzas.resize(pizzaCount);
    for (size_t i = 0; i < pizzaCount; ++i) {
        Pizza pizza;
        size_t typeLen;
        in.read((char*)&typeLen, sizeof(size_t));
        std::string pizzaType(typeLen, '\0');
        in.read(&pizzaType[0], typeLen);
        pizza.SetPizzaType(pizzaType);
        double price;
        in.read((char*)&price, sizeof(double));
        pizza.SetPrice(price);
        availablePizzas[i] = pizza;
    }
    in.close();

    // Чтение WorkersDB
    in.open("WorkersDB.bin", std::ios::binary);
    if (!in) {
        std::cout << "Failed to open WorkersDB.bin for reading." << std::endl;
        return;
    }
    if (in.peek() == std::ifstream::traits_type::eof()) {
        // Файл пуст, пропускаем чтение
        return;
    }
    size_t workerCount;
    in.read((char*)&workerCount, sizeof(size_t));
    workers.resize(workerCount);
    for (size_t i = 0; i < workerCount; ++i) {
        Employee employee;
        size_t nameLen = 20;
        in.read((char*)&nameLen, sizeof(size_t));   
        std::string name(nameLen, '\0');
        in.read(&name[0], nameLen);
        employee.SetName(name);
        bool isFree;
        in.read((char*)&isFree, sizeof(bool));
        employee.SetFree(isFree);
        workers[i] = employee;
    }
    in.close();
}

У пицц все записывается и считывается хорошо. А вот у работников, именно у второго работника не считывается размер имени. Заносится рандомное большое число(лимит size_t наверное) и потом string не конструируется из за нехватки памяти. По сути алгоритмы записи и чтения одинаковые, что у пицц, что у работников.


Ответы (1 шт):

Автор решения: Harry

Итак, мы пишем для работника...

for (const auto& worker : workers) {
    size_t nameLen = worker.GetName().size();
    out.write((char*)&nameLen, sizeof(size_t));
    out.write(worker.GetName().c_str(), nameLen);
}

Длину строки, строку. Всё.

А что мы читаем?

in.read((char*)&nameLen, sizeof(size_t));   
std::string name(nameLen, '\0');
in.read(&name[0], nameLen);
employee.SetName(name);
bool isFree;
in.read((char*)&isFree, sizeof(bool));

Длину строки, строку, булеву переменную.

Дальше пояснять не надо? Если, грубо говоря, из кошелька брать то, что ты туда не клал — неприятности не заставят себя ждать :)

→ Ссылка