Редактирование записи в последовательном двоичном файле

При редактировании записи о продукте с помощью функции editProduct возникает проблема последующего вывода списка в консоль. Приведу пример: я хочу изменить запись под индексом 1, ввожу новые данные, затем хочу посмотреть изменилась ли запись. Вывожу в консоль список с помощью функции viewProducts, вижу следующую картину: все записи о товарах, что были после индекса 1 не выводятся в консоль, хотя в бинарном файле они есть. В чём может быть проблема?
Сравнение размерности полей должно быть по заданию: при изменении размерности записи она переписывается в конец файла.

#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>
#include <vector>
#include <algorithm>
#include <iomanip> 

using namespace std;

// Класс Product
class Product {
public:
    Product();
    Product(const string& _name, const string& _category, int _quantity,
        const string& _arrivalDate, double _price, double _markupPercentage);
    Product(const Product& obj); // Конструктор копирования
    ~Product();

    // Геттеры
    string getName() const;
    string getCategory() const;
    int getQuantity() const;
    string getArrivalDate() const;
    double getPrice() const;
    double getMarkupPercentage() const;

    // Сеттеры
    void setName(const string& _name);
    void setCategory(const string& _category);
    void setQuantity(int _quantity);
    void setArrivalDate(const string& _arrivalDate);
    void setPrice(double _price);
    void setMarkupPercentage(double _markupPercentage);

    // Сериализация
    void serialize(std::ostream& os) const;
    void deserialize(std::istream& is);

    long next; 
    long prev; 

private:
    string name;
    string category;
    int quantity;
    string arrivalDate;
    double price;
    double markupPercentage;
};

#define MAXnameLength 100
#define MAXcategoryLength 100

Product::Product()
    : name(""), category(""), quantity(0), arrivalDate(""),
    price(0.0), markupPercentage(0.0), next(-1), prev(-1) {}

Product::Product(const string& _name, const string& _category, int _quantity,
    const string& _arrivalDate, double _price, double _markupPercentage)
    : name(_name), category(_category), quantity(_quantity),
    arrivalDate(_arrivalDate), price(_price), markupPercentage(_markupPercentage),
    next(-1), prev(-1) {}

Product::Product(const Product& obj)
    : name(obj.name), category(obj.category), quantity(obj.quantity),
    arrivalDate(obj.arrivalDate), price(obj.price),
    markupPercentage(obj.markupPercentage), next(obj.next), prev(obj.prev) {}

Product::~Product() {}

string Product::getName() const { return name; }
string Product::getCategory() const { return category; }
int Product::getQuantity() const { return quantity; }
string Product::getArrivalDate() const { return arrivalDate; }
double Product::getPrice() const { return price; }
double Product::getMarkupPercentage() const { return markupPercentage; }

void Product::setName(const string& _name) { name = _name; }
void Product::setCategory(const string& _category) { category = _category; }
void Product::setQuantity(int _quantity) { quantity = _quantity; }
void Product::setArrivalDate(const string& _arrivalDate) { arrivalDate = _arrivalDate; }
void Product::setPrice(double _price) { price = _price; }
void Product::setMarkupPercentage(double _markupPercentage) { markupPercentage = _markupPercentage; }

void Product::serialize(std::ostream& os) const {
    size_t nameLength = name.size();
    os.write(reinterpret_cast<const char*>(&nameLength), sizeof(nameLength));
    os.write(name.c_str(), nameLength);

    size_t categoryLength = category.size();
    os.write(reinterpret_cast<const char*>(&categoryLength), sizeof(categoryLength));
    os.write(category.c_str(), categoryLength);

    os.write(reinterpret_cast<const char*>(&quantity), sizeof(quantity));

    size_t arrivalDateLength = arrivalDate.size();
    os.write(reinterpret_cast<const char*>(&arrivalDateLength), sizeof(arrivalDateLength));
    os.write(arrivalDate.c_str(), arrivalDateLength);

    os.write(reinterpret_cast<const char*>(&price), sizeof(price));
    os.write(reinterpret_cast<const char*>(&markupPercentage), sizeof(markupPercentage));

    os.write(reinterpret_cast<const char*>(&prev), sizeof(prev));
    os.write(reinterpret_cast<const char*>(&next), sizeof(next));
}

