Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

7_ Файлы .

...doc
Скачиваний:
9
Добавлен:
10.02.2015
Размер:
192.4 Кб
Скачать

int Num=i*w+j;

// Чтение элемента

double x;

for(int k=0; k<=Num;k++)

fscanf(pFile, "%lf", &x);

fclose(pFile);

return x;

}

6.5 Чтение и запись объектов абстрактных типов

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

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

zise_t fwrite(

// Адрес первого блока с записываемым объектом

const char* Buffer,

// Размер одного блока в байтах

size_t Size,

// Количество записываемых блоков

size_t Count,

// Адрес структуры типа FILE

FILE* pFile);

Идентификатор size_t является синонимом идентификатора типа unsigned int, определенным с помощью команды typedef. Первым в файл записывается байт за байтом без каких-либо преобразований блок с адресом Buffer, преобразованным к типу char. Затем следующий блок. Функция возвращает количество записанных в файл блоков.

Для чтения из файла абстрактных объектов можно воспользоваться функцией с именем fread(). Ее прототип выглядит следующим образом.

zise_t fread(

// Адрес первого блока с читаемым объектом

const char* Buffer,

// Размер одного блока в байтах

size_t Size,

// Количество читаемых блоков

size_t Count,

// Адрес структуры типа FILE

FILE* pFile);

Она позволяет прочитать из файла с указателем pFile ровно Count объектов размером Size байтов каждый. Читаемые объекты размещаются в буфере с адресом Buffer, преобразованном к типу char, байт за байтом без каких-либо преобразований. Функция возвращает количество прочитанных из файла объектов.

Пример 6.5 - Чтение и запись объектов абстрактных типов

// Подключение файлов с прототипами функций

#include <stdio.h>

// Определение абстрактного типа

struct AA {

char ch;

int i;

float f;

};

void main(void) {

// Открытие файла для записи и чтения

FILE* pFile=fopen("Data.dat", "w+b");

// Проверка корректности результата

if(pFile==NULL) {

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

return ;

}

// Создание объектов

AA aa={'A', 1, 2.0f},

bb={'B', 2, 3.0f};

// Запись в файл и вычисление значения текущей позиции

fwrite(&aa, sizeof(AA), 1, pFile);

printf("LenFile: %ld\n", ftell(pFile));

fwrite(&bb, sizeof(AA), 1, pFile);

printf("LenFile: %ld\n", ftell(pFile));

// Установка текущей позиции на начало файла

fseek(pFile, 0L, SEEK_SET);

// Чтение из файла

fread(&bb, sizeof(AA), 1, pFile);

fread(&aa, sizeof(AA), 1, pFile);

// Отображение прочитанных объектов

printf("aa={%c %d %f}\n", aa.ch, aa.i, aa.f);

printf("bb={%c %d %f}\n", bb.ch, bb.i, bb.f);

// Закрытие файла

fclose(pFile);

}

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

LenFile: 12

LenFile: 24

aa={B 2 3.000000}

bb={A 1 2.000000}

Отметим, что для хранения структуры из трех элементов типов char, int и float компилятор MS Visual C++ v.6.0 выделяет 12 байт, а не девять!

В следующем примере в файл записываются размеры и элементы матрицы. Затем из файла читается ее элемент из строки с номером i и столбца с номером j. Для чтения элемента написана отдельная функция ReadFromFile().

Пример 6.6 – Чтение из файла элемента таблицы

// Чтение из файла элемента i-ой строки и j-ого столбца таблицы

#include <stdio.h>

#include <stdlib.h>

double ReadFromFile(char* FileName, int i, int j);

void main(void){

// Размеры матрицы

int h=3, w=4;

// Матрица

double A[]={0.0, 0.1, 0.2, 0.3,

1.0, 1.1, 1.2, 1.3,

2.0, 2.1, 2.2, 2.3};

// Открытие файла для записи

FILE* pFile=fopen("Matrix.dat", "wb");

if(!pFile){

printf("The file for a record was not opened!\n");

return;

}

// Запись размеров

fwrite((char*)&h, sizeof(int), 1, pFile);

fwrite((char*)&w, sizeof(int), 1, pFile);

printf("%d\n", ftell(pFile));

// Запись матрицы

fwrite((char*)A, sizeof(double), h*w, pFile);

printf("%d\n", ftell(pFile));

fclose(pFile);

printf("Ready...\n");

// Пауза

getchar();

// Чтение элемента матрицы a[i][j]

int i, j;

printf("Reading of an element of a matrix\n");

printf(" Number of a line: ");

scanf("%d", &i);

printf(" Number of a column: ");

scanf("%d", &j);

double Res=ReadFromFile("Matrix.dat", i, j);

printf("A[%d][%d]=%f\n", i, j, Res);

}

