При вводе с клавиатуры и выводе на экран или в текстовый файл с каждым полем струк-
туры надо работать отдельно, как с обычной переменной. В приведенном примере данные вводятся в структуру b типа Book с клавиатуры и записываются в конец текстового файла
books.txt.
Book b;
FILE *fp;
printf("Автор ");
gets(b.author);
printf("Название книги ");
gets(b.title);
printf("Год издания, кол-во страниц ");
scanf("%d%d", &b.years, &b.pages);
fp = fopen("books.txt", "a"); // дописать в конец файла
fprintf(fp, "%s\n%s\n%d %d\n",
b.author, b.title, b.years, b.pages);
fclose (fp);
Работа с двоичным файлом
Структуры очень удобно записывать в двоичные файлы, поскольку можно за 1 раз прочи-
тать или записать сразу одну или даже несколько структур. Вспомним, что при чтении из дво-
ичного файла функции fread надо передать адрес нужной области памяти (куда записать про-
читанные данные), размер одного блока и количество таких блоков. Для того, чтобы не вычис-
лять размер структуры вручную (можно легко ошибиться), применяют оператор sizeof.
Book b;
int n;
|
|
FILE *fp;
fp = fopen("books.dat", "rb");
n = fread (&b, sizeof(Book), 1, fp);
if (n == 0) {
printf ("Ошибка при чтении из файла");
}
fclose (fp);
Можно было также вместо sizeof(Book) написать sizeof(b), поскольку запись b – это
как раз один экземпляр структуры Book. Функция fread возвращает число удачно прочитанных элементов (в нашем случае – структур). Поэтому если в примере переменная n равно нулю,чтение закончилось неудачно и надо вывести сообщение об ошибке.
Для записи структуры в двоичный файл используют функцию fwrite. Ее параметры – те
же, что и у fread. Пример ниже показывает добавление структуры в конец двоичного файла
books.dat.
Book b;
FILE *fp;
// здесь надо заполнить структуру
fp = fopen("books.dat ", "ab");
fwrite(&b, sizeof(Book), 1, fp);
fclose (fp);
Копирование
Пример. Пусть в памяти выделено две структуры одного типа и в одну из них записаны какие-то данные. Требуется скопировать все данные из первой структуры во вторую.
Пусть структуры имеют тип Book и называются b1 и b2. Существуют три способа решения этой задачи. Самый сложный – копирование каждого поля отдельно:
Book b1, b2;
// здесь заполняем структуру b1
strcpy (b2.author, b1.author);
strcpy (b2.title, b1.title);
b2.year = b1.year;
b2.pages = b1.pages;
Можно использовать специальную функцию memcpy, которая умеет копировать блоки памяти.Для ее использования надо подключить к программе заголовочный файл mem.h.
#include <mem.h>
Book b1, b2;
// здесь нужно заполнить структуру b1
memcpy(&b2, &b1, sizeof(Book)); // куда, откуда, сколько байт
Самый простой способ – третий. Достаточно просто написать
b2 = b1;
При этом программа скопирует одну структуру в другую «бит в бит». Зачем же рассказыватьпро остальные два способа? Только для того, чтобы понять, как это все работает, посколькунепонимание ведет к трудноуловимым ошибкам.
|
|
Массивы структур
Структуры служат для обработки большого объема информации, поэтому чаще всего в
программе используются массивы структур. Они объявляются так же, как обычно, но предварительно (выше) надо объявить саму структуру как новый тип данных.
Для обращения к полю структуры также используют точку, но теперь надо указать в квад-
ратных скобках еще номер нужной структуры, например
Book A[20];
...
A[12].pages = 50;
for (i = 0; i < 20; i ++) // цикл по всем структурам в массива
puts(A[i].title); // вывести название книги
Если вы работаете с двоичными файлами, то чтение и запись всего массива структур выполняется в одну строчку. Покажем приемы работы с двоичным файлом на примере.
Пример. В файле books.dat записаны структуры типа Book. Известно, что их не больше 100.
Требуется прочитать их в память, у всех книг установить 2009 год издания и записать обратнов тот же файл.
Поскольку по условию известно, что структур не больше 100, заранее выделяем в памяти массив на 100 структур.
Book b[100];
При чтении из файла пытаемся читать все 100 структур:
n = fread (&b[0], sizeof(Book), 100, fp);
Чтобы определить, сколько структур было в действительности прочитано, используем значение n, которое функция fread возвращает в качестве результата. Вот полная программа:
#include <stdio.h>
struct Book { // объявление нового типа данных
char author[40];
char title[80];
int year;
int pages;
};
Main()
{
Book b[100]; // выделение памяти под массив структур
int i, n;
FILE *fp;
fp = fopen("books.dat", "rb"); // читаем 100 структур
n = fread(&b[0], sizeof(Book), 100, fp); // прочитали n шт.
fclose (fp);
for (i = 0; i < n; i ++) // обрабатываем все, что прочитали
b[i].year = 2009;
fp = fopen("books.dat", "wb"); // записываем n шт.
fwrite (b, sizeof(Book), n, fp);
fclose (fp);
}