void Product::deserialize(std::istream& is) {
    size_t nameLength;
    is.read(reinterpret_cast<char*>(&nameLength), sizeof(nameLength));
    if (nameLength > MAXnameLength) {
        throw std::runtime_error("Длина имени превышает допустимое значение.");
    }
    name.resize(nameLength);
    is.read(&name[0], nameLength);

    size_t categoryLength;
    is.read(reinterpret_cast<char*>(&categoryLength), sizeof(categoryLength));
    if (categoryLength > MAXcategoryLength) {
        throw std::runtime_error("Длина категории превышает допустимое значение.");
    }
    category.resize(categoryLength);
    is.read(&category[0], categoryLength);

    is.read(reinterpret_cast<char*>(&quantity), sizeof(quantity));

    size_t arrivalDateLength;
    is.read(reinterpret_cast<char*>(&arrivalDateLength), sizeof(arrivalDateLength));
    arrivalDate.resize(arrivalDateLength);
    is.read(&arrivalDate[0], arrivalDateLength);

    is.read(reinterpret_cast<char*>(&price), sizeof(price));
    is.read(reinterpret_cast<char*>(&markupPercentage), sizeof(markupPercentage));

    is.read(reinterpret_cast<char*>(&prev), sizeof(prev));
    is.read(reinterpret_cast<char*>(&next), sizeof(next));
}

// Класс BinaryFile
class BinaryFile {
public:
    BinaryFile(const char* filename);
    ~BinaryFile();

    void addProduct(const Product& product);
    void deleteProduct(size_t index);
    void insertProduct(size_t index, const Product& product);
    void editProduct(size_t index, const Product& product);
    void sortProducts();
    void viewProducts(size_t pageSize, size_t pageNumber);
    void createInvoice();
    void compressFile();
    Product getProductByIndex(size_t index);

private:
    std::fstream file;
    const char* filename;

    long head; // Указатель на голову списка
    long tail; // Указатель на хвост списка

    size_t getProductCount();
    Product readProduct(long offset);
    void writeProduct(long offset, const Product& product);
};

BinaryFile::BinaryFile(const char* filename) : filename(filename), head(-1), tail(-1) {
    file.open(filename, std::ios::binary | std::ios::in | std::ios::out | std::ios::trunc);
    if (!file.is_open()) {
        file.open(filename, std::ios::binary | std::ios::out | std::ios::trunc);
        file.close();
        file.open(filename, std::ios::binary | std::ios::in | std::ios::out);
    }
}

BinaryFile::~BinaryFile() {
    file.close();
}

size_t BinaryFile::getProductCount() {
    file.clear();
    file.seekg(0, std::ios::beg);
    size_t count = 0;
    while (file.peek() != EOF) {
        Product product;
        product.deserialize(file);
        count++;
    }
    return count;
}

Product BinaryFile::readProduct(long offset) {
    file.clear();
    file.seekg(offset, std::ios::beg);
    Product product;
    product.deserialize(file);
    return product;
}

void BinaryFile::writeProduct(long offset, const Product& product) {
    file.clear();
    file.seekp(offset, std::ios::beg);
    product.serialize(file);
}

void BinaryFile::addProduct(const Product& product) {
    long newOffset = file.tellp();
    Product newProduct = product;

    // Установка указателей
    if (tail != -1) {
        newProduct.prev = tail;
        Product tailProduct = readProduct(tail);
        tailProduct.next = newOffset;
        writeProduct(tail, tailProduct);
    }
    else {
        newProduct.prev = -1; // Это первый элемент
        head = newOffset;
    }

    newProduct.next = -1; // Указывает на конец списка
    writeProduct(newOffset, newProduct);
    tail = newOffset; // Обновляем хвост
}

void BinaryFile::deleteProduct(size_t index) {
    long currentOffset = head;
    long productOffset = -1;
    long prevOffset = -1;

    // Находим продукт по индексу
    for (size_t i = 0; i < index && currentOffset != -1; ++i) {
        prevOffset = currentOffset; // Сохраняем предыдущий продукт
        Product currentProduct = readProduct(currentOffset);
        currentOffset = currentProduct.next;
    }

    if (currentOffset == -1) {
        throw std::out_of_range("Index out of range");
    }

    // Удаляем продукт
    Product productToDelete = readProduct(currentOffset);

    // Обновляем указатели prev и next для соседних продуктов
    if (prevOffset != -1) {
        Product prevProduct = readProduct(prevOffset);
        prevProduct.next = productToDelete.next; // Пропускаем удаляемый продукт
        writeProduct(prevOffset, prevProduct); // Записываем обновленный продукт
    }
    else {
        head = productToDelete.next; // Если удаляемый продукт был головой
    }

    if (productToDelete.next != -1) {
        Product nextProduct = readProduct(productToDelete.next);
        nextProduct.prev = prevOffset; // Обновляем указатель prev для следующего продукта
        writeProduct(productToDelete.next, nextProduct);
    }
    else {
        tail = prevOffset; // Если удаляемый продукт был хвостом
    }


}