double ReadFromFile(char* FileName, int i, int j){

// Открытие файла для чтения

FILE* pFile=fopen(FileName, "rb");

if(!pFile){

printf("The file for reading was not opened!\n");

return 0;

}

// Чтение размеров

int h,w;

fread((char*)&h, sizeof(int), 1, pFile);

fread((char*)&w, sizeof(int), 1, pFile);

// Проверка правильности задания индексов

if(i<0||NumLine<=i){

printf("Number of a line is not correct!\n");

exit(-1);

}

if(j<0||NumCol<=j){

printf("Number of a column is not correct!\n");

exit(-1);

}

// Вычисление смещения

int offset=(i*NumCol+j)*sizeof(double)+2*sizeof(int);

// Чтение элемента

double x;

fseek(pFile, offset, 0);

fread((char*)&x, sizeof(double), 1, pFile);

fclose(pFile);

return x;

}

6.6 Запись и чтение строк

Для записи строки в файл можно воспользоваться стандартной функцией fputs() c прототипом

int fputs(

// Адрес строки

const char* szBuffer,

// Адрес структуры типа FILE

FILE* pFile);

Ее первый параметр является адресом записываемой в файл стоки, а второй - адресом структуры типа FILE, полученным при открытии файла. Так как ‘\0‘-символ, которым заканчивается каждая строка, функция fputs() в файл не записывает, то при создании текстовых файлов после ввода каждой строки программист должен предусмотреть запись символа ‘\n‘ - новая строка. Функция возвращает объект типа int. Его значение зависит от конкретной модели компилятора. Для MS Visual C++ 4.0, например, при успешном завершении функция возвращает ненулевое значение, а в остальных случаях - константу EOF.

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

Пример 6.7 - Создание текстового файла с клавиатуры

#include <stdio.h>

#include <process.h>

void main(void) {

// Буфер для записываемой в файл строки

char szBuffer[81];

// Открытие текстового файла для записи

FILE* pFile=fopen("MyFile.txt", "wt");

// Проверка корректности результата операции

if(!pFile) {

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

printf("The file to open it was not possible!\n");

return ;

}

// Действия при корректном открытии файла

while(1) {

// Предупреждение о вводе с клавиатуры

printf("Input of a string or command \”Enter!\” \n");

// Ввод строки или клавиши Enter с клавиатуры

gets(szBuffer);

// Анализ введенной информации

if(szBuffer[0]==(char)NULL) {

// Действия при нажатии Enter (вводе пустой строки)

printf("The file is created!\n");

break;

}

// Действия при вводе строки

else {

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

fputs(szBuffer, pFile);

// Запись в файл символа '\n'

fputc('\n', pFile);

}

}

// Закрытие файла

fclose(pFile);

}

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

char* fgets(

// Адрес буфера для читаемой строки

char* szBuffer,

// Число читаемых символов (байтов)

int n,

// Адрес структур типа FILE

FILE* pFile);

Ее первым параметром является адрес буфера, в который записывается читаемая строка. Второй параметр определяет максимальное количество читаемых из файла байтов, а третий - адрес структуры типа FILE*, полученный при открытии файла. Чтение из файла продолжается до тех пор, пока не наступит любое из следующих трех событий: будет прочитан символ ‘\n‘ - новая строка, будут прочитаны n-1 объектов типа char или будет достигнут конец файла. Концом текстового файла считается байт, содержащий константу EOF. После завершения чтения из файла к уже прочитанным байтам в буфер добавляется ‘\0‘-символ. Если n=1, то формируется пустая строка. При успешном завершении операции функция возвращает адрес буфера с прочитанной строкой, а в случае возникновения ошибки или достижения конца файла она возвращает NULL типа char*.

Пример 6.8 - Чтение из файлов строк заданной длины

#include <stdio.h>

#include <string.h>

// Прототип функции чтения текстовых файлов

int ReadTextFile(

// Строка с именем файла

const char* szFileName,

// Длина строки

int StrLen,

// Число строк на странице

int PageSize);

void main (void) {

// Имя файла для чтения

char szFileName[]="MyFile.txt";

// Длина строки

int StrLen=7;

// Число строк

int PageSize=2;

// Чтение из файла

int iResponse=ReadTextFile(szFileName, StrLen, PageSize);

// Анализ результата выполнения чтения

if(!iResponse)

printf("\nError!");

else

printf("\nOk\n");

}

// Определение функции ReadTextFile()

