Основные типы файлов в Си
Система программирования Borland С поддерживает работу с файлами и потоками, данные в которых представлены либо в символьном, либо в двоичном формате. Однако все ранее описанные типы файлов доступны и в программах на Си.
Текстовые (строковые) файлы в Си
Текстовый файл в Си может быть создан путем записи на диск символьных и/или числовых данных по заданному формату с помощью оператора fprintf. В качестве признака конца строки здесь заносятся те же самые байты ODOA, которые появляются на диске в результате вывода управляющего символа \п.
Для инициализации текстового файла необходимо завести указатель на структуру типа FILE и открыть файл в одном из нужных режимов ("rt" для ввода, "wt" - для вывода, "at" — для дозаписи в уже существующий набор данных) по оператору f open:
FILE *f1;
f1=fopen(имя_файла, "режим");
Формат оператора вывода данных в текстовый файл таков:
fprintf(f1,"список_форматов \n",список_вывода);
Если очередная строка текстового файла формируется из значения элементов символьного массива str, то вместо оператора fprintf (fi, "%s\n",str) проще воспользоваться оператором fputs (f1, str).
Чтение данных из текстового файла осуществляется с помощью оператора fscanf(f1,"список_форматов", список_ввода) или fgets(str,n,f1). В последней функции параметр n означает максимальное количество считываемых символов, если раньше не встретится управляющий байт ОА.
В Си существуют и другие возможности для работы с текстовыми файлами — функции open, creat, read, write,
Программа 7_02.с
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
main( ) {
FILE *f;
int j,k;
float d;.
char s[7]="Строка";
f=fopen("c_txt","wt");
for(j=l;j<11;j++)
{
fprintf(f,"%s %d %f\n",s,j,sqrt(j));
fprintf("\n Строка %d %n",j,sqrt(j)); }
fclose(f); fprintf("\n");
f=fopen("c_txt","rt");
for(j=10; j>0; j--) {
fscanf(f,"%s %d %f",s,&k,&d);
fprintf("\n%s %d %f",s,k,d); }
getch () ; }
Обратите внимание на возможную ошибку при наборе программы 7_01.с. Если между форматными указателями %з и %d не сделать пробел, то в файле текст "строка" склеится с последующим целым числом. После этого при чтении в переменную s будут попадать строки вида "строка!", "строка2", ..., "строкаю", в переменную k будут считываться старшие цифры корня из j (до символа "точка"), а в переменной d скажутся дробные разряды соответствующего корня.
Записеориентированные файлы в Си
Записеориентированный файл является частным случаем двоичного файла, в котором в качестве порции обмена выступает структура Си, являющаяся точным аналогом записи в Паскале.
Для инициализации записеориентированного файла необходимо завести указатель на структуру типа FILE и открыть файл в одном из нужных режимов ("rb" — для ввода, "wb" — для вывода, "ab" — для дозаписи в уже существующий набор данных) по оператору f open:
FILE *f11;
f1=fopen(имя_файла, "режим");
Формат оператора вывода данных в записеориентированный файл таков:
fwrite(buf, size_rec, n_rec, f1) ;
Здесь size_rec — размер записи в байтах, а п_гес — количество записей, участвующих в обмене. Считывание данных из записеориентированного файла осуществляется с помощью функции f read:
fread(buf, size_rec, n_rec, f1);
Программа 7_02.с в цикле формирует значение записи b, состоящей из символьного (b.s, 7 байт, включая нулевой байт — признак конца строки), целочисленного (b.n, 2 байта) и вещественного (b.r, 4 байта) полей, и выводит содержимое полей на диск последовательными порциями. Затем файл открывается для ввода и содержимое записей извлекается в обратном порядке. Второй аргумент функции fseek определяет величину смещения указателя файла в байтах относительно точки, заданной третьим параметром. Параметр SEEK_SET означает, что сдвиг указателя в файле производится от его начала. Для сдвига от конца файла используется константа SEEK_END, а для сдвига относительно текущей позиции — константа SEEK_CUR.
Программа 7_03.с
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
main( ) {
FILE *fl; int j, k;
struct { char s [7]; int n; float r; } b;
clrscr();
strcpy(b.s,"Строка");
fl=fopen("c_rec","wb");
for(j=l;j<ll;j++)
{
b.n=j; b.r=sqrt(j);
fwrite(&b,sizeof(b),l,fl);
printf("\n%s %d %f",b.s,b.n,b.r);
}
fclose(fl); printf("\n");
fl=fopen("c_rec","rb");
for(j=10; j>0; j —) {
fseek(fl,(j-1)*sizeof(b),SEEK_SET);
fread(&b,sizeof(b),l,f1);
printf("\n%s %d %f",b.s,b.n,b.r);
}
getch();
}
Двоичные файлы в Си
Работа с настоящими двоичными файлами в Си отличается от приведенного выше примера только тем, что обмены с одним и тем же дисковым файлом могут производиться порциями любой длины, тогда как в записеориентиро-ванном файле предполагается, что размеры всех порций одинаковы.
Кроме набора функций {fopen/fciose, fread/fwrite}, для работы с двоичными файлами в библиотеке Borland С предусмотрены и другие средства -
{_dos_open/_dos_close, _dos_read/_dos_write}, (_creat/_close, _read/_write}.
Однако знакомство со всеми возможностями этой библиотеки в рамках настоящего пособия не предусмотрено.
Программа 7_04.с
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
main ( ) {
FILE *f1; int j, k;
char s[7]="Строка";
int n;
float r; clrscr. () ;
fl=fopen("c_bin","wb");
for(j=l;j<11;j++) {
r=sqrt(j);
fwrite(s,sizeof(s),1,f1);
fwrite(&j,sizeof(int),1,f1);
fwrite(&r,sizeof(float),1,f1);
printf("\n%s %d %f",s,j,r); }
fclose(f1l); printf("\n"); fl=fopen("c_rec","rb"); for(j=10; j>0; j--) {
fseekffl,(j-1)*(sizeof(s)+sizeof(int)+sizeof(float)),
SEEK_SET);
fread(&s,sizeof(s),1,fl);
fread(&n,sizeof(int),1,f1);
fread(&r,sizeof(float),1,f1);
printf("\n%s %d %f",s,n,r); }
getch(); }