Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Ниже перечислены основные аспекты.
• Имя массива можно использовать для передачи в функцию адреса первой структуры массива.
• Для доступа к последующим структурам массива можно применять запись с квадратными скобками. Обратите внимание, что вызов функции
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
Введ$ите названия новых книг.
Нажмите [enter] в начале строки, чтобы закончить ввод.
Metric Merriment
Теперь введите имя автора.
Polly Poetica Теперь введите цену.
18.99
Введите название следующей книги.
Deadly Farce
Теперь введите имя автора.
Dudley Forse Теперь введите цену.
15.99
Введите название следующей книги.
[enter]
Каталог ваших книг:
Metric Merriment авторства Polly Poetica: $18.99 Deadly Farce авторства Dudley Forse: $15.99 Программа завершена.
600 глава 14
$ booksave
Текущее содержимое файла book.dat:
Metric Merriment авторства Polly Poetica: $18.99 Deadly Farce авторства Dudley Forse: $15.99 Введите названия новых книг.
The Third Jar
Теперь введите имя автора.
Nellie Nostrum Теперь введите цену.
22.99
Введите название следующей книги.
[enter]
Каталог ваших книг:
Metric Merriment авторства Polly Poetica: $18.99 Deadly Farce авторства Dudley Forse: $15.99 The Third Jar авторства Nellie Nostrum: $22.99 Программа завершена.
$
При следующем запуске программы booksave.с все три книги будут отображены как текущие записи файла book.dat.
Анализ программы
Для начала файл открывается в режиме "а+b". Часть а+ позволяет программе читать весь файл и добавлять данные в конец файла. Часть b — это принятый в ANSI способ для сообщения о том, что программа будет применять двоичный файловый формат. Для систем Unix, которые не принимают частьb, ее можно опустить, поскольку Unix в любом случае имеется только одна форма файлов. Для реализаций С, предшествующих ANSI, может понадобиться найти локальный эквивалент b.
Двоичный режим был выбран из-за того, что функции fread() и fwrite() предназначены для работы с двоичными файлами. Действительно, некоторое содержимое структуры является текстовым, однако член value — нет. Если вы воспользуетесь текстовым редактором для просмотра файла book.dat, то текстовая часть будет отображаться нормально, но числовая часть окажется нечитабельной и может даже стать причиной выдачи предупреждений.
Вызов rewind() обеспечивает установку указателя позиции в файле на начало файла, приводя его в состояние готовности к первому чтению.
Первый цикл while читает одну структуру за раз в массив структур, останавливаясь при заполнении этого массива либо при исчерпании данных в файле. Переменная filecount отслуживает количество прочитанных структур.
Следующий цикл while запрашивает и получает пользовательский ввод. Как и в листинге 14.2, этот цикл прекращается, когда массив заполнен или пользователь нажал клавишу в начале строки. Обратите внимание, что переменная count начинается со значения, которое она получила по окончании предыдущего цикла. Это приводит к добавлению новых записей в конец массива.
Читать дальшеИнтервал:
Закладка: