Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Текстовые файлы с буферизацией



Функции fopen( ) и fclose( ) работают с текстовыми файлами с " буферизацией". Под буферизацией мы понимаем, что вводимые и выводимые данные запоминаются во временной области памяти, называемой буфером. Если буфер заполнился, содержимое его передается в блок, и процесс буферизации начинается снова. Одна из основных задач fclose( ) заключается в том, чтобы освободить любые частично заполненные буферы, если файл закрыт. Текстовым считается файл, в котором информация запоминается в виде символов в коде ASCII или аналогичном. Текстовый файл отличается от двоичного файла, который обычно используется для запоминания кодов машинного языка.

Ввод-вывод текстового файла: getc( ), putc( )

Две функции getc( ) и putc( ) работают аналогично функциям getchar( ) и putchar( ) (описанным в предыдущих лекциях). Разница заключается в том, что вы должны сообщить, какой файл следует использовать.

char ch;

ch=getchar( );

предназначена для получения символа от стандартного ввода, а

ch=getc(in);

- для получения символа от файла, на который указывает in.

putchar(ch);

выводит символ на стандартный файл вывода.

putc(ch, t);

предназначена для записи символа ch в файл, на который ссылается указатель t типа FILE.

Ввод-вывод файла: fprintf( ), fscanf( ), fgets( ), fputs( )

Все функции ввода-вывода, которые мы использовали в предыдущих лекциях, имеют аналоги для ввода-вывода файла. Основное отличие состоит в том, что нам нужно использовать указатель типа FILE, чтобы сообщить функциям с каким файлом им следует работать. Подобно getc( ) и putc( ) эти функции используются после функции fopen( ), открывающей файл, и перед fclose( ), закрывающей его.

Функции fprintf( ) и fscanf( )

Эти функции ввода-вывода работают почти как printf( ) и scanf( ) (см. лекцию 4), но им нужен дополнительный аргумент для ссылки на сам файл. Он является первым в списке аргументов. Пример, иллюстрирующий обращение к этим функциям:

#include < stdio.h>

main( )

{

FILE *fi;

int age;

fi=fopen(" File", " r" ); /* считывание */

fscanf(fi, " %d", & age); /* fi указывает на File */

fclose(fi);

fi=fopen(" Data", " a" ); /*дополнение*/

fprintf(fi, " Data is %d.\n", age);

/*fi указывает на Data*/

fclose(fi);

}

В отличие от getc( ) и putc( ) эти функции получают указатель типа FILE в качестве первого аргумента.

Функция fgets( )

Эта функция имеет три аргумента, в то время как gets( ) имеет лишь один. Пример ее использования:

/* Программа считывает файл строка за строкой */

#include < stdio.h>

#define MAX 80

main( )

{

FILE *f1;

char *string[MAX]

f1=fopen(" File", " r" );

while (fgets(string, MAX, f1)! = NULL)

puts(string);

}

Мы расположили вводимую информацию в символьном массиве string. Первый из трех аргументов функции fgets( ) является указателем на местоположение считываемой строки. Второй аргумент содержит предельную длину считываемой строки. Функция прекращает работу после считывания символа новой строки или после считывания символов общим числом MAX-1, в зависимости от того, что произойдет раньше. В любом случае нуль-символ '\0' добавляется в самый конец строки. Третий аргумент указывает на файл, который будет читаться. Разница между gets( ) и fgets( ) заключается в том, что gets( ) заменяет символ новой строки на '\0', в то время как fgets( ) сохраняет символ новой строки. Подобно gets( ) функция fgets( ) возвращает значение NULL, если встречает символ EOF. Это позволяет нам проверить, достигли ли мы конца файла.

Функция fputs( )

Эта функция похожа на функцию puts( ). Оператор

l=fputs(" Строка", fi);

Код Положение в файле
начало файла
текущая позиция
конец файла

Передает строку " Строка" в файл, на который ссылается указатель fi типа FILE. Конечно, сначала нужно открыть файл при помощи функции fopen( ).

l является целым числом, которое устанавливается в EOF, если fputs( ) встречает EOF или ошибку. Эта функция не ставит завершающий символ '\0' в конце копируемой строки. В отличии puts функция fputs( ) не добавляет символ новой строки в ее вывод.

Функция fseek( )

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

Покажем на примере работу fseek( ):

/* использование fseek( ) для печати содержимого файла */

#include < stdio.h>

int main(int number, char *names[])

{

FILE *fp; long set = 0L;

if(number< 2)

puts(" Введите имя файла в качестве аргумента." );

else {

if ((fp=fopen(names[1], " r" )) == 0)

printf(" Нельзя открыть %s\n", names[1]);

else {

while(fseek(fp, set++, 0) ==0)

putchar(getc(fp));

fclose(fp);

}

}

}

Первый из трех аргументов функции fseek( ) является указателем типа FILE на файл, в котором ведется поиск. Файл следует открыть, используя функцию fopen( ). Второй аргумент " set" . Этот аргумент сообщает, как далеко следует передвинуться от начальной точки (см. ниже). Он должен иметь значение типа long, которое может быть положительным (движение вперед) или отрицательным (движение назад). Третий аргумент является кодом, определяющим начальную точку.