void BinaryFile::insertProduct(size_t index, const Product& product) {
    long currentOffset = head;
    long newOffset = file.tellp(); // Получаем текущую позицию для нового продукта

    for (size_t i = 0; i < index && currentOffset != -1; ++i) {
        Product currentProduct = readProduct(currentOffset);
        currentOffset = currentProduct.next;
    }

    Product newProduct = product;
    newProduct.prev = (currentOffset != -1) ? (currentOffset != head ? readProduct(currentOffset).prev : head) : tail;
    newProduct.next = currentOffset;

    // Обновляем указатель prev для предыдущего продукта
    if (newProduct.prev != -1) {
        Product prevProduct = readProduct(newProduct.prev);
        prevProduct.next = newOffset; // Указатель на новый продукт
        writeProduct(newProduct.prev, prevProduct);
    }
    else {
        head = newOffset; // Новый продукт становится головой
    }

    writeProduct(newOffset, newProduct); // Записываем новый продукт

    // Обновляем указатель prev для текущего продукта
    if (currentOffset != -1) {
        Product currentProduct = readProduct(currentOffset);
        currentProduct.prev = newOffset;
        writeProduct(currentOffset, currentProduct);
    }
    else {
        tail = newOffset; // Если вставляем в конец, обновляем хвост
    }
}


void BinaryFile::editProduct(size_t index, const Product& product) {
    long currentOffset = head;
    long previousOffset = -1;

    // Находим продукт по индексу
    for (size_t i = 0; i < index && currentOffset != -1; ++i) {
        previousOffset = currentOffset;
        Product currentProduct = readProduct(currentOffset);
        currentOffset = currentProduct.next;
    }

    if (currentOffset == -1) {
        throw std::out_of_range("Index out of range");
    }

    Product productToEdit = readProduct(currentOffset);

    // Сравниваем размеры полей
    size_t newNameLength = product.getName().size();
    size_t newCategoryLength = product.getCategory().size();
    size_t newArrivalDateLength = product.getArrivalDate().size();

    size_t oldNameLength = productToEdit.getName().size();
    size_t oldCategoryLength = productToEdit.getCategory().size();
    size_t oldArrivalDateLength = productToEdit.getArrivalDate().size();

    // Проверяем, изменился ли размер хотя бы одного поля
    bool sizeChanged = (newNameLength != oldNameLength) || 
                       (newCategoryLength != oldCategoryLength) || 
                       (newArrivalDateLength != oldArrivalDateLength);

    if (sizeChanged) {
        // Удаляем старый продукт
        deleteProduct(index);
        // Добавляем новый продукт в конец файла
        addProduct(product);

        
    } else {
        // Если размеры не изменились, просто перезаписываем
        writeProduct(currentOffset, product);
    }
}




