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. При проектировании структуры её поля обязательно следует ранжировать по размеру в байтах от меньшего к большему и писать/читать их сверху вниз!
Удачи!
Чтобы бинарный файл в программе прочитать, его нужно сначала этой же программой записать. Потому что никто лучше, чем записывающая программа не знает размер структуры данных. А он важен!
Итак, пример, написанный в среде 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. При проектировании структуры её поля обязательно следует ранжировать по размеру в байтах от меньшего к большему и писать/читать их сверху вниз!
Удачи!
Правильно читать, чтобы ошибки не возникало.
Я бы вообще fc library применил. Она поддерживает рефлексию для таких структур, чтобы не приходилось чтение каждого поля отдельно делать. Правда, эта библиотека почти никому не известна и надо быть хорошим программистом, чтобы научиться ей пользоваться.
Но можно то же самое сделать и без fc. Просто читай поля структуры по очереди и все.
Я бы вообще fc library применил. Она поддерживает рефлексию для таких структур, чтобы не приходилось чтение каждого поля отдельно делать. Правда, эта библиотека почти никому не известна и надо быть хорошим программистом, чтобы научиться ей пользоваться.
Но можно то же самое сделать и без fc. Просто читай поля структуры по очереди и все.
Анатолий Тутевич
Так он бинарный
Анатолий Тутевич

Анатолий Тутевич
Как сделать правильно?
Похожие вопросы
- Язык Си. Тема: структуры данных.
- Задача на структуры данных, очереди и стек, не могу понять что делаю нет так?
- Нужно найти в бинарном файле введенные пользователем данные.
- Удалить дубликаты в структуре данных лист (ошибка в коде)
- Для чего можно приспособить следующие структуры данных...
- Создать файл ABONENT.dat, содержащий записи следующей структуры: ФИО абонента; его номер телефона. на языке си++
- Создать структуры в с++
- [C++] Помогите написать задачу на структуры!
- Программа на c++ не работает. Написать структуру и прочее. Подскажите, пожалуйста, что я делаю не так.
- Вложенные структуры. С++