Блоковый ввод-вывод

 

Функции блокового ввода-вывода позволяют выполнять перенос между файлом и программой фиксированных блоков байтов, или записей (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

Нажмите любую клавишу…