Скачиваний:
2
Добавлен:
03.01.2024
Размер:
3.49 Mб
Скачать

Двоичные и текстовые режимы доступа к файлам

Закрытие файла производится с помощью функции fclose: int fclose(FILE *stream);

«Перемотка» файла в начало : void rewind(FILE *stream);

В потоке *stream эта функция смещает указатель чтения записи в начало файла.

Позиционирование указателя чтения-записи

int fseek(FILE *stream, long int offset, int whence);

Смещение задаётся переменной или выражением типа long. Может быть меньше нуля, т.е.

Можно "ходить" по файлу в разные стороны:

offset- смещение,

whence — начало отсчёта.

Начало отсчёта задаётся одной из определённых констант:

SEEK_SET(имеет значение 0) – начало файла

SEEK_CUR(имеет значение 1) – текущая позиция

SEEK_END(имеет значение 2) – конец файла

fseek(fp, 0L, SEEK_SET); /* перемещение к началу файла из произвольной позиции */

Так мы можем перейти к началу файла из произвольной позиции.

Посимвольный ввод:

int fgetc(FILE *stream);

Функция считывает один символ с текущей позиции потока и перемещает указатель файла на следующий символ.

Ошибка, если конец файла - EOF.

Посимвольный вывод:

int fputc(int c, FILE *stream);

Ввод строки из файла:

char *fgets(char *s, int n, FILE *stream);

Читает из файла не более n-1 символов и размещает их по адресу s.

Символов может быть меньше, чем n-1, если встретился \n или EOF.

Запись строки в файл:

int fputs(const char *s, FILE *stream);

Записывает строку, ограниченную \0, в файл и возвращает неотрицательное целое число.

При неудаче возвращает EOF. Не заменяет ноль-терминатор на перевод новой строки.

Запись данных в поток и чтение из потока:

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

В файлах можно хранить потоки данных, состоящих из

фиксированного числа последовательных байт.

Именно вышеуказанные функции fread и fwrite осуществляют последовательные запись\чтение блоков.

Функция fread считывает элементы данных nmemb (с размером каждого size байтов) с потока, на который указывает stream, и сохраняет их в позиции, на которую указывает ptr.

Функция fwrite записывает элементы данных nmemb (с размером каждого size байтов) в поток, на который указывает stream, при получении элементов с той позиции, на которую

указывает ptr.

31

Двоичные и текстовые режимы доступа к файлам

Библиотека stdio.h поддерживает текстовые и бинарные (двоичные) потоки.

Текстовый поток – это последовательность строк, каждая из которых заканчивается символом ‘\n’.

ОС может потребовать коррекции текстового потока.

Например, при вводе текстового потока система преобразует

символы возврат каретки 0x13 и перевод строки 0x10 в

одиночный символ ‘\n’.

При обнаружении в текстовом файле символа с кодом 26 (0x26), т.е. признака конца файла, чтение файла в текстовом режиме

заканчивается, хотя файл может иметь продолжение.

При выводе текстового потока в среду операционной системы происходит обратное преобразование.

При осуществлении операции ввода-вывода в текстовом режиме:

При записи информации в файл символ новой строки преобразуется в пару символов CR и LF.

При чтении из файла эта пара символов преобразуется обратно в символ \n.

В конце файла записывается EOF (0x1A) End Of File конец файла.

При считывании информации прочитать находящуюся после EOF не удаётся.

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

При выполнении ввода-вывода в двоичном режиме никакого преобразования символов не происходит и все остальные рассматриваются как не имеющие особого значения символы.

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

Функции работы с файлами определены в заголовочном файле stdio.h

Указатель на поток: FILE *fp;

Открытие файла: fp=fopen(имя_файла, режим_открытия);

Пример:

FILE *fp; fp=fopen("t.txt", "r");

При открытии файла он связывается со структурой,

определённой в типе FILE.

В ней содержатся компоненты, с помощью которых ведётся работа с потоком.

Указатель на буфер, указатель текущей позиции в потоке,

флаги состояния файла, размер внутреннего буфера и т.п.

При открытии потока в программу возвращается указатель на поток, являющийся указателем на объект структурного типа

FILE.

Режимы открытия:

"w" - Новый текстовый файл открывается для записи. Если файл

уже существовал, то старый стирается и создаётся новый.

"r" — Существующий текстовый файл открывается для чтения.

"a" — Текстовый файл открывается для добавления новой информации в конец файла.

"w+" - Новый текстовый файл открывается для записи и последующих многократных исправлений. Стирает файл, если он уже есть и создаёт новый.

"r+" - Существующий файл открывается как для чтения, так и для записи в любое место файла

"a+" - Текстовый файл открывается или создаётся и становится доступным для изменений.

Для использования этих же режимов, но для двоичных файлов, к

ним добавляется буква b.

32

 