Функция fseek( ) возвращает 0, если все хорошо, и -1, если есть ошибка. Поскольку переменная set инициализирована нулем, при первом прохождении через цикл

while(fseek(fp, set++, 0)==0)

putchar(getc(fp));

мы имеем выражение

fseek(fp, OL, 0);

означающее, что мы идем в файл, на который ссылается указатель fp, и находим байт, отстоящий на 0 байт от начала, т.е. первый байт. Затем функция putchar( ) печатает содержимое этого байта. При следующем прохождении через цикл переменная set увеличивается до 1L, и печатается следующий байт. То есть, переменная set действует подобно индексу для элементов файла. Процесс продолжается до тех пор, пока set не попытается попасть в fseek( ) после конца файла. В этом случае fseek( ) возвращает значение -1 и цикл прекращается.

Распределение памяти

Функция malloc( )

Пусть нам нужно распределить память для запоминания используемых данных. Некоторые ячейки памяти распределяются автоматически, Например, мы можем объявить

char str[ ] = " Символьная строка";

Будет выделена память, достаточная для запоминания этой строки. Мы можем запросить определенный объем памяти:

int mas[150];

Это описание выделяет 150 ячеек памяти, каждая из которых предназначена для запоминания целого значения. Но язык Си позволяет нам распределять дополнительную память во время работы программы. Предположим, мы пишем программу и не знаем, сколько данных нам придется вводить. Тогда можно выделить нужный нам, по нашему предположению, объем памяти, а затем, если понадобится, потребовать еще. Чтобы сделать это, нужно использовать функцию malloc( ). И без указателей тут не обойтись!

/* добавляем память, если необходимо */

#include < stdio.h>

#include < stdlib.h>

#include < string.h>

#define STOP " \n" /* сигнал прекращения ввода */

#define BLOCK 100 /*байты памяти */

#define LIM 40 /*предельная длина вводимой строки*/

#define MAX 50 /*максимальное число вводимых строк */

#define TIME 20000 /* большая задержка времени */

main ( )

{

char store[BLOCK]; /* исходный блок памяти*/

char symph[LIM]; /* приемник вводимых строк*/

char *end; /* указывает на конец памяти */

char *starts[MAX]; /* указывает на начала строк*/

int index = 0; /*количество вводимых строк */

int count; /* счетчик*/

сhar malloc( ); / * распределитель памяти */

starts[0]=store;

end=starts[0]+BLOCK-1;

puts(" Вводите строки по одной" );

puts(" для завершения ввода в начале строке нажимите клавишу [ввод]" );

puts(" Начинайте!." );

while(index< MAX) {

if(fgets(symph, LIM, stdin))

if (strcmp(fgets(symph, LIM, stdin), STOP) == 0)

break;

if(strlen(symph)> end - starts[index]) {

/* действия при недостатке памяти для

запоминания вводимых данных*/

puts(" подождите, программа попробует найти

дополнительную память" );

starts[index]=malloc(BLOCK);

end=starts[index]+BLOCK- 1;

for(count=0; count< TIME; count++);

puts(" память найдена" );

}

strcpy(starts[index], symph);

starts[index+1]=starts[index] + strlen(symph)+1;

if(++index< MAX)

printf(" Строка: %d. продолжайте.\n", index);

}

puts(" Вывод программы" );

for(count=0; count< index; count++)

puts(starts[count]);

}

Давайте посмотрим, что делает функция malloc( ). Она берет аргумент в виде целого без знака, которое представляет количество требуемых байтов памяти. Так, malloc(BLOCK) требует 100 байт. Функция возвращает указатель на тип char в начало нового блока памяти. Мы использовали описание

char *malloc( );

чтобы предупредить компилятор, что malloc( ) возвращает указатель на тип char. Поэтому мы присвоили значение этого указателя элементу массива starts[index] при помощи оператора

starts[index]=malloc(BLOCK);

Предположим, что мы хотим работать с памятью типа int, а не char. Mожете и здесь использовать malloc( ). Вот как это делается:

char malloc( );

/* по-прежнему описываем как указатель на char */

int *newmem; newmem = (int *)malloc(100);

/* используем операцию приведения типа */

Снова требуется 100 байт. Операция приведения типа преобразует значение, возвращенное указателем на тип char, в указатель на тип int. Если в системе int. занимает два байта памяти, это значит, что 100 байт можно использовать для запоминания 50 целых чисел.

Функция calloc( )

Другую возможность распределения памяти дает нам применение функции calloc( ).

char *calloc( ); long *newmem;

newmem=(long *) calloc(100, sizeof(long));

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

 

 

16. Лекция: Функции в примерах.

 

-Функция получения случайных чисел.

-Поиск узлов из простых чисел.

-Матрица инцидентности.

-Структуры данных. Работа с файлами.

-Все операции со стеком.

-Примеры из графики, все преобразования трехмерного пространства.

 


Поделиться:



Последнее изменение этой страницы: 2017-04-13; Просмотров: 364; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.043 с.)
Главная | Случайная страница | Обратная связь