C/C++

Есть структура, где много различных полей, в т. ч. типа string. Как потоком читать из файла в структуру данные? Возникает

Ошибка bad allocation
Здесь важно грамотно спроектировать структуру. Для этого тип std::string не подходит, так как для бинарного представления важно, чтобы все записываемые и читаемые куски были всегда одного размера. Поэтому для строк всегда используете статические массивы, размер которых должен быть известен до начала компиляции.

Чтобы бинарный файл в программе прочитать, его нужно сначала этой же программой записать. Потому что никто лучше, чем записывающая программа не знает размер структуры данных. А он важен!

Итак, пример, написанный в среде Visual C++2019...

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <vector>
#include <cstring>
using namespace std;
struct Box {
int id;
double rating;
char title[52];
Box(int id, double rating, const char* src) : id(id), rating(rating) {
strcpy_s(title, 52, src); // strcpy_s это самоуправство Майкрософт
}
Box() : id(0), rating(0) {}
friend bool operator<(const Box& a, const Box& b) {
return a.rating < b.rating;
}
friend bool operator>(const Box& a, const Box& b) {
return a.rating > b.rating;
}
friend ostream& operator<<(ostream& out, const Box& box) {
out.setf(ios::fixed);
out.precision(2);
out << setw(2) << box.id << ". "
<< setw(52) << left << box.title
<< setw(8) << right << box.rating;
out.unsetf(ios::fixed);
out.precision(8);
return out;
}
};
int main() {
vector<Box> box{
{ 1, 4498.36, "Lenovo Ideapad L340-15" },
{ 2, 4947.82, "Apple MacBook Air 13 Late 2020" },
{ 3, 4632.07, "ASUS VivoBook 15 X512" },
{ 4, 4910.37, "MSI GL75 Leopard 10SDK" },
{ 5, 4628.25, "HONOR MagicBook Pro" }
};
ofstream db("database.bin", ios::binary);
if (db.is_open()) {
for (auto& item : box) {
db.write((char*)&item, sizeof(item)); // вот и вся запись!
}
db.close();
} else {
puts("The database.bin file has not been created!");
}
vector<Box> tmp;
ifstream op("database.bin", ios::binary);
if (op.is_open()) {
Box box;
while (op.read((char*)&box, sizeof(box))) { // вот и всё чтение!
tmp.push_back(box);
}
op.close();
sort(tmp.begin(), tmp.end(), greater<>()); // сортировка по рейтингу через перегруженный оператор
for (const auto& item : tmp) cout << item << '\n';
} else {
puts("File database.bin not found!");
}
system("pause > nul");
}

P.S. Как видно из кода, писать и читать бинарные файлы стандартными средствами намного проще, чем любые другие, и никакие сторонние библиотеки для этого использовать не нужно.

P.P.S. При проектировании структуры её поля обязательно следует ранжировать по размеру в байтах от меньшего к большему и писать/читать их сверху вниз!

Удачи!
Руслан Байзак
Руслан Байзак
80 004
Лучший ответ
Правильно читать, чтобы ошибки не возникало.
Я бы вообще fc library применил. Она поддерживает рефлексию для таких структур, чтобы не приходилось чтение каждого поля отдельно делать. Правда, эта библиотека почти никому не известна и надо быть хорошим программистом, чтобы научиться ей пользоваться.
Но можно то же самое сделать и без fc. Просто читай поля структуры по очереди и все.
Сергей Головко
Сергей Головко
92 464
Анатолий Тутевич Так он бинарный
Анатолий Тутевич Как сделать правильно?