При выполнении операций чтения - записи в файле требуется иногда перемещать указатель текущей позиции файла, например, при переходе от чтения к записи или наоборот (когда файл открыт в комбинированных режимах). Для перемещения указателя существуют специальные функции.
Функция для установки указателя текущей позиции в заданное положение:
int fseek(FILE * stream, long offset, int fromwhere);
параметры: stream – указатель на структуру FILE, offset – смещение в байтах указателя текущей позиции от позиции, заданной следующим параметром, fromwhere – возможные значения заданы константами: SEEK_SET – начало файла, SEEK_CUR – текущее положение указателя, SEEK_END – конец файла. Возвращаемое значение: 0, если функция нормально завершает свою работу, не 0 – в случае ошибки.
Функция для установки указателя текущей позиции в начало файла:
void rewind(FILE * stream);
параметр stream – указатель на структуру FILE.
Функция для получения текущего положения указателя позиции файла (смещение в байтах от начала файла):
long ftell(FILE * stream);
параметр stream – указатель на структуру FILE, функция возвращает текущее положение указателя.
Функции для сброса буферов ввода- вывода
Иногда требуется явно проводить сброс буфера ввода- вывода. В частности, эта операция обязательна при переходе от операции записи к операции чтения (при открытии файла в комбинированном режиме), чтобы записанные данные гарантированно оказались записаны в файле.
Функция сброса заданного буфера ввода- вывода:
int fflush(FILE * stream);
параметр stream – указатель на структуру FILE, функция возвращает 0 – в случае нормального завершения и EOF – в случае ошибки.
Функция сброса всех буферов ввода- вывода:
int flushall();
функция возвращает количество открытых потоков (входных и выходных), в случае ошибки возвращаемое значение не определено.
Задачи и порядок выполнения работы
В лабораторной работе необходимо разработать два приложения. В первом приложении исходные данные вводятся с клавиатуры (количество объектов, заданных структурным типом, заранее неизвестно) и сохраняются в файле. Во втором приложении данные, сохраненные в первом приложении в файле, читаются из файла и выводятся на экран. В зависимости от варианта данные могут сохраняться в файле как в текстовом, так и в двоичном режиме.
Пример выполнения работы
Условие задачи:
Структура книга (поля: ФИО автора, название, издательство, год издания, число страниц). Создается массив книг размерности n. Сохраняется в файле и читается из файла. Файл открывается в двоичном режиме.
Для решения задач в среде Microsoft Visual Studio 2013 были созданы стандартные консольные приложения (проект типа Win32 Console Application) с установленным свойством «пустой проект» (Empty project). В каждый из проектов добавлен файл с расширением .cpp, исходные коды которых приведены ниже.
Листинг программы с комментариями для записи в файл:
#include <stdio.h>
#include <stdlib.h>
struct BOOK // Структура - книга
{
char Author[64];
char Title[128];
char Firm[64];
int year, page;
};
int main(int argc, char* argv[])
{
int n; // Переменная, задающая число элементов массива
BOOK *pBook; // Указатель на массив структур
printf("n="); scanf_s("%d", &n); // Ввод числа книг
pBook = new BOOK[n]; // Выделяем память под массив структур (книг)
for (int i = 0; i<n; i++) // Цикл ввода данных о книгах с клавиатуры
{
printf("Book N=%d:\n", i + 1);
printf("Author: ");
fflush(stdin); gets_s(pBook[i].Author, 63);
printf("Title: ");
fflush(stdin); gets_s(pBook[i].Title, 127);
printf("Firm: ");
fflush(stdin); gets_s(pBook[i].Firm, 63);
printf("year: "); scanf_s("%d", &pBook[i].year);
printf("page: "); scanf_s("%d", &pBook[i].page);
}
FILE *pF;
fopen_s(&pF, "MyBook.dat", "wb"); // Открываем файл для записи в двоичном режиме
fwrite(&n, sizeof(int), 1, pF); // Записываем в файл число элементов массива
fwrite(pBook, sizeof(BOOK), n, pF); // Записываем в файл массив книг
fclose(pF); // Закрываем файл
system("pause"); // Останавливаем программу, ждем нажатия любой клавиши
return 0;
}
Листинг программы с комментариями для чтения из файла:
#include <stdio.h>
#include <stdlib.h>
struct BOOK // Структура - книга
{
char Author[64];
char Title[128];
char Firm[64];
int year, page;
};
int main(int argc, char* argv[])
{
int n; // Переменная, задающая число элементов массива
BOOK *pBook; // Указатель на массив структур
FILE *pF;
fopen_s(&pF, "MyBook.dat", "rb");// Открываем файл для чтения в двоичном режиме
if (pF == 0) // Ошибка открытия файла, например, файл не существует
{
printf("Error, file not found");
return 1;
}
fread(&n, sizeof(int), 1, pF); // Читаем из файла число элементов массива
pBook = new BOOK[n]; // Выделяем память под массив структур (книг)
fread(pBook, sizeof(BOOK), n, pF); // Читаем из файла массив книг
fclose(pF); // Закрываем файл
for (int i = 0; i<n; i++) // Цикл вывода данных о книгах на экран
printf("%s. %s. %s, %d. - %d.\n", pBook[i].Author,
pBook[i].Title, pBook[i].Firm, pBook[i].year,
pBook[i].page);
system("pause"); // Останавливаем программу до нажатия любой клавиши
return 0;
}