
- •Алгоритм
- •3. Этапы решения задач на эвм.
- •4. Структу́рное программи́рование
- •6. Типизированные указатели.
- •7.Ссылочный тип.
- •8.Перечислимый тип.
- •10.Процедуры ввода-вывода. Потоковый ввод-вывод.
- •13.Условный оператор. Оператор выбора.
- •14.Операторы безусловного перехода.
- •16.Циклические программы. Вложенные циклы.
- •17.Глобальные и локальные переменные.
- •18.Функции. Механизм передачи параметров.
- •19.Вложенные функции. Рекурсия.
- •20.Область видимости и время жизни переменной.
- •21.Фактические и формальные параметры.
- •22.Перегрузка функций.
- •23.Шаблоны функций.
- •24.Понятие модуля. Преимущества модульного программирования. Структура модуля.
- •25.Пример модуля. Способ использования модуля.
- •27.Символьный тип данных. Строковые массивы. Способы обработки.
- •28.Основные операции над строками. Функции для работы со строками.
- •29.Структуры. Работа со структурами. Примеры.
- •30.Массивы структур. Особенности обработки. Примеры.
- •31.Файлы. Виды файлов. Файловая переменная. Общая схема работы с файлами.
- •33.Текстовые файлы. Функции обработки для текстовых файлов.
- •34.Бинарные файлы. Функции для работы с бинарными файлами.
- •35.Статическая и динамическая память.
- •37.Алгоритмы и методы сортировки: оценка эффективности алгоритма.
- •38.Сортировка выбором.
- •43.Алгоритмы и методы поиска в отсортированном массиве данных.
34.Бинарные файлы. Функции для работы с бинарными файлами.
C++ Двоичные файлы Сохранить динамическую структуру в бинарный файл
Внимание!
Можно использовать двойной проход по файлу. Первым посчитать количество структур, выделить нужное число памяти и вторым прочитать все структуры из файла. Такой способ лучше. Мой пример менее безопасен и скорее несет только теоретическую пользу, а не практическую
Вопрос как сохранить динамическую структуру в бинарный файл меня заинтересовал сильно и сразу после моего первого опыта удачной работы с двоичными файлами. Для тех кто только что начал всё изучение с++, сам смысл использования динамических структур, объектов, классов пока не так очевиден.
Я перерыл поиск вдоль и поперек, но не нашел ничего толкового по этому поводу. В основном был приведен пример, в котором используется статическая переменная.
Можно использовать разные способы. Первые мои мысли были посчитать число объектов и записать его в начало файла, считать его оттуда как счетчик и потом выполнить цикл по этому счетчику. Да, такой вариант вполне нормальный, но мне хотелось по другому, чтоб в бинарный файл не записывалось ничего лишнего. В итоге я нашел один из способов решения. Далеко не лучший способ, но я знаю, что много людей даже так придумать не в состоянии.
Код C++ Сохранить/Прочитать динамическую структуру в бинарный файл
PHP1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 #include <iostream.h>
#include <fstream.h>
int n; //Число структур
char F[]="C:MyFile"; //Путь к файлу
//Некоторая структура
struct MyStruct
{
char Name[20];
int age;
};
MyStruct *X=0,*Y=0,*tempY; //Указатели на структуру
/*ФУНКЦИЯ ВВОДА ДАННЫХ В СТРУКТУРУ*/
void input(int i,MyStruct *X)
{
cout<<"ИМЯ ";
cin.getline(X[i].Name,20);
cout<<"ВОЗРАСТ ";
cin>>X[i].age;
cin.ignore();
cout<<"n";
}
/*ФУНКЦИЯ ВЫВОДА ДАННЫХ СТРУКТУРЫ НА ЭКРАН*/
void output(int i,MyStruct *X)
{
cout<<X[i].Name<<" "<<X[i].age<<endl;
}
//===============
void main()
{
n=5; //Пусть число структур 5
X=new MyStruct [n]; //Выделяем память под пять структур для указателя X
for (int i=0;i<n;i++) input(i,X); //Вводим n структур по типу структуры Х
for (i=0;i<n;i++) output(i,X); //Выводим n структур типа X на экран
ofstream create(F,ios::binary); create.close(); //Это я для себя переписывал файл
/*ЗАПИСЫВАЕМ ВСЮ СТРУКТУРУ В БИНАРНЫЙ ФАЙЛ*/
ofstream out(F,ios::binary|ios::out); //Открыли файл для записи в бинарном режиме
out.write((char*)&X,sizeof X); //Записали в файл структуру X
out.close(); //Закрыли открытый файл
/*ЧИТАЕМ СТРУКТУРЫ ИЗ БИНАРНОГО ФАЙЛА*/
tempY=0;int count=0; //Инициализируем указатель на структуру и счетчик в нули
ifstream in(F,ios::binary|ios::in); //Открыли бинарный файл для чтения
in.read((char*)&tempY,sizeof tempY); //Считываем первый блок
while (in.cur!=in.eof())
{
in.read((char*)&tempY,sizeof tempY); //Считываем все блоки файла
count++;
}
cout<<count<<endl;
in.close(); //Закрываем файл
Y=new MyStruct [count]; //Выделяем память для новых структур
for (int i=0;i<n;i++) Y[i]=tempY[i]; //Переселяем ячейки
for (int i=0;i<n;i++) cout<<Y[i].Name<<" "<<Y[i].age<<endl; //Выводим все структуры на экран
// Освобождаем память
delete tempY[];
delete[]Y;
delete []X;
}
Если вас интересует эта тема, то значит вы должны быть уже хорошо знакомы с общим представлением и созданием простых программ. Я постараюсь сделать акцент именно на нужную часть, чтобы всё получилось покомпактнее.
Во-первых, я обращу внимание на то что я использую три структуры. Первая структура – это некоторая структура, данные из которой мы хотим записать в бинарный файл. При этом мы знаем, что структура будет динамическая. Вторая структура – это независимая от первой структуры, структура в которую мы хотим считать данные из бинарного файла. Про последнюю я расскажу ниже.
Перед тем как что-то записать в бинарный файл, нужно это самое создать, поэтому идут обычные шаги по созданию структуры. (у меня ввод в неё данных и вывод их на экран).
После того как написали стандартные и нужные функции, нужно записать данные файл. Если вы уже записывали файлы в бинарные файлы, то заметите, что в нашем случае нам не нужен цикл. Дело в том, что мы выделили память для структуры X и тем самым увеличили её размер.
PHP1
2 MyStruct *X //sizeof X = a;
X=new MyStruct [n]; //sizeof X=a*n;
Другими словами. Записать динамическую структуру в файл можно точно также как записать обычную переменную.
С записью в бинарный файл разобрались. Оказывается это не так сложно, но возникает вопрос по прочтению. Как прочитать из бинарного файла несколько структур.
Во избежание ошибок, указатель в который будем считывать структуры нужно инициализировать нулем. (или пустотой). При этом мы не обязательно знаем сколько структур в файл записано, значит хотим мы или нет, количество структур в бинарном файле придется посчитать. Инициализируем счетчик нулем. Теперь читаем данные из бинарника. Так как память под tempY не выделялась, то получается, что мы читаем данные из файла блоками, равными размеру структуры. Сколько таких блоков в файле мы не знаем и поэтому я использовал цикл с условием: “До тех пор пока курсор не встанет на позицию конца файла считывать информацию”. А с каждым новым прочтением блока, каждый прочитанный блок Дописывается в одну большую кучу, на начало которой указывает указатель TempY
Теперь, после того как мы считали всё в одну кучу, всю эту кучу данных по указателю TempY можно вывести на экран, используя счетчик count и цикл for . Кто-то может успокоиться и решить, что это все, что больше ничего не нужно. Но кто так подумает, тот совершит глобальную ошибку. Если вы вспомните, то увидите, что под TempY изначально не выделялось памяти, а значит любые полученные данные могут быть изгнаны из своих ячеек как нелегальные поселенцы. Такое выселение данных из ячеек может привести к непредсказуемым последствиям и поэтом всех надо переселить туда, откуда их ничто не выгонит. Для этого и использован третий указатель. Число структур известно и посчитано, значит выделяем под третий указатель столько памяти, сколько требуется и с помощью цикла переселяем данные динамических структур из небезопасной ячейки в безопасную
Мою идею легко довести до ума если уметь использовать динамические списки и в таком случае получите безопасное чтение структур из файла за один раз.