Программа чтения данных из файла

# include <stdio.h>

 

// Чтение данных файла (продолжение 1-й части)

int main (void)

 

col=fscanf (f_cht, %x %d %o %lf %f %c %s %c %s”, &k, &k1,

{

 

&k2, &l, &x, &ch, str, &str[3], &str[4]);

int k, // Данные будут прочитаны из файла и

if (col!=9)

k1, /* могут использоваться в данной

{

программе */

 

printf (”\nДанные прочитаны с ошибками.”);

k2;

 

return 2;

float x;

 

}

long l;

 

// Закрываем файл.

char ch,

 

col=fclose (f_cht);

str[15];

 

if (col==EOF) /* EOF – это значение функции fclose при

file *f_cht;

// Указатель на файл для чтения.

ошибке */

int col;

// Возвращаемое значение fscanf.

// При успехе возвращается 0

// Открываем файл «f1.dat» для чтения.

{

f_cht=fopen (“f1.dat”, “r”);

print f(“\nФайл f1.dat не закрыт.”);

if (f_cht==NULL) /* NULL–нулевой указатель

return 3;

(означает ошибку) */

 

}

{

 

return 0;

printf (“\nФайл f1.dat для чтения не открыт.

} //конец программы чтения из файла

Ошибка!”);

 

return 1;

}

33

Примеры файлового ввода-вывода

# include <stdio.h>

// Для функции ввода/вывода.

int main (void)

// Возвращает 0 при успехе.

{

// Данные для записи в файл

int n=7;

 

long int ln=12l;

 

short int sn=5;

 

float x=1.5e2;

 

long double ld=2.0e-3L;

file *f_zap;

// Указатель на файл для записи

int col;

// Возвращаемое значение для fclose.

 

// Открываем файл f2.out для записи.

f_zap=fopen (“f2.out”, “w”);

if (f_zap==NULL)

 

{

 

printf (“\nФайл f2.out для записи не открыт.”);

return 1;

 

}

 

 

}

// end main ()

Просмотрев содержимое файла любым текстовым редактором, можно убедиться, что данные в нем располагаются точно так, как на экране, если воспользоваться функцией printf с такими же списками параметров.

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

f = fopen ("Dat_sp.dat ", "w"); /* Открывается для записи файл с логическим именем f, имеющий физическое имя Dat_sp.dat или более кратко: */

FILE *f = fopen ("Dat_sp.dat", "w");

По умолчанию файл открывается в текстовом режиме.

Текстовый режим отличается от двоичного тем, что при открытии файла как текстового, пара символов «перевод строки» и «возврат каретки» заменяется на один символ «перевод строки» для всех функций записи данных в файл.

И для всех функций вывода – наоборот – символ «перевод строки» заменяется на два символа – «перевод строки» и «возврат каретки».

#include<stdio.h> void main(void)

{

FILE *f1;

int a=2, b=3;

if( ! (f1 = fopen(“f_rez.txt”,”w+t”) ) ) // f1 = NULL

{

puts(“Open File Error!”);

 

return;

// exit(1);

}

fprintf(f1,”\t Файл результатов \n”); fprintf(f1,” %d плюс %d = %d\n”, a, b, a+b); fclose(f1);

}

34

Пример использования ввода-вывода на Си

 

 

Код программы

Программа

 

 

 

s1

 

s2

 

 

 

 

 

 

Ядро ОС

 

fd1

 

FILE

->file1

 

 

 

 

FILE

fd2

 

->file2

 

 

 

 

 

Станд. библиотека

 

 

 

 

GLibC

 

 

 

 

 

file1

file2

 

 

 

Файловая система

Функция fscanf считывает данные с текущей позиции вводимого потока в заданный список аргументом в соответствии с заданным условием.

Общая структура выглядит так: fscanf (stream, format-string [, argument ...]);

где stream – поток данных, который мы считываем, format-string – условия при которых данные сохранятся и [, argument1,

 

argument2, …] –аргументы.

35

Пример использования ввода-вывода на С/С++

Код программы

file1

Файловая система

Пример кода:

char str [60]; FILE * aF;

aF = fopen ("file.txt","w+"); fscanf (aF, "%s", str); fclose (aF);

Впервых двух строках идет объявление необходимых в работе переменных – массива символов str и файла (а если корректней, то потока) aF.

Далее идет инициализация aF, путем открытия файла file.txt. На следующей строке идет нужная нам функция. Первой переменной в fscanf является aF – тот поток, из которого мы будем считывать данные.

Далее идет идентификатор %s, показывающий, что считывание будет происходить до 1-ого пробела.

Возможны и другие идентификаторы, например %i, сохраняющее любое целое число 10-тичной, 8-ричной или 16-ричной системы. И последнее str – куда записывается данные из потока.

