Краткие теоретические сведения

Ввод и вывод в Си

     Особенностью Си является отсутствие в этом языке структурированных файлов. Все файлы рассматриваются как не структурированная последовательность байтов. При таком подходе понятие файла распространяется и на различные устройства.

     В Си отсутствуют средства ввода-вывода. Все операции ввода-вывода реализуются с помощью функций, которые находятся в библиотеке Си. Библиотека Си поддерживает три уровня ввода-вывода:

·      потоковый ввод-вывод;

·      ввод-вывод нижнего уровня;

·      ввод-вывод для консоли и портов (зависит от ОС).

Потоковый ввод-вывод

     На уровне потокового ввода-вывода обмен данными производится побайтно, т. е. за одно обращение к устройству (файлу) производится считывание или запись фиксированной порции данных (512 ил 1024 байта). При вводе с диска или при считывании из файла данные помещаются в буфер ОС, затем побайтно или порциями передаются в программе пользователя. При вывод в файл данные накапливаются в буфере, а при заполнении буфера записываются в виде единого блока на диск. Буферы ОС реализуются в виде участков основной памяти . Функции библиотеки Си, поддерживающие обмен, с данными на уровне потока позволяют обрабатывать данные различных размеров и форматов.

     Поток - это файл вместе с предоставленными средствами буферизации. При работе с потоком можно:

1)  Открывать и закрывать потоки ( связывать указатели на поток с конкретными файлами);

2)  вводит и выводить строку, символ, форматированные данные, порцию данных произвольной длины;

3)  анализировать ошибки ввода-вывода и достижения конца файла;

4)  управлять буферизацией потока и размером буфера;

5)  получать и устанавливать указатель текущей позиции в файле;

Функции библиотеки ввода-вывода находятся в заголовочном файле <stdio.h>.

Открытие и закрытие потока

     Прежде чем начать работать с потоком, его надо инициировать, т. е. открыть. При этом поток связывается со структурой предопределенного типа FILE, определение которой находится в библиотечном файле <stdio.h>. В структуре находится указатель на буфер, указатель на текущую позицию файла и т. п. При открытии потока, возвращается указатель на поток, т. е. на объект типа FILE.

#include <stdio.h>;

. . . . . . . .

FILE *fp;

. . . . . . . . . . ..

fp= fopen( ”t.txt”, ”r”);

где fopen(<имя_файла>,<режим_открытия>) - функция для инициации файла.

Существуют следующие режимы для открытия файла:

”w” - открыть файл для записи, если файл существует, то он стирается;

”r” - открыть файл для чтения;

”a” - открыть файл для добавления, если файл существует, то он не стирается и можно писать в конец файла;

”w+” - открыть файл для записи и исправления, если файл существует, то он стирается, а далее можно и читать , и писать, размеры файла можно увеличивать;

”r+” - открыть файл для чтения и записи, но увеличить размер файла нельзя;

”a+” - открыть файл для добавления, т. е. можно и читать и писать, в том числе и в конец файла. 

Поток можно открыть в текстовом (t) или двоичном (b) режиме. По умолчанию - текстовый режим. В явном виде режим указывается следующим образом: ”r+b”или ”rb” - двоичный (бинарный) режим.

Пример:

if ((fp=fopen(”t.txt”, ”w”)==NULL)

{

perror(”\nошибка при открытии файла”); // выводит строку символов с сообщением                            // об ошибке

exit(0);

}

После работы с файлом, его надо закрыть

fclose(<указатель_на_поток>);

 

 

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

     Для блокового ввода и вывода используются функции :

1)  int fread( void *ptr, int size, int n, FILE *fp) , где 

void *ptr - указатель на область памяти, в которой размещаются считываемые из файла данные;

int size - размер одного считываемого элемента;

int n - количество считываемых элементов;

FILE *fp - указатель на файл, из которого производится считывание.

В случае успешного считывания информации функция возвращает число прочитанных элементов (а не байтов), иначе возвращает EOF.

2) int fwrite( void *ptr, int size, int n, FILE *fp) , где 

void *ptr - указатель на область памяти, в которой размещаются записываемые в файл данные;

int size - размер одного записываемого элемента;

int n - количество записываемых элементов;

FILE *fp - указатель на файл, в который производится запись.

В случае успешной записи информации функция возвращает число записанных элементов, иначе возвращает EOF.

Пример:

. . . .. . . ..

typedef STRUCT

{

char name [40];

char post [40];

float rate;

}EMPLOYEE;

void main ()

{

FILE *f; // указатель связанный с файлом

EMPLOYEE e;   // переменная

EMPLOYEE mas[10]   //массив

//открываем файл

if ((f=fopen("f.dat", "wb")==NULL) exit(1); // если при открытии файла возникает

      //ошибка, то выходим из функции

int i;

for(i=1; i<=10;i++)

{

//формируем запись е

printf("name="); scanf("%s",&e.name);

printf("post="); scanf("%s",&e.post);

printf("rate="); scanf("%f",e.rate);

// записываем запись е в файл

fwrite(&e, sizeof(EMPLOYEE),1,f);

if (ferror(f)==NULL) exit(2);

}

fclose(f);

//чтение записей из файла

if ((f=fopen("f.dat", "rb")==NULL) exit(3); // если при открытии файла возникает

      //ошибка, то выходим из функции

i=0;

while(!feof(f)&&i<=10)

{

 fread(&mas[i], sizeof(EMPLOYEE),1,f);

i++;

}

fclose(f);

}