int ReadTextFile(const char* szFileName, int StrLen, int PageSize) {

// Буфер для прочитанных объектов

char* szBuffer=new char[StrLen+1];

// Открытие текстового файла для чтения

FILE* pFile=fopen(szFileName, "rt");

// Проверка корректности выполнения операции

if(!pFile)

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

return 0;

// Номер строки и страницы в документе

int LineCount=0, PageCount=0;

// Чтение строк в буфер

while(fgets(szBuffer, StrLen+1, pFile)>(char*)0){

// Анализ и коррекция строки

for(int i=0; (szBuffer[i]!='\n')&&(i<StrLen); i++);

// Пустой цикл

if(i==0)

// Действия при чтении пустой строки

continue;

if(szBuffer[i]=='\n')

// Укороченная строка

szBuffer[i]='\0';

// Вычисление и печать номера страницы

if(((LineCount+PageSize)/PageSize)>PageCount){

PageCount++;

printf("\n");

for(int k=0; k<StrLen; k++)

printf(" ");

printf("%d\n", PageCount);

}

LineCount++;

puts(szBuffer);

}

// Действия при достижении конца файла

fclose(pFile);

delete[] szBuffer;

return 1;

}

/*

8.4. Запись в файл и чтение из него объектов типа char

Для хранения объектов типа char требуется минимальный объем памяти равный одному байту. Для того, чтобы записать в файл объект типа char, можно воспользоваться стандартной функцией fputc() с прототипом

int fputc(

// Записываемый в файл объект

int c,

// Адрес структуры типа FILE

FILE* pFile);

Ее первым параметром является записываемый объект. В соответствии с правилами вызова функций ASCII-код записываемого объекта преобразуется к типу int. Вторым параметром является адрес структуры типа FILE, полученный при открытии файла. При успешном завершении функция возвращает ASCII-код записываемого символа, преобразованный к типу int. В остальных случаях возвращаемым значением будет константа EOF.

Пример 8.2. Запись в файл объектов типа char

#include <stdio.h>

#include <stdlib.h>

void main(){

// Текст для записи в файл: 22 символа, не считая ‘\0’-символа

char psz[]="Writing and computing\n";

// Открытие файла

FILE* pFile=fopen("Text.asc", "wt");

// Проверка

if(!pFile){

printf("Error! The file is not opened\n");

exit(1);

}

// Запись в файл

int i=0;

while(psz[i]!='\0')

// Запись символа

fputc(psz[i++], pFile);

// Длина файла

printf("FileLenght=%d\n", ftell(pFile));

// Закрытие файла

fclose(pFile);

}

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

FileLenght=23

Оно означает, что кроме 22 символов, записанных в файл прог­раммистом, там оказался еще один байт. Это связано с тем, что управляющая последовательность ‘\n’ при записи в текстовый файл заменяется парой из ‘\r’ и ‘\n’. Поскольку путь к файлу не был указан, то он будет создан в том же каталоге, в котором находится само приложение.

Для чтения из файла объектов типа char можно использовать стандартную функцию с именем fgetc() и прототипом

int fgetc(

// Адрес структуры типа FILE

FILE* pFile);

Ее единственным параметром является адрес структуры типа FILE, полученный при открытии файла. Функция возвращает ASCII-код прочитанного объекта типа char, преобразованный к типу int. При попытке чтения константы EOF или возникновении ошибки возвращается EOF.

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

int feof(

// Адрес структуры FILE

);

позволяющая определить достижение конца файла. Она возвращает отличное от нуля значение, если внутренний указатель файла совпадает с его длиной. В остальных случаях – нуль.

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

int getche();

Она возвращает ASCII-код введенного с клавиатуры символа, преобразованный к типу int, и отображает его на экране дисплея. При использовании функциональных клавиш или клавиш управления курсором для получения ASCII-кода необходимо вызывать функцию дважды. В качестве признака завершения ввода выбрана комбинация клавиш Ctrl+z c ASCII-кодом равным ‘\32’.

Пример 8.3. Запись объектов типа char и копирование файла

#include <stdio.h>

#include <stdlib.h>

#include <conio.h>

void main(){

// Открытие файла для записи и чтения

FILE* pSrc=fopen("Text.asc", "w+t");

// Проверка

if(!pSrc){

printf("Error! The file is not opened\n");

exit(1);

}

// Ввод и запись в файл

int ch;

printf("Input: ");

while((ch=getche())!='\32'){

// Запись символа

fputc(ch, pSrc);

}

printf("\n\n");

// Длина файла

printf("FileLenght=%ld\n", ftell(pSrc));

// Открытие файла для записи

FILE* pDest=fopen("Copy.asc", "wt");

if(!pDest){

printf("Error: not open file!\n");

exit(2);

}

// Подготовка к копированию

int temp;

rewind(pSrc);

// Копирование

while((temp=fgetc(pSrc))!=EOF)

fputc(temp, pDest);

// Закрытие

fclose(pSrc);

fclose(pDest);

printf("Ready\n");

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]