money = &jones[0];
Поскольку money указывает на первый элемент массива jones, то money [0] — это еще одно имя первого элемента массива. Аналогично, money [1] — второй элемент массива. Каждый элемент является структурой funds, поэтому для каждого из них можно применять операцию точки (.), чтобы обращаться к членам структуры.
Ниже перечислены основные аспекты.
• Имя массива можно использовать для передачи в функцию адреса первой структуры массива.
• Для доступа к последующим структурам массива можно применять запись с квадратными скобками. Обратите внимание, что вызов функции
sum(&jones[0], N)
приведет к таким же результатам, как и в случае указания имени массива, поскольку jones и &jones [0] — это один и тот же адрес. Использование имени массива представляет собой просто косвенный способ передачи адреса структуры.
• Из-за того, что функция sum() не должна изменять исходные данные, в ней применяется квалификатор const из ANSI С.
Сохранение содержимого структур в файле
Поскольку структуры могут содержать самую разнообразную информацию, они являются важными инструментами для построения баз данных. Например, структуру можно использовать для хранения информации о служащих компании или об автомобильных запчастях. В итоге неизбежно возникнет необходимость сохранять эту
Структуры и другие формы данных 597
информацию в файле и извлекать ее из файла. Файл базы данных может содержать произвольное количество таких объектов данных. Полный набор информации, хранящейся в структуре, называется записью, а отдельные члены структуры — полями. Давайте рассмотрим эту тему более подробно.
Вероятно наиболее очевидный, но и наименее эффективный способ сохранения записи предполагает применение функции fprintf().
В качестве примера вспомним структуру book, определенную в листинге 14.1:
#define MAXTITL 40
#define MAXAUTL 40
struct book {
char title[MAXTITL]; char author[MAXAUTL]; float value;
};
Если pbooks идентифицирует файловый поток, то информацию из переменной primer типа struct book можно было бы сохранить с помощью следующего оператора:
fprintf(pbooks, "%s %s %.2f\n", primer.title,
primer.author, primer.value);
Такой подход становится громоздким для структур, которые имеют, скажем, 30 членов. Кроме того, возникает проблема извлечения, т.к. программе необходим какой- то способ выяснения, где одно поле заканчивается, а другое начинается. Проблему можно решить, используя формат с полями фиксированного размера (например, "%39s%39s%8.2f"), но громоздкость никуда не девается.
Более приемлемое решение заключается в применении функций fread() и fwrite() для чтения и записи единиц с размером структуры. Вспомните, что эти функции производят чтение и запись с использованием такого же двоичного представления, как и программа. Например, вызов
fwrite(sprimer, sizeof (struct book), 1, pbooks);
переходит к начальному адресу структуры primer и копирует все байты этой структуры в файл, ассоциированный с pbooks. Выражение sizeof (struct book) сообщает функции размер блока, подлежащего копированию, а 1 означает, что должен копироваться только один блок. Функция fread() с теми же аргументами копирует порцию данных размером со структуру из файла в область памяти, на которую указывает &pnmer. Короче говоря, эти функции читают и записывают за один раз полную запись, а не поле.
Один из недостатков хранения данных в двоичном представлении связан с тем, что в разных системах могут применяться отличающиеся двоичные представления, поэтому файл данных может оказаться непереносимым. Даже в одной и той же системе разные настройки компилятора могут в результате приводить к получению разных двоичных представлений.
Пример сохранения структуры
Чтобы продемонстрировать использование этих функций в программе, мы модифицировали код из листинга 14.2, чтобы сведения о книгах сохранялись в файле по имени book.dat. Если файл уже существует, программа отображает его текущее содержимое и затем позволяет добавить в файл новые данные. Новая версия программы показана в листинге 14.14. (Если вы имеете дело с Borland C/C++, ознакомьтесь с врезкой “Borland С и плавающая запятая” ранее в главе.)

Структуры и другие формы данных 599

Мы сначала посмотрим на результаты двух пробных запусков и затем обсудим основные особенности программы.
$ booksave
Читать дальше