void BinaryFile::sortProducts() {
    size_t productCount = getProductCount();
    std::vector<Product> products;

    // Считываем все продукты в вектор
    long currentOffset = head;
    while (currentOffset != -1) {
        products.push_back(readProduct(currentOffset));
        currentOffset = products.back().next;
    }

    // Выбор параметра сортировки
    int sortChoice;
    std::cout << "Выберите параметр для сортировки:" << std::endl;
    std::cout << "1. Имя" << std::endl;
    std::cout << "2. Категория" << std::endl;
    std::cout << "3. Количество" << std::endl;
    std::cout << "4. Дата поступления" << std::endl;
    std::cout << "5. Цена" << std::endl;
    std::cout << "6. Процент наценки" << std::endl;
    std::cout << "Введите номер параметра: ";
    std::cin >> sortChoice;

    // Сортировка вектора в зависимости от выбора пользователя
    switch (sortChoice) {
    case 1:
        std::sort(products.begin(), products.end(), [](const Product& a, const Product& b) {
            return a.getName() < b.getName();
            });
        break;
    case 2:
        std::sort(products.begin(), products.end(), [](const Product& a, const Product& b) {
            return a.getCategory() < b.getCategory();
            });
        break;
    case 3:
        std::sort(products.begin(), products.end(), [](const Product& a, const Product& b) {
            return a.getQuantity() < b.getQuantity();
            });
        break;
    case 4:
        std::sort(products.begin(), products.end(), [](const Product& a, const Product& b) {
            return a.getArrivalDate() < b.getArrivalDate();
            });
        break;
    case 5:
        std::sort(products.begin(), products.end(), [](const Product& a, const Product& b) {
            return a.getPrice() < b.getPrice();
            });
        break;
    case 6:
        std::sort(products.begin(), products.end(), [](const Product& a, const Product& b) {
            return a.getMarkupPercentage() < b.getMarkupPercentage();
            });
        break;
    default:
        std::cout << "Неверный выбор. Сортировка отменена." << std::endl;
        return;
    }

    // Запись отсортированных продуктов обратно в файл
    file.clear();
    file.seekp(0, std::ios::beg);
    head = -1;
    tail = -1;

    for (const auto& product : products) {
        addProduct(product);
    }
}


void BinaryFile::viewProducts(size_t pageSize, size_t pageNumber) {
    long currentOffset = head;
    size_t count = 0;
    size_t startIndex = (pageNumber - 1) * pageSize;

    // Заголовок таблицы
    std::cout << std::left << std::setw(15) << "Имя"
        << std::setw(20) << "Категория"
        << std::setw(15) << "Количество"
        << std::setw(20) << "Дата поступления"
        << std::setw(15) << "Цена"
        << std::setw(15) << "Процент наценки" << std::endl;

    // Разделительная линия
    std::cout << std::string(100, '-') << std::endl;

    while (currentOffset != -1 && count < startIndex + pageSize) {
        Product product = readProduct(currentOffset);
        if (count >= startIndex) {
            std::cout << std::left << std::setw(15) << product.getName()
                << std::setw(20) << product.getCategory()
                << std::setw(15) << product.getQuantity()
                << std::setw(20) << product.getArrivalDate()
                << std::setw(15) << product.getPrice()
                << std::setw(15) << product.getMarkupPercentage() << std::endl;
        }
        currentOffset = product.next;
        count++;
    }

    // Разделительная линия в конце
    std::cout << std::string(100, '-') << std::endl;
}

void BinaryFile::compressFile() {
    // Создаем временный файл для сжатых данных
    const char* tempFilename = "compressed_products.bin";
    std::fstream tempFile(tempFilename, std::ios::binary | std::ios::out);

    // Проверяем, удалось ли открыть временный файл
    if (!tempFile.is_open()) {
        throw std::runtime_error("Не удалось открыть временный файл для сжатия.");
    }

    // Считываем все продукты и записываем их в новый файл
    long currentOffset = head;
    std::streampos prevPosition = -1; // Используем std::streampos для prev

    while (currentOffset != -1) {
        Product product = readProduct(currentOffset);
        product.prev = (prevPosition == -1) ? std::streampos(-1) : prevPosition; // Приводим к std::streampos
        product.next = -1; // Изначально указываем на конец списка

        // Записываем продукт в временный файл
        product.serialize(tempFile);

        // Обновляем prevPosition для следующего продукта
        prevPosition = tempFile.tellp(); // Получаем текущую позицию в файле

        // Переходим к следующему продукту
        currentOffset = product.next;
    }

    // Закрываем временный файл
    tempFile.close();

    std::cout << "Сжатый файл сохранен как " << tempFilename << std::endl;
}


