Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_по_программированию.doc
Скачиваний:
125
Добавлен:
02.04.2015
Размер:
5 Мб
Скачать
☆

Работа с дисками.

Библиотека Си поддерживает следующие три уровня ввода-вывода:

  • ввод-вывод потока;

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

  • ввод-вывод для консоли и порта.

Ввод-вывод потока.

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

Ввод вывод потока позволяет:

  • открывать и закрывать потоки;

  • создавать и удалять временные потоки;

  • читать и записывать символ;

  • читать и записывать строки;

  • читать и записывать форматированные данные;

  • читать и записывать неформатированные данные;

  • анализировать ошибки ввода-вывода потока и условия конца потока (конца файла);

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

  • выгружать буфера, связанные с потоками;

  • получать и устанавливать указатель текущей позиции в потоке.

Чтобы использовать функции ввода-вывода потока в программе

необходимо директивой #includeвключить файлstdio.h. Этот файл содержит объявления функций ввода-вывода, а также определения констант, типов и струк4тур, используемых фунциями потока.

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

Перед выполнением операций ввода-вывода для потока его нужно открыть. Когда поток открывается для операций ввода-вывода, он связывается со структурой предопределённого типа FILE, содержащей всю необходимую информацию для работы с потоком: такую, как указатель текущей позиции в потоке, указатель на буфер связанный с потоком, тип доступа к потоку и др.. При открытии потока возвращается указатель на структуруFILE, называемый указателем потока.

Для открытия потока библиотека Си представляет три функции: fopenиfdopenоткрывают потоки, аfreopenпереназначает указатель на другой поток.

При успешном открытии потока функции открытия возвращают указатель на структуру FILE, в противном случае возвращается нулевой указатель (NULL).

#include <stdio.h>

…

FILE *file_ptr;

…

if(file_ptr=fopen(…)== NULL)

printf(“\nОшибка открытия файла”);

Тип доступа к потоку задаётся как аргумент функции открытия. Он является строковым литералом, который может принимать значения:

“r” - поток открывается для чтения;

“w” - открывается пустой поток для записи. Если поток

существует, его содержимое пропадает;

“a” - поток открывается для записи в конец потока. Если поток

не существует, он создаётся;

“r+” - поток открывается для чтения и записи (поток должен

существовать);

“w+” - открывается пустой поток для чтения и записи. Если

поток существует, его содержимое пропадает;

“a+” - поток открывается для чтения и записи в конец

потока. Если поток не существует, он создаётся.

#include <stdio.h>

…

FILE *file_ptr;

…

if(file_ptr=fopen(“a:file.dat”,”r”)== NULL)

printf(“\nОшибка открытия файла”);

else

printf(“\nФайл открыт для чтения”);

Операции чтения и записи для потока начинаются с текущей позиции потока, определяемой указателем текущей позиции в потоке.

Библиотека Си предоставляет следующие функции для позиционирования указателя текущей позиции в потоке:

ftell(fp) иfgetposполучают текущую позицию указателя потока

fseekиfsetposустанавливают текущую позицию указателя в потоке

rewind(fp) позиционирует указатель потока на начало потока.

Новая позиция указателя потока в функции fseekзадаётся как смещение от некоторой начальной позиции, которая может быть одним из следующих значений

SEEK_SET- начало потока,

SEEK_CUR– текущая позиия указателя потока,

SEEK_END– конец потока.

ПРИМЕР использования функции fseek

FILE*fp;

longn;

…

fseek(fp,0L,SEEK_SET);//Позиционирование на начало потока

fseek(fp,0L,SEEK_END); //Позиционирование на конец потока

fseek(fp,n,SEEK_SET); //Позиционирование наn

//байт от начала потока

fseek(fp,n,SEEK_END); //Позиционирование наn

//байт от конца потока

fseek(fp,n,SEEK_CUR); //Позиционирование наn

//байт от текущей позиции

fseek(fp,-n,SEEK_CUR); //Позиционирование наn

//байт до текущей позиции

fseek(fp,-n,SEEK_END); //Позиционирование наn

//байт до конца потока

Пример

Пусть имеется структура

sruct h_main

{

int tipe;

char s[20];

char s2[20];

char s[320];

}

sructh_mainm;

//позиционирование курсора на начало i–й записи структуры в файле

fseek(fmain, i*sizeof(m), SEEK_SET);

чтение

fread(&m, i*sizeof(m), 1, fmain);

запись

fwrite(&m, i*sizeof(m), 1, fmain);

Операции динамического распределения памяти.

Операции new, new[ ],delete, delete[ ]введены в язык С++ с целью решения одной из задач управления памятью, а именно – её динамического распределения. Две операцииnew, new[ ]предназначены для выделения участков свободной памяти и размещения в них переменных (new[ ]– массивов). Продолжительность существования таким образом созданных (динамических) переменных – от точки создания до конца программы или до явного освобождения соответсвующего участка памяти применением операцийdelete(delete[]– для удаления массивов).

Первая из рассматриваемых операций предназначена для размещения в динамической памяти переменной заданного аргументом типа (кроме типов массивов) и имеет следующий общий тип

newимя_типа илиnewимя_типа(выражение)

Вторая форма помимо выделения памяти осуществлвяет её инициализацию значением выражения. В обоих случаях результат операции имеет тип указателя того же типа что и аргумент, (т.е. имя_типа), и значение адреса размещенной динамической переменной. Это значение, очевидно, нужно сохратить в какой-либо переменной-указателе, что обеспечит в дальнейшем доступ к динамической переменной.

Пример создания и использования двух динамических переменных:

int *i = new int, *j = new(5);

*i=*j**j ;

Для размещения динамических массивов предусмотрена специальная операция new[ ],вызываемая следующим образом:

newтип_элемента[размер ] . . . [размер]

Заметим, что не предусмотрено средств для инициализации динамических массивов, и для размещаемых массивов должны быть определены все размерности, более того, только первая размерность может быть задана с помощью переменой, все остальные размерности многомерных массивов должны быть заданы с помощью константы. Результатом операции является указатель на начало созданного массива.

Пример размещения в памяти трехмерного динамического массива

long (*p) [3][4]; // описание указателя

p=new long [2][3][4]; // размещение массива

p[1][1][1]=1; // обращение к элементу

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

delete i; delete j; delete[] p;

Создание многомерных динамических массивов с переменным количеством элементов

double **a=new double *[n];

for(int i=0; i<n;i++) a[i]=new double[m];

a[1][1]=1.0;

for(int i=0; i<n;i++) delete[] a[i]; delete[] a;