Блоковый ввод-вывод
Функции блокового ввода-вывода позволяют выполнять перенос между файлом и программой фиксированных блоков байтов, или записей (records). Блок – группа расположенных подряд байтов, не имеющих никаких специальных разделителей (форматирующих знаков).
Пусть описаны переменные:
void *ptr; int size, n; FILE *fp;
Блоковый ввод выполняет функция вида
int fread (ptr, size, n, fp);
которая считывает n элементов размером size байт каждый из открытого файла с указателем fp в область памяти, определяемую указателем ptr. В случае успеха возвращает число прочитанных элементов (не байтов!), иначе возвращается EOF.
Блоковый вывод выполняет функция вида:
int fwrite (ptr, size, n, fp);
которая записывает n элементов размером size байт каждый из области памяти, определяемой указателем ptr, в открытый файл с указателем fp. В случае успеха возвращает число записанных элементов (не байтов!), иначе возвращается EOF.
За одно обращение к таким функциям переносится блок размером n*size байт. Для того чтобы рассматриваемые функции не порождали неожиданностей при переносе данных, файлы следует открывать в двоичном режиме для подавления трансляции пары символов CR LF в символ ‘\n’ (новая строка) при чтении и символа ‘\n’ в символы CR LF (перевод каретки, перевод строки) при записи.
Пример. Требуется ввести данные об успеваемости студентов в двоичный файл, отсортировать в файле эти данные по убыванию среднего балла и вывести на экран списки студентов из файла до и после сортировки. Для позиционирования маркера записи-чтения файла используется функция fseek().
Программа:
# include <stdio.h>
# include <conio.h>
# include <alloc.h> /* для выделения памати под name */
# define kst 3 /* количество студентов */
# define kb 2 /* количество баллов в сессию */
typedef struct { /* описание типа структуры */
char name[20]; /* массив для Фамилии И.О. */
int ball [kb]; /* массив баллов в сессию */
float sb; /* средний балл */
} student; /* тип структуры */
FILE *fst; /* указатель потока */
void OUTSUD (FILE *fst, int kstud, int sizest); /* прототип функции ввода */
int main ( ) /* главная функция */
{
student st, stb; /* структурные переменные */
int i, j, k, sizest; /* переменные циклов и размера структуры */
float sum; /* сумматор */
clrscr ( ); /* очистка экрана */
sizest = sizeof (student); /* размер структуры в байтах */
/* Открываем двоичный файл для чтения и записи: */
if (( fst = fopen (“c:\\tc\\myfiles\\stud.dat”, “w+b”)) == null)
{ perror (“Ошибка открытия файла”);
return 1; /* аварийное завершение программы */
}
printf (“ Открыт файл fst для ввода данных о %d студентах”, kst);
for (i=0; i < kst ; i++) /* цикл по студентам */
{ printf (“\nСтудент %d: “, i+1);
fflush (stdin); /* очистка входного буфера */
gets (st.name); /* ввод Фамилии И.О. */
printf (“Ввод %d баллов от 3 до 5): “, kb);
sum = 0;
for (j=0; j < kb; j++)
{ scanf (“%d”, &st.ball [j] ); /* ввод баллов */
sum += st.ball[j]); /* cумма баллов */
}
st.sb = sum / kb; /* ввод среднего балла в структуру */
fwrite (&st, sizest, 1, fst); /* запись структуры st в файл fst */
}
printf (“\nКонец ввода исходных данных студентов”);
printf (“\nСписок студентов до обработки: “);
OUTSTUD (fst, kst, sizest); /* вывод списка студентов */
printf (“\nСортировка студентов по убыванию среднего балла”
” методом простого выбора”);
for (i=0; i < kst –1; i++) /* цикл шагов сортировки */
{ k=i; /* начальный индекс максимального sb */
fseek (fst, (long) i*sizest, 0); /* установка на i-ю структуру от начала */
fread (&st, sizest, 1, fst); /* чтение из файла fst данных в структуру st */
for (j=i+1; j < kst; j++) /* цикл поиска максимального средн. балла */
{ fseek (fst, (long) j*sizes, 0); /* установка на j-ю структуру от начала */
fread (&stb, sizest, 1, fst); /*чтение из файла fst данных в структуру stb*/
if (stb.sb > st.sb) /* проверка значения среднего балла */
{ k = j; /* изменение индекса максимального sb */
st = stb; /* изменение текущей структуры */
}
}
if (k != i) /* несовпадение начального и текущего индекса */
{ fseek (fst, (long) i*sizest, 0); /* установка на i-ю структуру от начала */
fread (&std, sizest,1, fst); /* чтение из файла fst даных в структуру std*/
fseek (fst, (long) i*sizest, 0); /* установка на i-ю структуру от начала */
fwrite (&st, sizest,1, fst); /* запись в файл fst новой структуры st */
fseek (fst, (long) k*sizest, 0); /* установка на k-ю структуру от начала */
fwrite (&std, sizest,1, fst); /* запись в файл fst новой структуры std */
}
}
printf (“\nСписок студентов после обработки:”);
OUTSTUD (fst, kst, sizest); /* вывод списка студентов */
puts (“\nНажмите на любую клавишу…”);
getch(); /* задержка экрана */
fclose (fst); /* закрытие файла fst */
return 0; /* нормальное завершение программы */
} /* конец главной функции */
void OUTSTUD (FILE fst, int kstud, int sizest) /* вывод списка студентов */
{ int i, j;
STUDENT st;
printf (“\nСтудент Баллы Средний балл”);
rewind (fst); /* установка указателя на начало файла fst*/
for (i=0; i < kstud; i++) /* по цикл студентам */
{ fread (&st, sizest, 1, fst); /* чтение из файла данных в структуру st */
printf (“\n%-15s”, st.name); /* вывод Фамилии И.О. */
for (j=0; j < kb; j++) /* цикл по баллам */
printf (“%-3d”, st.ball[j]); /* вывод баллов */
printf (“%16.3f”, st.sb); /* вывод среднего балла */
}
} /* конец функции OUTSTUD */
Результаты программы:
Открыт файл fst для ввода данных о 3 студентах
Студент 1: Иванов П.А.
Ввод 2 баллов (от 3 до 5) 4 5
Студент 2: Петров О.Л.
Ввод 2 баллов (от 3 до 5) 4 4
Студент 3: Сидоров Р.Д.
Ввод 2 баллов (от 3 до 5) 5 5
Конец ввода исходных данных студентов
Список студентов до обработки:
Студент Баллы Средний балл
Иванов П.А. 4 5 4.500
Петров О.Л. 4 4 4.000
Сидоров Р.Д. 5 5 5.000
Сортировка студентов по убыванию среднего балла методом простого выбора
Список студентов после обработки:
Студент Баллы Средний балл
Сидоров Р.Д. 5 5 5.000
Иванов П.А. 4 5 4.500
Петров О.Л. 4 4 4.000
Нажмите любую клавишу…