void BinaryFile::createInvoice() {
    std::vector<Product> selectedProducts;
    double totalAmount = 0.0;
    double totalMarkup = 0.0;

    while (true) {
        size_t productIndex;
        std::cout << "Введите индекс продукта для добавления в фактуру (или -1 для завершения): ";
        std::cin >> productIndex;

        if (productIndex == static_cast<size_t>(-1)) {
            break; // Завершение выбора продуктов
        }

        long currentOffset = head;
        for (size_t i = 0; i < productIndex && currentOffset != -1; ++i) {
            Product currentProduct = readProduct(currentOffset);
            currentOffset = currentProduct.next;
        }

        if (currentOffset == -1) {
            std::cout << "Продукт с таким индексом не найден." << std::endl;
            continue; // Повторить выбор
        }

        Product selectedProduct = readProduct(currentOffset);
        int quantityToBuy;

        std::cout << "Введите количество для покупки (доступно: " << selectedProduct.getQuantity() << "): ";
        std::cin >> quantityToBuy;

        if (quantityToBuy > selectedProduct.getQuantity()) {
            std::cout << "Недостаточно товара на складе." << std::endl;
            continue; // Повторить выбор
        }

        // Уменьшение количества на складе
        selectedProduct.setQuantity(selectedProduct.getQuantity() - quantityToBuy);
        writeProduct(currentOffset, selectedProduct); // Обновление продукта в файле

        // Подсчет суммы и торговой надбавки
        double amount = selectedProduct.getPrice() * quantityToBuy;
        double markup = amount * (selectedProduct.getMarkupPercentage() / 100);

        totalAmount += amount;
        totalMarkup += markup;

        selectedProducts.push_back(selectedProduct); // Сохранение выбранного товара
    }

    // Вывод фактуры
    std::cout << "----- Фактура -----" << std::endl;
    for (const auto& product : selectedProducts) {
        double amount = product.getPrice() * (product.getQuantity() + 1); // Возвращаем количество до уменьшения
        std::cout << "Продукт: " << product.getName()
            << ", Количество: " << (product.getQuantity() + 1)
            << ", Цена: " << product.getPrice()
            << ", Сумма: " << amount << std::endl;
    }

    std::cout << "Общая сумма: " << totalAmount << std::endl;
    std::cout << "Общая торговая надбавка: " << totalMarkup << std::endl;
}

Product BinaryFile::getProductByIndex(size_t index) {
    long currentOffset = head;
    for (size_t i = 0; i < index && currentOffset != -1; ++i) {
        Product currentProduct = readProduct(currentOffset);
        currentOffset = currentProduct.next;
    }

    if (currentOffset == -1) {
        throw std::out_of_range("Index out of range");
    }

    return readProduct(currentOffset);
}


void displayMenu() {
    std::cout << "Выберите операцию:" << std::endl;
    std::cout << "1. Добавить продукт" << std::endl;
    std::cout << "2. Редактировать продукт" << std::endl;
    std::cout << "3. Вставить продукт" << std::endl;
    std::cout << "4. Просмотреть продукты" << std::endl;
    std::cout << "5. Сортировать продукты" << std::endl;
    std::cout << "6. Сжать файл" << std::endl;
    std::cout << "7. Составить фактуру" << std::endl;
    std::cout << "8. Извлечь продукт по индексу" << std::endl;
    std::cout << "9. Удалить продукт по индексу" << std::endl;
    std::cout << "0. Выход" << std::endl;
}

