Краткие теоретические сведения
Ввод и вывод в Си
Особенностью Си является отсутствие в этом языке структурированных файлов. Все файлы рассматриваются как не структурированная последовательность байтов. При таком подходе понятие файла распространяется и на различные устройства.
В Си отсутствуют средства ввода-вывода. Все операции ввода-вывода реализуются с помощью функций, которые находятся в библиотеке Си. Библиотека Си поддерживает три уровня ввода-вывода:
· потоковый ввод-вывод;
· ввод-вывод нижнего уровня;
· ввод-вывод для консоли и портов (зависит от ОС).
Потоковый ввод-вывод
На уровне потокового ввода-вывода обмен данными производится побайтно, т. е. за одно обращение к устройству (файлу) производится считывание или запись фиксированной порции данных (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);
}