Витоге в str сохранятся символы из потока, начиная с первого символа, пока не встретится пробел.

Последняя строка закрывает файл.

36

Приложение. Функции ВВ getchar( ) и putchar(х)

Операции ввода/вывода в языке Си организованы посредством библиотечных функций (причем их довольно много).

Самый простой механизм ввода - чтение по одному символу из стандартного входного потока (с клавиатуры) с помощью функции getchar( ).

Она имеет следующий прототип (т.е. описание заголовка):

int getchar(void);

Здесь определен тип единственного аргумента (void) и тип возвращаемого функцией значения (int).

Оператор вида:

х = getchar( );

присваивает переменной х очередной вводимый символ. Переменная х должна иметь символьный или целый тип.

Другая функция - putchar(х) выдает значение переменной x в стандартный выходной поток (на экран дисплея).

Функция putchar( ) имеет прототип:

int putchar(int);

Объявления getchar( ) и putchar( ) сделаны в заголовочном файле stdio.h, содержащем описания заголовков библиотечных функций стандартного ввода/вывода.

Чтобы библиотечные функции стали доступны программе, к ней необходимо подключить данный файл.

Подключение осуществляется с помощью директивы препроцессора

#include <stdio.h>

помещаемой в начало программы

Заметим, что для функции getchar( ) после выбора символа необходимо нажать клавишу <Enter>.

Иногда это создает определенные неудобства.

Функции getch( ) и getche( ) устраняют их. Они имеют следующие прототипы:

int getch(void);

int getche(void);

Обе эти функции вводят символ сразу же после нажатия соответствующей клавиши (здесь не надо дополнительно нажимать клавишу <Enter>).

Отличие между ними заключается в том, что getche( ) отображает вводимый символ на экране дисплея, а getch( ) - нет.

Прототипы этих функций содержатся в файле conio.h (консольный ввод/вывод).

Для их использования файл conio.h также следует подключить к программе с помощью директивы #include <conio.h>

37

Приложение. Форматированный вывод данных. Функция printf( )

Функция printf( ) (прототип содержится в файле stdio.h: #include <stdio.h>) обеспечивает форматированный вывод.

Ее можно записать в следующем формальном виде:

рrintf ("управляющая строка", аргумент _1, аргумент

_2,...);

Управляющая строка содержит компоненты трех типов:

1)обычные символы, которые просто копируются в стандартный выходной поток (выводятся на экран дисплея);

2)спецификации преобразования, каждая из которых вызывает вывод на экран очередного аргумента из последующего списка;

3)управляющие символьные константы.

Каждая спецификация преобразования начинается со знака % и заканчивается некоторым символом, задающим преобразование.

Между знаком % и символом преобразования могут встречаться другие знаки в соответствии со следующим форматом:

% [признаки] [ширина_поля] [точность] [F|N|h|l|L] c_n

Все параметры в квадратных скобках не являются обязательными.

На месте параметра c_n (символ преобразования) могут быть записаны:

с - значением аргумента является символ;

d или i - значением аргумента является десятичное целое число;

е - значением аргумента является вещественное десятичное число в экспоненциальной форме вида 1.23e+2;

Е - значением аргумента является вещественное десятичное число в экспоненциальной форме вида 1.23E+2;

f - значением аргумента является вещественное десятичное число с плавающей точкой;

g (или G) - используется, как е или f, и исключает вывод незначащих нулей;

о - значением аргумента является восьмеричное целое число; s - значением аргумента является строка символов (символы

строки выводятся до тех пор, пока не встретится символ конца строки или же не будет, выведено число символов, заданное точностью);

u - значением аргумента является беззнаковое целое число; х - значением аргумента является шестнадцатеричное целое

число с цифрами 0,..., 9, а, b, с, d, е, f;

X - значением аргумента является шестнадцатеричное целое число с цифрами 0,..., 9, А, В, С, О, Е, F;

р - значением аргумента является указатель;

n - применяется в операциях форматирования. Аргумент, соответствующий этому символу спецификации, должен быть указателем на целое. В него возвращается номер позиции строки (отображаемой на экране), в которой записана спецификация %n.

38

Приложение. Форматированный вывод данных. Функция printf( )

Необязательные параметры в спецификации преобразования:

признак минус (-) указывает, что преобразованный параметр должен быть выровнен влево в своем поле;

признак плюс (+) требует вывода результата со знаком; строка цифр, задающая минимальный размер поля (ширина

поля). Здесь может так же использоваться символ *, который тоже позволяет задать минимальную ширину поля и точность представления выводимого числа;

точка (.), отделяющая размер поля от последующей строки цифр;

строка цифр, задающая максимальное число выводимых символов, или же количество цифр, выводимых справа от десятичной точки в значениях типов float или double (точность);

символ F, определяющий указатель типа far; символ N, определяющий указатель типа near; символ h, определяющий аргумент типа short int