int main() {
    setlocale(LC_ALL, "Russian");
    BinaryFile binFile("products.bin");
    // Автоматическое добавление товаров
    std::vector<Product> products = {
        Product("Apples", "Fruits", 50, "10-10-2023", 1.20, 15.5),
        Product("Bananas", "Fruits", 40, "10-10-2023", 0.50, 8.0),
        Product("Bread", "Bakery", 30, "10-10-2023", 2.50, 10.0),
        Product("Milk", "Dairy", 20, "10-10-2023", 1.00, 5.0),
        Product("Chicken", "Meat", 15, "10-10-2023", 5.75, 20.0),
        Product("Rice", "Grains", 25, "10-10-2023", 0.80, 12.5),
        Product("Cheese", "Dairy", 10, "10-10-2023", 3.00, 7.5),
        Product("Eggs", "Dairy", 12, "10-10-2023", 2.00, 6.0)
    };

    for (const auto& product : products) {
        binFile.addProduct(product);
    }

    int choice;

    while (true) {
        displayMenu();
        std::cout << "Введите номер операции: ";
        std::cin >> choice;

        switch (choice) {
        case 1: {
            std::string name, category, arrivalDate;
            int quantity;
            double price, markupPercentage;

            std::cout << "Введите имя продукта: ";
            std::cin >> name;
            std::cout << "Введите категорию продукта: ";
            std::cin >> category;
            std::cout << "Введите количество: ";
            std::cin >> quantity;
            std::cout << "Введите дату поступления (YYYY-MM-DD): ";
            std::cin >> arrivalDate;
            std::cout << "Введите цену: ";
            std::cin >> price;
            std::cout << "Введите процент наценки: ";
            std::cin >> markupPercentage;

            Product newProduct(name, category, quantity, arrivalDate, price, markupPercentage);
            binFile.addProduct(newProduct);
            break;
        }
        case 2: {
            size_t index;
            std::cout << "Введите индекс продукта для редактирования: ";
            std::cin >> index;

            std::string name, category, arrivalDate;
            int quantity;
            double price, markupPercentage;

            std::cout << "Введите новое имя продукта: ";
            std::cin >> name;
            std::cout << "Введите новую категорию продукта: ";
            std::cin >> category;
            std::cout << "Введите новое количество: ";
            std::cin >> quantity;
            std::cout << "Введите новую дату поступления (YYYY-MM-DD): ";
            std::cin >> arrivalDate;
            std::cout << "Введите новую цену: ";
            std::cin >> price;
            std::cout << "Введите новый процент наценки: ";
            std::cin >> markupPercentage;

            Product updatedProduct(name, category, quantity, arrivalDate, price, markupPercentage);
            binFile.editProduct(index, updatedProduct);
            break;
        }
        case 3: {
            size_t index;
            std::cout << "Введите индекс для вставки продукта: ";
            std::cin >> index;

            std::string name, category, arrivalDate;
            int quantity;
            double price, markupPercentage;

            std::cout << "Введите имя продукта: ";
            std::cin >> name;
            std::cout << "Введите категорию продукта: ";
            std::cin >> category;
            std::cout << "Введите количество: ";
            std::cin >> quantity;
            std::cout << "Введите дату поступления (YYYY-MM-DD): ";
            std::cin >> arrivalDate;
            std::cout << "Введите цену: ";
            std::cin >> price;
            std::cout << "Введите процент наценки: ";
            std::cin >> markupPercentage;

            Product newProduct(name, category, quantity, arrivalDate, price, markupPercentage);
            binFile.insertProduct(index, newProduct);
            break;
        }
        case 4: {
            size_t pageSize, pageNumber;
            std::cout << "Введите размер страницы: ";
            std::cin >> pageSize;
            std::cout << "Введите номер страницы: ";
            std::cin >> pageNumber;
            binFile.viewProducts(pageSize, pageNumber);
            break;
        }
        case 5: {
            binFile.sortProducts();
            std::cout << "Продукты отсортированы." << std::endl;
            break;
        }
        case 6: {
            binFile.compressFile();
            std::cout << "Файл сжат." << std::endl;
            break;
        }
        case 7: {
            binFile.createInvoice();
            std::cout << "Фактура создана." << std::endl;
            break;
        }
        case 8: { 
            size_t index;
            std::cout << "Введите индекс продукта для извлечения: ";
            std::cin >> index;

            try {
                Product product = binFile.getProductByIndex(index);
                std::cout << "Извлеченный продукт:" << std::endl;
                std::cout << "Имя: " << product.getName() << std::endl;
                std::cout << "Категория: " << product.getCategory() << std::endl;
                std::cout << "Количество: " << product.getQuantity() << std::endl;
                std::cout << "Дата поступления: " << product.getArrivalDate() << std::endl;
                std::cout << "Цена: " << product.getPrice() << std::endl;
                std::cout << "Процент наценки: " << product.getMarkupPercentage() << std::endl;
            }
            catch (const std::out_of_range& e) {
                std::cout << e.what() << std::endl;
            }
            break;
        }
        case 9: { 
            size_t index;
            std::cout << "Введите индекс продукта для удаления: ";
            std::cin >> index;

            try {
                binFile.deleteProduct(index);
                std::cout << "Продукт успешно удален." << std::endl;
            }
            catch (const std::out_of_range& e) {
                std::cout << e.what() << std::endl;
            }
            break;
        }

        case 0:
            return 0;
        default:
            std::cout << "Неверный выбор. Попробуйте снова." << std::endl;
        }
    }

    return 0;
}

  • std::ios::trunc сразу обрежет файл до нулевой длины при открытии.
  • Поэтому, даже если вы собираетесь записывать в “середину”, на момент открытия файла его длина уже равна нулю.

Вообще не ясно, как вы собираетесь позиционироваться на нужную запись, если записи у вас разного размера.