Главная страница

Лекции Булатицкий Дмитрий Иванович (во многом по материалам Прасолова А. Н.)


Скачать 319.62 Kb.
НазваниеЛекции Булатицкий Дмитрий Иванович (во многом по материалам Прасолова А. Н.)
Дата11.01.2022
Размер319.62 Kb.
Формат файлаdocx
Имя файлаLecture_Programming_2021_09_01.docx
ТипЛекции
#328427
страница21 из 36
1   ...   17   18   19   20   21   22   23   24   ...   36

Работа с текстовыми файлами


Для работы с текстовым файлом его открывают с параметром открытия файла, содержащим постфикс «t» (впрочем, он подразумевается по умолчанию и, если не написать никакого суффикса типа файла, то файл будет открыт как текстовый).

Для работы с текстовыми файлами предназначены функции, аналогичные функциям для работы со стандартным устройством ввода/вывода, и отличаются от них наличием дополнительного аргумента: указателя на дескриптор файла. Вот список основных функций для работы с текстовыми файлами:

int fprintf (FILE *stream, const char *template, ...);

int fscanf (FILE *stream, const char *template, ...);

int fgetc (FILE*);

char*fgets (char*, int, FILE*);

int fputc (int, FILE*);

int fputs (const char*, FILE*);
Допустим, у нас есть файл, содержащий такое описание объектов:

apples 10 23.4

bananas 5 25.0

bread 1 10.3
Тогда, чтобы считать эти данные, мы можем написать такую программу:

#include

main () {

FILE *file;

struct food {

char name[20];

unsigned qty;

float price;

};

struct food shop[10];

char i=0;

file = fopen("fscanf.txt", "rt");

while (fscanf (file, "%s%u%f", shop[i].name, &(shop[i].qty), &(shop[i].price)) != EOF) {

printf("%s %u %.2f\n", shop[i].name, shop[i].qty, shop[i].price);

i++;

}

}


int feof (FILE *stream) The feof function returns nonzero if and only if the end-of-file indicator for the stream stream is set.
int fseek(

FILE *stream,

long offset,

int origin

);

int _fseeki64(

FILE *stream,

__int64 offset,

int origin

);
If successful, fseek and _fseeki64 returns 0. Otherwise, it returns a nonzero value.

SEEK_CUR

SEEK_END

SEEK_SET


    1. Работа с двоичными файлами


Для работы с двоичным файлом его открывают с параметром открытия файла, содержащим постфикс «b».

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

size_t fread(void *буфер, size_t колич_байт, size_t счетчик, FILE *уф);

size_t fwrite(const void *буфер, size_t колич_байт, size_t счетчик, FILE *уф);
Для fread() буфер — это указатель на область памяти, в которую будут прочитаны данные из файла. А для fwrite() буфер — это указатель на данные, которые будут записаны в файл. Значение счетчик определяет, сколько считывается или записывается элементов данных, причем длина каждого элемента в байтах равна колич_байт. (Вспомните, что тип size_t определяется как одна из разновидностей целого типа без знака.) И, наконец, уф — это указатель файла, то есть на уже открытый поток.

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

Как только файл открыт для работы с двоичными данными, fread() и fwrite() соответственно могут читать и записывать информацию любого типа. Например, следующая программа записывает в дисковый файл данные типов double, int и long, a затем читает эти данные из того же файла. Обратите внимание, как в этой программе при определении длины каждого типа данных используется функция sizeof().
/* Запись несимвольных данных в дисковый файл

и последующее их чтение. */

#include

#include
int main(void)

{

FILE *fp;

double d = 12.23;

int i = 101;

long l = 123023L;
if((fp=fopen("test", "wb+"))==NULL) {

printf("Ошибка при открытии файла.\n");

exit(1);

}
fwrite(&d, sizeof(double), 1, fp);

fwrite(&i, sizeof(int), 1, fp);

fwrite(&l, sizeof(long), 1, fp);
rewind(fp);
fread(&d, sizeof(double), 1, fp);

fread(&i, sizeof(int), 1, fp);

fread(&l, sizeof(long), 1, fp);
printf("%f %d %ld", d, i, l);
fclose(fp);
return 0;

}

Как видно из этой программы, в качестве буфера можно использовать (и часто именно так и делают) просто память, в которой размещена переменная. В этой простой программе значения, возвращаемые функциями fread() и fwrite(), игнорируются. Однако на практике эти значения необходимо проверять, чтобы обнаружить ошибки.

Одним из самых полезных применений функций fread() и fwrite() является чтение и запись данных пользовательских типов, особенно структур. Например, если определена структура:

struct struct_type {

float balance;

char name[80];

} cust;

то следующий оператор записывает содержимое cust в файл, на который указывает fp:
fwrite(&cust, sizeof(struct struct_type), 1, fp);
В качестве дополнительного примера удобства использования рассмотрим функции для записи массива целых чисел и массива пользовательских структур в файл.
// Сохраняет n элементов массива arr в файл с именем fname. Файл очищается

// перед сохранением данных.

// Функция возвращает количество удачно записанных элементов массива

int SaveArrayToBinFile(int *arr, int n, char const *fname)

{

FILE *fp;

fp=fopen(fname, "wb");

if(fp==NULL) return 0;

return fwrite(arr, sizeof(arr[0]), n, fp);

}
// Сохраняет n элементов массива arr в файл с именем fname. Файл очищается

// перед сохранением данных.

// Функция возвращает количество удачно записанных элементов массива

int SaveArrayToBinFile(MyStruct *arr, int n, char const *fname)

{

FILE *fp;

fp=fopen(fname, "wb");

if(fp==NULL) return 0;

return fwrite(arr, sizeof(arr[0]), n, fp);

}
Загрузка из подобных файлов может осуществляться как поэлементно, так и целиком:

// Загружает n элементов в буфер arr из файла с именем fname.

// Функция возвращает количество удачно прочитанных элементов массива

int LoadArrayFromBinFile(int *arr, int n, char const *fname)

{

FILE *fp;

fp=fopen(fname, "rb");

if(fp==NULL) return 0;

return fread(arr, sizeof(arr[0]), n, fp);

}
// Загружает n элементов в буфер arr из файла с именем fname.

// Функция возвращает количество удачно прочитанных элементов массива

int LoadArrayFromBinFile(MyStruct *arr, int n, char const *fname)

{

FILE *fp;

fp=fopen(fname, "wb");

if(fp==NULL) return 0;

return fwrite(arr, sizeof(arr[0]), n, fp);

}
Преимуществом двоичной работы с файлами является не только удобство работы и компактность файла, но и эффективность: ведь не приходится тратить время на преобразование из внутреннего представления данных в текстовый вид и обратно.
  1. 1   ...   17   18   19   20   21   22   23   24   ...   36


написать администратору сайта