Описание и внутреннее представление файлов
Файлы отличаются друг от друга. Все файлы, хранящиеся в компьютере, имеют специальные атрибуты, т.е. специальные способы описания, позволяющие отличить один файл от другого: 1)имя; 2)размер; 3)дата и время; 4)значок.
У каждого файла есть имя - имя файла. Имя файла описывает его содержимое или подсказывает, для чего он может использоваться. Имя присваивается файлу при его создании. Это относится ко всем файлам.
Каждый файл имеет физический размер. Файл занимает некоторый объем памяти компьютера и некоторый объем дискового пространства.
В момент создания файла операционная система на него ставит печать с указанием даты и времени создания. Это позволяет сортировать файлы по дате и времени и таким образом наводить порядок в компьютере. Также отмечается дата и время обновления или изменения файла.
Каждый файл относится к определенному типу, тесно связанному со значком файла, который мы видим. Тип файла зависит от его содержимого. Каждая программа присваивает созданному документу определенный тип и соответствующий значок.
Размер файла измеряется в байтах, как и объем памяти.
Размер файла может составлять 0 байт, это значит, что файл существует, но ничего в себе не содержит. S Максимальный размер файла - 4 Гбайт. Но такие огромные файлы встречаются очень редко.
Встроенные часы компьютера нужны, в частности, для присвоения файлам времени и даты их создания. Этим объясняется то, как важно правильно настроить эти часы. Есть еще и дополнительные атрибуты для описания файлов, например системные файлы, скрытые файлы, файлы, предназначенные только для чтения, архивные файлы и т.д. Операционная система с этим разберется сама.
Каждый файл имеет уникальный индекс. Индекс содержит информацию, необходимую любому процессу для того, чтобы обратиться к файлу. Процессы обращаются к файлам, используя четко определенный набор системных вызовов и идентифицируя файл строкой символов, выступающих в качестве составного имени файла. Каждое составное имя однозначно определяет файл, благодаря чему ядро системы преобразует это имя в индекс файла. Индекс включает в себя таблицу адресов расположения информации файла на диске. Так как каждый блок на диске адресуется по своему номеру, в этой таблице хранится совокупность номеров дисковых блоков. В целях повышения гибкости ядро присоединяет к файлу по одному блоку, позволяя информации файла быть разбросанной по всей файловой системе. Но такая схема размещения усложняет задачу поиска данных. Таблица адресов содержит список номеров блоков, содержащих принадлежащую файлу информацию, однако простые вычисления показывают, что линейным списком блоков файла в индексе трудно управлять. Для того, чтобы небольшая структура индекса позволяла работать с большими файлами, таблица адресов дисковых блоков приводится в соответствие со структурой.
Текстовые и бинарные файлы
Файлы позволяют пользователю считывать большие объемы данных непосредственно с диска, не вводя их с клавиатуры. Существуют два основных типа файлов: текстовые и двоичные.
Текстовыми называются файлы, состоящие из любых символов. Они организуются по строкам, каждая из которых заканчивается символом «конца строки» . Конец самого файла обозначается символом «конца файла» . При записи информации в текстовый файл, просмотреть который можно с помощью любого текстового редактора, все данные преобразуются к символьному типу и хранятся в символьном виде.
В двоичных файлах информация считывается и записывается в виде блоков определенного размера, в которых могут храниться данные любого вида и структуры.
Для работы с файлами используются специальные типы данных, называемые потоками. Поток ifstreamслужит для работы с файлами в режиме чтения, а ifstream в режиме записи. Для работы с файлами в режимах, как записи, так и чтения служит поток ifstream.
В программах на C++ при работе с текстовыми файлами необходимо подключать библиотекиifstream и iostream.
Для того чтобы записывать данные в текстовый файл, необходимо: 1)описать переменную типа ofstream open ; 3)вывести информацию в файл; 4)обязательно закрыть файл.
Для считывания данных из текстового файла, необходимо:
1)описать переменную типа ifstream ; 2)открыть файл с помощью функции open ; 3)считать информацию из файла, при считывании каждой порции данных необходимо проверять, достигнут ли конец файла; 4)закрыть файл.
Следует отметить, что во всех рассмотренных выше примерах функция fopen() в режимах “r” и “w” открывает текстовый файл на чтение и запись соответственно. Это означает, что некоторые символы форматирования текста, например возврат каретки ‘\r’ не могут быть считаны как отдельные символы, их как бы ни существует в файле, но при этом они там есть. Это особенность текстового режима файла. Для более «тонкой» работы с содержимым файлов существует бинарный режим, который представляет содержимое файла как последовательность байтов, где все возможные управляющие коды являются просто числами. Именно в этом режиме возможно удаление или добавление управляющих символов недоступных в текстовом режиме. Для того чтобы открыть файл в бинарном режиме используется также функция fopen() с последним параметром равным “rb” и “wb” соответственно для чтения и записи.
Вся информация хранится в компьютере в виде 0 и 1, т. е. в двоичном виде. Двоичные файлы отличаются от текстовых только методами работы с ними. Например, если мы записываем в текстовый файл цифру «4», то она записывается как символ, и для ее хранения нужен один байт. Соответственно и размер файла будет равен одному байту. Текстовый файл, содержащий запись: «145687», будет иметь размер шесть байт.
Если же записать целое число 145 687 в двоичный файл, то он будет иметь размер четыре байта, так как именно столько необходимо для хранения данных типа int. То есть двоичные файлы более компактны и в некоторых случаях более удобны для обработки.
Для того чтобы открыть двоичный файл, необходимо задать режим доступа ios::binary (в некоторых компиляторах C++ - ios::bin).
Для создания выходного файла создают объект:
ofstream outBinFile("out.bin", ios::out | ios::binary);
/* создание объекта класса ofstream out. bin
if (! out_f і 1) //стандартная проверка
Запись данных происходит с помощью метода write (), который имеет два параметра: первый - указатель на начало (адрес начала) записываемых данных, второй - количество записываемых байтов. При этом указатель необходимо явно преобразовать к типу char.
Пример 1. Записать в двоичный файл переменные различного типа:
ofstream outBinFile("test.bin", ios::out I
ios: :binary) ; /^создание объекта класса of stream и попытка связать его с файлом test. bin в режиме записи двоичного файла */
int а - 145687; //объявление целой переменной а
outBinFi le. write ((char*) &а, sizeof (а)) ; /^запись в файл
переменной а как потока байтов, т. е. запись в файл внутреннего представления целой переменной а */ float х - 123.25; // объявление вещественной переменной х
outBinFile .write ((char*) &х, sizeof (х)) ; /^запись в файл
переменной х как потока байтов, т. е. запись в файл внутреннего представления целой переменной х*/
//определение символьной переменной с и инициализация ее символом g outBinFile.write((char*)&c, sizeof(c));
//запись символа g в файл
outBinFile.close(); return 0;
Если открыть содержимое файла test .bin текстовым редактором, то он будет иметь вид:
а размер файла составит 9 байт.
Для того чтобы открыть существующий двоичный файл для чтения, нужно создать объект:
ifstream inpBinFile("inp.bin", ios::in I ios::binary);
/* используем дизъюнкцию флагов, указывающую на то что файл открывается на чтение в двоичном виде*/
if (! inpBinFile)
coutДля чтения данных используем функцию read(), имеющую аналогичные функции write() параметры.
#include using namespace std; int main()
ifstream inpBinFile("test.bin", ios::in I
ios: : binary) ; //открываем файл на чтение в двоичном виде
int а; float х; char с = "g";
inpBinFile.read((char*)&a, sizeof(a));
//читаем целочисленную переменную inpBinFile.read((char*)&x, sizeof(x));
//читаем вещественную переменную inpBinFile.read((char*)&c, sizeof (c));
//читаем символьную переменную
inpBinFile.close(); cout
Результат работы программы:
а = 145687 х = 123.25 с = g
Обратите внимание, что при использовании функции write и read не происходит никакого преобразования информации. В файл записывается и считывается внутреннее представление данных. Именно поэтому две предыдущие программы дали правильный результат.
В отличие от текстовых файлов, работа с пользовательскими типами данных с использованием двоичных файлов ничем не отличается от стандартных типов данных. Аналогично используются методы write() и read(). Программисту только остается указать адрес записываемого участка памяти и количество записываемых байтов, учтя при этом, что никакого преобразования данных не происходит, записывается и считывается только внутреннее представление информации.
Также при работе с двоичными файлами могут использоваться методы seekg(), tellg(), seekp(), tellp().
Пример 3. Написать программу, которая записывает сведения о группе туристов в двоичный файл.
fstream BinFile("ankety.bin", ios::in I ios::out | ios::binary);
Anketa Gruppa = ; for (int i = 0; i
BinFile.write((char*)&Gruppa[i], sizeof(Anketa)); BinFile.close(); return 0;
Пример 4. В файле «ankety.bin» содержатся данные о группе туристов, необходимо считать их и вывести на экран.
#include using namespace std; struct Anketa {
char name; int age;
структурного типа данных Anketa на экран*/
ostream& operator
fstream BinFile("ankety.bin", ios::in | ios::out | ios::binary); if (!BinFile)
for (int i = 0; i
//сразу читаем все байты, занимаемые переменной типа Anketa BinFile.read((char*)&Gruppa[i], sizeof(Anketa));
BinFile.close(); return 0;
Результат работы программы:
Ivanov, 23 Sidorov, 21 Petrov,22
Для продолжения нажмите любую клавишу. . .
Постоянно пользоваться методами write() и read() неудобно, гораздо приятнее иметь возможность пользоваться операциями «>» по аналогии с текстовыми файлами. Приведем пример реализации своего класса для работы с двоичными файлами.
using namespace std;
struct Anketa //объявляем структуру для хранения информации
/*перегрузка операции вставки в поток для вывода пользовательского
структурного типа данных Anketa на экран*/
ostream& operator
class outBinaryFile: public of stream /^определяем свой класс для работы с выходными бинарными файлами. Порождаем его от класса работы с выходными файловыми потоками*/
/*при описании конструктора порожденного класса не забываем вызвать конструктор базового, передав ему необходимые параметры*/
outBinaryFile(char* name) : ofstream(name, ios::out I ios::binary)
//перегружаем необходимые операции как методы класса outBinaryFile& operator
write((char*)&chislo, sizeof(chislo)); return *this;
outBinaryFile& operator
write((char*)&ank, sizeof(ank)); return *this;
class inpBinaryFile: public if stream /* определяем свои класс для работы с входными бинарными файлами. Порождаем его от класса работы с входными файловыми потоками*/
inpBinaryFile(char* name) : ifstream(name, ios::in I ios::binary)
/*вызова конструктора базового класса с необходимыми параметрами,
достаточно для конструктора порожденного класса */
//перегружаем необходимые операции
inpBinaryFile& operator >> (int& chislo)
read((char*)&chislo, sizeof(chislo)); return *this;
inpBinaryFile& operator >> (Anketa& ank)
read((char*)&ank, sizeof(ank)); return *this;
int а = 111, b = 112; outBinaryFile outFile("dannye.bin");
//открываем файл на чтение
inpBinaryFile inpFile("dannye.bin"); if (!inpFile)
for (int і = 0; i
inpFile >> a; //читаем анкету из файла
cout //и выводим ее на экран
inpFile >> anketa; cout
Результат работы программы:
Kolya, 1990, 582-78-95.
Для продолжения нажмите любую клавишу. . .
1. Можно ли в программе использовать операцию?
ios::in I ios::out
З.Что будет выведено на экран в результате выполнения следующего кода?
inputFile.get(с);
next - inputFile.peek();
if (next == EOF)
Контрольные вопросы
В приведенном выше примере самым "длинным" является вариант "b ": для него требуется 23 байта (21 байт для строки и 2 байта для целого числа). Для вариантов "n " и "m " требуется 4 и 5 байт соответственно (см. таблицу).
name, publisher item Вариантная часть
Бинарные файлы хранят информацию в том виде, в каком она представлена в памяти компьютера, и потому неудобны для человека. Заглянув в такой файл, невозможно понять, что в нем записано; его нельзя создавать или исправлять вручную - в каком-нибудь текстовом редакторе - и т.п. Однако все эти неудобства компенсируются скоростью работы с данными.
Кроме того, текстовые файлы относятся к структурам последовательного доступа, а бинарные - прямого. Это означает, что в любой момент времени можно обратиться к любому, а не только к текущему элементубинарного файла .
Переменные структурированных типов данных (кроме строкового) невозможно считать из текстового файла. Например, если нужно ввести из текстового файла данные для наполнения записи toy информацией об имеющихся в продаже игрушках (название товара, цена товара и возрастной диапазон, для которого игрушка предназначена):
age: set of 0..18; {в файле задано границами}
то придется написать следующий код:
c: char; i,j,min,max: integer;
a: array of toy;
begin assign(f,input); reset(f);
for i:=1 to 100 do if not eof(f)
then with a[i] do
begin readln(f,name,price,min,max); age:=;
for j:= min to max do age:=age+[j];
Как видим, такое поэлементное считывание весьма неудобно и трудоемко.
Выход из этой ситуации предлагают типизированные файлы - их элементы могут относиться к любому базовому или структурированному типу данных. Единственное ограничение: все элементы должны быть одного и того же типа. Это кажущееся неудобство является
непременным условием для организации прямого доступа к элементам бинарного файла : как и в случае массивов, если точно известна длина каждого компонента структуры, то адрес любого компонента может быть вычислен по очень простой формуле:
<начало_структуры> + <номер_компонента>*<длина_компонента>
В разделе var файловые переменные, предназначенные для работы стипизированными файлами , описываются следующим образом:
var <файловая_перем>: file of <тип_элементов_файла>;
Никакая файловая переменная не может быть задана константой.
С этого момента и до конца раздела под словом "файл" мы будем подразумевать "бинарный типизированный файл " (разумеется, если специально не оговорено иное).
Команда assign(f,"<имя_файла>"); служит для установления связи между файловой переменнойf и именем того файла, за работу с которым эта переменная будет отвечать.
Строка "<имя_файла> " может содержать полный путь к файлу. Если путь не указан, файл считается расположенным в той же директории, что и исполняемый модуль программы.
В зависимости от того, какие действия ваша программа собирается производить с открываемым файлом, возможно двоякое его открытие:
reset(f); - открытие файла для считывания из него информации и одновременно длязаписи в него (если такого файла не существует, попытка открытия вызовет ошибку). Эта же команда служит для возвращения указателя на начало файла;
rewrite(f); - открытие файла длязаписи в него информации; если такого файла не существует, он будет создан; если файл с таким именем уже есть, вся содержавшаяся в нем ранее информация исчезнет.
Закрываются типизированные файлы процедуройclose(f) , общей для всех типов файлов.
Чтение из файла, открытого для считывания, производится с помощью команды read() . В скобках сначала указывается имя файловой переменной, а затем - список ввода1) :
Вводить из файла можно только переменные соответствующего объявлению типа, но этот тип данных может быть и структурированным. Cкажем, если вернуться к примеру, приведенному в начале п. "Типизированные файлы ", то станет очевидным, что использованиетипизированного файла вместо текстового позволит значительно сократить текст программы:
type toy = record name: string; price: real;
age: set of 0..18; {задано границами}
var f: file of toy;
a: array of toy; begin
assign(f,input);
for i:=1 to 100 do
if not eof(f) then read(f,a[i]); close(f);
Уже знакомая нам функция eof(f:file):boolean сообщает о достигнутом конце файла. Все остальные функции "поиска конца" (eoln() ,seekeof() иseekeoln() ), свойственные текстовым файлам, нельзя применять к файламтипизированным .
Зато существуют специальные подпрограммы, которые позволяют работать с типизированными файлами как со структурами прямого доступа:
1. Функция filepos(f:file):longint сообщит текущее положение указателя в файлеf . Если он указывает на самый конец файла, содержащегоN элементов, то эта функция выдаст результатN . Это легко объяснимо: элементы файла нумеруются начиная с нуля, поэтому последний элемент имеет номер N-1 . А номерN принадлежит, таким образом, "несуществующему" элементу - признаку конца файла.
2. Функция filesize(f:file):longint вычислит длину файлаf .
3. Процедура seek(f:file,n:longint) передвинет указатель в файлеf на началозаписи с номеромN . Если окажется, чтоn больше фактической длины файла, то указатель будет передвинут и за реальный конец файла.
4. Процедура truncate(f:file) обрежет "хвост" файлаf : все элементы начиная с текущего и до конца файла будут из него удалены. На самом же деле произойдет лишь переписывание признака "конец файла" в то место, куда указывал указатель, а физически "отрезанные" значения останутся на прежних местах - просто они станут "бесхозными".
Сохранять переменные в файл, открытый для записи , можно при помощи командыwrite() . Так же как и в случае считывания, первой указывается файловая переменная, а за ней - список вывода:
write(f,a,b,c); - записать в файлf (предварительно открытый длязаписи командамиrewrite(f) илиreset(f) ) переменныеa ,b ,c .
Выводить в типизированный файл можно только переменные соответствующего описанию типа данных. Неименованные и нетипизированные константы нельзя выводить в
типизированный файл.
Типизированные файлы рассматриваются как структуры одновременно и прямого, и последовательного доступа. Это означает, чтозапись возможна не только в самый конец файла, но и в любой другой его элемент. Записываемое значение заместит предыдущее значение в этом элементе (старое значение будет "затерто").
Например, если нужно заместить пятый элемент файла значением, хранящимся в переменной а , то следует написать следующий отрывок программы:
seek(f,5); {указатель будет установлен на начало 5-го элемента}
write(f,a); {указатель будет установлен на начало 6-го элемента}
У многих часто возникает вопрос о том, как открыть бинарный файл. Этот документ представляет собой любой файл, который находится на персональном компьютере. Все данные, которые находятся на компьютерах и носителях, связанных с ним, записываются обычно в битах. Именно от этого слова и произошло название. Если в качестве сравнения привести простой текстовый файл, то проблем с его чтением не возникнет. Для этого достаточно иметь на компьютере обычный редактор, сойдет даже блокнот. Для того чтобы открыть бинарный файл, простым блокнотом обойтись не получится. И если говорить о том, что информация текстовых файлов зашифровывается все теми же битами, то обычно, когда говорят о чтении бинарных файлов, подразумевают исполняемые документы.
Инструкция к действию
Во-первых, на жесткий диск персонального компьютера необходимо установить программное средство под названием HexEditor, которое представляет собой простой редактор для бинарных файлов. После установки программу следует открыть, щелкнув для этого два раза кнопкой мыши по иконке. Это средство позволит проводить чтение бинарного файла в реальном режиме. При этом можно изменять данные в файле, добавлять свою информацию и т.д. Для того чтобы работать в данном редакторе и изменять бинарный файл, необходимо обладать хоть какими-нибудь знаниями в этой сфере деятельности.
Во-вторых, необходимо ознакомиться с Главное ее окно не имеет больших отличий от окна обычного редактора. Те же самые кнопки, то же меню, тело документа, закладки и строки состояния. Открыть интересующий файл можно через вкладку File или через специальную кнопку, которая располагается на в программе. После этого можно будет увидеть исполняемый файл, который предстанет в виде цифр и букв. Не стоит путать те символы, с помощью которых представлен бинарный файл, и те, которые имеет обычный редактор. В том случае, если будет принято решение об удалении или изменении какого-либо участка документа, следует понимать, что исчезнет или изменится какая-либо его часть.
В-третьих, с помощью программы можно попробовать изменить какой-либо участок документа. Как было сказано ранее, программное средство показывает файл в таком виде, который улучшает способы поиска необходимой части документа. К тому же программа обладает достаточно гибкой настройкой. С ее помощью можно изменить графическое отображение двоичного кода, который имеет бинарный файл. В том случае, если в какой-то участок файла будут внесены неправильные данные, то он впоследствии может либо полностью перестать работать, либо начнет работать не совсем корректно. В любом случае ввод таких данных вызовет изменения как в операционной системе, так и непосредственно в самом персональном компьютере.
В-четвертых, после изменения, удаления или добавления определенных данных в файле следует сохранить результат своей работы. В том случае, если достаточного опыта в редактировании файлов у вас нет, то следует быть готовым к не совсем приятным последствиям. Например, документ может перестать работать после изменения данных. До тех пор, пока вы не начнете хорошо разбираться в этом вопросе, будет испорчено очень много копий файлов. Если вы не уверены в своих возможностях, то изменять данные самостоятельно не стоит, особенно в тех ситуациях, когда исправить необходимо бинарный файл su.
Теги: Бинарные файлы, fseek, ftell, fpos, fread, fwrite
Т екстовые файлы хранят данные в виде текста (sic!). Это значит, что если, например, мы записываем целое число 12345678 в файл, то записывается 8 символов, а это 8 байт данных, несмотря на то, что число помещается в целый тип. Кроме того, вывод и ввод данных является форматированным, то есть каждый раз, когда мы считываем число из файла или записываем в файл происходит трансформация числа в строку или обратно. Это затратные операции, которых можно избежать.
Текстовые файлы позволяют хранить информацию в виде, понятном для человека. Можно, однако, хранить данные непосредственно в бинарном виде. Для этих целей используются бинарные файлы.
#include
Выполните программу и посмотрите содержимое файла output.bin. Число, которое ввёл пользователь записывается в файл непосредственно в бинарном виде. Можете открыть файл в любом редакторе, поддерживающем представление в шестнадцатеричном виде (Total Commander, Far) и убедиться в этом.
Запись в файл осуществляется с помощью функции
Size_t fwrite (const void * ptr, size_t size, size_t count, FILE * stream);
Функция возвращает число удачно записанных элементов. В качестве аргументов принимает указатель на массив, размер одного элемента, число элементов и указатель на файловый поток. Вместо массив, конечно, может быть передан любой объект.
Запись в бинарный файл объекта похожа на его отображение: берутся данные из оперативной памяти и пишутся как есть. Для считывания используется функция fread
Size_t fread (void * ptr, size_t size, size_t count, FILE * stream);
Функция возвращает число удачно прочитанных элементов, которые помещаются по адресу ptr. Всего считывается count элементов по size байт. Давайте теперь считаем наше число обратно в переменную.
#include
Одной из важных функций для работы с бинарными файлами является функция fseek
Int fseek (FILE * stream, long int offset, int origin);
Эта функция устанавливает указатель позиции, ассоциированный с потоком, на новое положение. Индикатор позиции указывает, на каком месте в файле мы остановились.
Когда мы открываем файл, позиция равна 0. Каждый раз, записывая байт данных, указатель позиции сдвигается на единицу вперёд.
fseek принимает в качестве аргументов указатель на поток и сдвиг в offset байт относительно origin. origin может принимать три значения
В случае удачной работы функция возвращает 0.
Дополним наш старый пример: запишем число, затем сдвинемся указатель на начало файла и прочитаем его.
#include
Вместо этого можно также использовать функцию rewind, которая перемещает индикатор позиции в начало.
В си определён специальный тип fpos_t, который используется для хранения позиции индикатора позиции в файле.
Функция
Int fgetpos (FILE * stream, fpos_t * pos);
используется для того, чтобы назначить переменной pos текущее положение. Функция
Int fsetpos (FILE * stream, const fpos_t * pos);
используется для перевода указателя в позицию, которая хранится в переменной pos. Обе функции в случае удачного завершения возвращают ноль.
Long int ftell (FILE * stream);
возвращает текущее положение индикатора относительно начала файла. Для бинарных файлов - это число байт, для текстовых не определено (если текстовый файл состоит из однобайтовых символов, то также число байт).
Рассмотрим пример: пользователь вводит числа. Первые 4 байта файла: целое, которое обозначает, сколько чисел было введено. После того, как пользователь прекращает вводить числа, мы перемещаемся в начало файла и записываем туда число введённых элементов.
#include
Вторая программа сначала считывает количество записанных чисел, а потом считывает и выводит числа по порядку.
#include
1. Имеется бинарный файл размером 10*sizeof(int) байт. Пользователь вводит номер ячейки, после чего в неё записывает число. После каждой операции выводятся все числа. Сначала пытаемся открыть файл в режиме чтения и записи. Если это не удаётся, то пробуем создать файл, если удаётся создать файл, то повторяем попытку открыть файл для чтения и записи.
#include
2. Пишем слова в бинарный файл. Формат такой - сначало число букв, потом само слово без нулевого символа. Ели длина слова равна нулю, то больше слов нет. Сначала запрашиваем слова у пользователя, потом считываем обратно.
#include
3. Задача - считать данные из текстового файла и записать их в бинарный. Для решения зачи создадим функцию обёртку. Она будет принимать имя файла, режим доступа, функцию, которую необходимо выполнить, если файл был удачно открыт и аргументы этой функции. Так как аргументов может быть много и они могут быть разного типа, то их можно передавать в качестве указателя на структуру. После выполнения функции файл закрывается. Таким образом, нет необходимости думать об освобождении ресурсов.
#include
4. Функция saveInt32Array позволяет сохранить массив типа int32_t в файл. Обратная ей loadInt32Array считывает массив обратно. Функция loadInt32Array сначала инициализирует переданный ей массив, поэтому мы должны передавать указатель на указатель; кроме того, она записывает считанный размер массива в переданный параметр size, из-за чего он передаётся как указатель.
#include
5. Создание таблицы поиска. Для ускорения работы программы вместо вычисления функции можно произвести сначала вычисление значений функции на интервале с определённой точностью, после чего брать значения уже из таблицы. Программа сначала производит табулирование функции с заданными параметрами и сохраняет его в файл, затем подгружает предвычисленный массив, который уже используется для определения значений. В этой программе все функции возвращают переменную типа Result, которая хранит номер ошибки. Если функция отработала без проблем, то она возвращает Ok (0).
#define _CRT_SECURE_NO_WARNINGS
//Да, это теперь обязательно добавлять, иначе не заработает
#include
6. У нас имеются две структуры. Первая PersonKey хранит логин, пароль, id пользователя и поле offset. Вторая структура PersonInfo хранит имя и фамилию пользователя и его возраст. Первые структуры записываются в бинарный файл keys.bin, вторые структуры в бинарный файл values.bin. Поле offset определяет положение соответствующей информации о пользователе во втором файле. Таким образом, получив PersonKey из первого файла, по полю offset можно извлечь из второго файла связанную с данным ключом информацию.
Зачем так делать? Это выгодно в том случае, если структура PersonInfo имеет большой размер. Извлекать массив маленьких структур из файла не накладно, а когда нам понадобится большая структура, её можно извлечь по уже известному адресу в файле.
#define _CRT_SECURE_NO_WARNINGS
#include