(используется вместе с символами преобразования d, i, о, u, х, Х); символ l, указывающий, что соответствующий аргумент имеет

тип long (в случае символов преобразования d, i, о, u, х, X) или double (в случае символов преобразования е, Е, f, g, G);

символ L, указывающий, что соответствующий аргумент имеет тип long double (используется вместе с символами преобразований е, Е, f, g, G);

символ #, который может встречаться перед символами преобразования g, f, е и перед символом х. В первом случае всегда будет выводиться десятичная точка, а во втором - префикс 0x перед соответствующим шестнадцатеричным числом.

Если после знака % записан не символ преобразования, то он выводится на экран. Таким образом, строка %% приводит к

Функция printf( ) использует управляющую строку, чтобы определить, сколько всего аргументов и каковы их типы. Аргументами могут быть переменные, константы, выражения, вызовы функций; главное, чтобы их значения соответствовали заданной спецификации.

При наличии ошибок, например, в числе аргументов или типе преобразования, результаты будут неверными.

Среди управляющих символьных констант наиболее часто используются следующие:

- для кратковременной подачи звукового сигнала; \b - для перевода курсора влево на одну позицию; \f - для подачи формата;

\n - для перехода на новую строку; \r - для возврата каретки;

\t - горизонтальная табуляция; \v - вертикальная табуляция; \\ - вывод символа \; \' - вывод символа ' ; \" - вывод символа "; \? - вывод символа ?.

Например, в результате вызова функции: printf("\tComputer\n%d\n", i);

Сначала выполняется горизонтальная табуляция (\t), т.е. курсор сместится от края экрана, затем на экран будет выведено слово Computer, после этого курсор переместится в начало следующей строки (\n), затем будет выведено целое число i по формату %d (десятичное целое), и, окончательно, курсор перейдет в начало новой строки (\n).

Напечатать строку символов можно и так: printf("Это строка символов");

выводу на экран знака %.

39

Приложение. Форматированный ввод данных. Функция scanf( )

Функция scanf( ) (прототип содержится в файле stdio.h) обеспечивает форматированный ввод.

Ее можно записать в следующем формальном виде:

scanf("управляющая строка", аргумент_1, аргумент_2,...);

Аргументы scanf( ) должны быть указателями на соответствующие значения.

Для этого перед именем переменной записывается символ &. Назначение указателей будет рассмотрено далее.

Управляющая строка содержит спецификации преобразования и используется для установления количества и типов аргументов. В нее могут включаться:

пробелы, символы табуляции и перехода на новую строку (все они игнорируются);

спецификации преобразования, состоящие из знака %, возможно, символа * (запрещение присваивания), возможно, числа, задающего максимальный размер поля, и самого символа преобразования;

обычные символы, кроме % (считается, что они должны совпадать с очередными неизвестными символами во входном потоке).

Рассмотрим символы преобразования функции scanf( )

(указываются после символа %):

с - на входе ожидается появление одиночного символа;

d или i - на входе ожидается десятичное целое число и аргумент является указателем на переменную типа int;

D или l - на входе ожидается десятичное целое число и аргумент является указателем на переменную типа long;

е или Е - на входе ожидается вещественное число с плавающей точкой;

f - на входе ожидается вещественное число с плавающей точкой; g или G - на входе ожидается вещественное число с плавающей

точкой; о - на входе ожидается восьмеричное целое число и аргумент

является указателем на переменную типа int;

О - на входе ожидается восьмеричное целое число и аргумент является указателем на переменную типа long;

s - на входе ожидается появление строки символов;

х - на входе ожидается шестнадцатеричное целое число и аргумент является указателем на переменную типа int;

Х - на входе ожидается шестнадцатеричное целое число и аргумент является указателем на переменную типа long;

р - на входе ожидается появление указателя в виде

шестнадцатеричного числа;

n - применяется в операциях форматирования. Аргумент, соответствующий этому символу спецификации, должен быть указателем на целое. В него возвращается номер позиции (после ввода), в которой записана спецификация %n;

u - на входе ожидается беззнаковое целое число и аргумент является указателем на переменную типа unsigned int;

U - на входе ожидается беззнаковое целое число и аргумент является указателем на переменную типа unsigned long;

[ ] - сканирует входную строку для получения символов.

Перед некоторыми символами преобразования могут записываться следующие модификаторы:

F - изменяет указатель, заданный по умолчанию, на указатель типа far;

N - изменяет указатель, заданный по умолчанию, на указатель типа near;

h - преобразует аргумент к типу short int (может записываться перед символами d, i, о, u, х);

l - преобразует аргумент к типу long int (может записываться перед

символами d, i, o, u, x);

 

L - преобразует аргумент к типу long double (может записываться

40

перед символами е, f, g).

Соседние файлы в папке Лекции