Главная страница
Навигация по странице:

  • Бинарные (двоичные)

  • Алгоритмизации


    Скачать 1.15 Mb.
    НазваниеАлгоритмизации
    Дата27.09.2022
    Размер1.15 Mb.
    Формат файлаdocx
    Имя файла12_100229_1_124427 (1).docx
    ТипДокументы
    #700459
    страница23 из 67
    1   ...   19   20   21   22   23   24   25   26   ...   67

    ГЛАВА 14. Файлы в языке Си



    Файл это набор данных, размещенный на внешнем носителе и рассматриваемый в процессе обработки как единое целое. В файлах размещаются данные, предназначенные для длительного хранения.

    Различают два вида файлов: текстовыеи бинарные.

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

    «перевод строки», «возврат каретки»: 13 и 10 (0xD и 0xA).

    Бинарные (двоичные)файлыпредставляют собой последовательность данных, структура которых определяется программно.

    В языке Си не предусмотрены никакие заранее определенные структуры файлов. Все файлы рассматриваются компилятором как последовательность (поток байт) информации.

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

    В языке Си имеется большой набор функций для работы с файлами, большинство которых находятся в библиотеках stdio.h и io.h. При этом потоки данных, с которыми работают функции ввода-вывода данных по умолчанию, буферизированы. Это означает, что при открытии потока с ним автоматически связывается определенный участок ОП, который и называется буфером. Все операции чтения-записи ведутся через этот буфер. Его размер фиксирован специальной константой BUFSIZ, которая определена в файле stdio.h как 512 (хотя программно ее можно изменять).

      1. Открытиефайла


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

    Формат объявления указателя на файл следующий:

    FILE*ID_указателя_на_файл;

    FILE идентификатор структурного типа, описанный в стандартной библиотеке stdio.h и содержащий следующую информацию:

    struct FILE {

    short level; – число оставшихся в буфере непрочитанных байт; обычный размер буфера 512 байт; как только

    level= 0, в буфер из файла читается следующий блок данных;

    unsigned flags; – флаг статуса файла– чтение, запись, дополнение; char fd; дескриптор файла, т.е. число, определяющее его

    номер;

    unsigned char hold; – непереданный символ, т.е. ungetc-символ; short bsize; – размер внутреннего промежуточного буфера;

    unsigned char buffer; значение указателя для доступа внутри буфера;

    задает начало буфера, начало строки или текущее значение указателя внутри буфера в зависимости от режима буферизации;

    unsigned char *curp; текущее значение указателя для доступа внутри

    буфера; задает текущую позицию в буфере для обмена с программой;

    unsigned istemp; – флаг временного файла; short token; – флаг при работе с файлом;

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

    Для этого обычно используется функция

    FILE* fopen(char * ID_файла, char *режим);

    Данная функция берет внешнее представление физическое имя файла на носителе (дискета, винчестер) и ставит ему в соответствие логическое имя (программное имя – указатель файла).

    Физическое имя, т.е. ID файла и путь к нему задается первым параметром– строкой, например, a:Mas_dat.dat – файл с именемMas_dat и расширением dat, находящийся на дискете, d:\\work\\Sved.txt – файл с именем Svedи расширением txt, находящийся на винчестере в каталоге work.

    Внимание. Обратный слеш «\», как специальный символ в строке записывается дважды.

    При успешном открытии функция fopen возвращает указатель на файл (в дальнейшем – указатель файла). При ошибке возвращается NULL. Данная ситуация обычно возникает, когда неверно указывается путь к открываемому файлу, например, если указать путь, запрещенный для записи.

    Второй параметр строка, в которой задается режим доступа к файлу.

    Возможные значения данного параметра следующие:

    w– файл открывается для записи (write); если файла с заданным именем нет, то он будет создан; если же такой файл уже существует, то перед открытием прежняя информация уничтожается;

    r файл открывается для чтения (read); если такого файла нет, то возникает ошибка;

    a файл открывается для добавления (append) новой информации в конец;

    r+ (w+) – файл открывается для редактирования данных, т.е. возможны и запись, и чтение информации;

    a+ – то же, что и дляa, только запись можно выполнять в любое место файла (доступно и чтение файла);

    t файл открывается в текстовом режиме;

    b файл открывается в двоичном режиме;

    Последние два режима используются совместно с рассмотренными выше. Возможны следующие комбинации режимов доступа: w+b”, wb+”, “rw+”, “w+t”, “rt+”, а также некоторые другие комбинации.

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

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

    Примероткрытия файла:

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

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

    FILE *f = fopen ("d:\\work\\Dat_sp.dat", "w");

      1. Закрытиефайла


    После работы с файлом доступ к нему необходимо закрыть с помощью функции

    intfclose(указательфайла);

    Например, для предыдущего примера файл закрывается так: fclose(f);

    Для закрытия нескольких файлов введена функция:

    voidfcloseall(void);

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

    FILE*freopen(char *ID_файла, char *режим, FILE *указатель_файла);

    которая сначала закрывает файл, заданный в третьем параметре (указатель файла), как это выполняет функция fclose, а затем выполняет действия, аналогичные функции fopen, используя указанные первый и второй параметры (открывает файл с ID_файла и правами доступа режим).

    В языке Си имеется возможность работы с временными файлами, которые нужны только в процессе работы программы и должны быть

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

    FILE*tmpfile(void);

    которая создает на диске временный файл с правами доступа w+b. После завершения работы программы или закрытия этого (временного) файла он автоматически удаляется.

      1. Запись-чтениеинформации


    Все действия по чтению-записи данных в файл можно разделить на три группы:

    • операции посимвольного ввода-вывода;

    • операции построчного ввода-вывода;

    • операции ввода-вывода по блокам.

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

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

    fprintf, fscanf, fgets, fputs.

    Формат параметров этих функций практически такой же, как и формат рассмотренных ранее (см. разд. 5.3, 5.4) функций printf, scanf, getsи puts. Так же практически совпадают и действия этих функций. Отличие состоит в том, что printf и другие функции работают по умолчанию с экраном монитора и клавиатурой, а функции fprintf и другие – с файлом, указатель которого является одним из параметров этих функций.

    Рассмотрим общий пример создания текстового файла: #include

    void main(void)

    {

    FILE *f1;

    int a=2, b=3;

    if( ! (f1 = fopen(“d:\\work\\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);

    }

    Просмотрев содержимое файла любым текстовым редактором, можно

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

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

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

    Такой способ обмена данными требует меньше времени.

    Функция

    unsignedfread(void*p, unsignedsize, unsignedn, FILE*f);

    выполняет считывание из файла f n блоков размером size байт каждый в область памяти, адрес которой p. В случае успеха функция возвращает количество считанных блоков. При возникновении ошибки или по достижении признака окончания файла значение EOF(EndOfFile– признак окончания файла).

    Обратное действие выполняет функция:

    unsignedfwrite(void*p, unsignedsize, unsignedn, FILE*f);

    при вызове которой в файл fбудет записано nблоков размером sizeбайт каждый из области памяти, начиная с адреса p.

      1. Позиционированиевфайле


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

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

    это последовательныйдоступкданным.


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

    Декларация функции позиционирования следующая:

    intfseek(FILE*f, longsize, intcode);

    Значение параметра size задает количество байт, на которое необходимо сместить указатель в файле f, в направлении параметра code, который может принимать следующие значения:


    смещение от начала файла

    0

    (SEEK_SET);

    смещение от текущей позиции

    1

    (SEEK_CUR);

    смещение от конца файла

    2

    (SEEK_END).

    Таким образом, смещение может быть как положительным, так и отрицательным, но нельзя выходить за пределы файла.

    В случае успеха функция возвращает нулевое значение, а в случае ошибки (например, попытка выхода за пределы файла) – единицу.

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

    называют произвольнымдоступом.

    Иногда нужно определить текущее положение в файле. Для этого используют функцию со следующей декларацией:

    longftell(FILE*f);

    которая возвращает значение указателя на текущую позицию в файле или –1

    в случае ошибки.

      1. Дополнительныефайловыефункции


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

    intfileno(FILE*f) определяет и возвращает значение дескриптора

    (fd) файла f, т.е. число, определяющее номер файла;

    longfilelength(intfd) возвращает длину файла, имеющего дескриптор fd , в байтах;

    int chsize (int fd, long pos) – выполняет изменение размера файла, имеющего номер fd, признак конца файла устанавливается после байта с номером pos;

    intfeof(FILE*f) возвращает ненулевое значение при правильной записи признака конца файла;

    intfgetpos(FILE*f, long*pos) определяет значение текущей позиции

    posфайла f.

    Примерпрограммыработысфайломструктур


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

    #include #include struct Sved {

    char Fam[30]; double S_Bal;

    } zap,zapt;

    char Spis[]="c:\\work\\Sp.dat"; FILE *F_zap;

    FILE* Open_file(char*, char*);

    void main (void)

    {

    int i, j, kodR, size = sizeof(Sved), kod_read; while(1) {

    puts("Создать 1\n Добавить– 3\nПросмотреть– 2\nВыход 0"); scanf("%d",&kodR);

    switch(kodR) {

    case 1: case 3:

    if(kodR==1) F_zap = Open_file (Spis,"w+"); else F_zap = Open_file (Spis,"a+");

    while(2) {

    puts("\n Fam (. end) ");

    scanf("%s",zap.Fam); if((zap.Fam[0])=='.') break; puts("\n Ball: "); scanf("%lf",&zap.S_Bal); fwrite(&zap,size,1,F_zap);

    }

    fclose(F_zap); break;

    case 2: F_zap = Open_file (Spis,"r+"); int nom=1; while(2) {

    if(!fread(&zap,size, 1, F_zap)) break; printf(" %2d: %20s %5.2lf\n",

    nom++, zap.Fam, zap.S_Bal);

    }

    fclose(F_zap); break;

    case 0: return; // exit(0);

    } // Закрывает switch()

    } // Закрывает while()

    }

    // Функция обработки ошибочной ситуации при открытии файла

    FILE* Open_file(char *file, char *kod)

    {

    FILE *f;

    if(!(f = fopen(file, kod))) { puts("Open File Error!"); exit(1);

    }

    return f;

    }

    Советыпопрограммированию


    При выполнении вариантов заданий придерживайтесь следующих

    ключевых моментов.

    1. Объекты типов структуры и объединения применяются для логически связанных между собой данных различных типов.

    2. После описания шаблона структурного типа данных ставится точка с запятой.

    3. Элементы данных, входящие в структуры и объединения, называются полями. Поля могут быть любого базового (стандартного) типа данных, массивом, указателем, объединением или структурой.

    4. Для обращения к полю используется операция принадлежности (привязки, выбора) «.» (точка) при обращении через IDструктуры, или «–>» (стрелка) при обращении через указатель.

    5. Структуры одного типа можно присваивать друг другу с использованием стандартной функции memcpy.

    6. Ввод-вывод структур выполняется поэлементно.

    7. Структуры, память под которые выделяет компилятор, можно инициализировать значениями их полей.

    8. Файл это именованный объект, хранящий данные на каком-либо носителе, хотя может располагаться и на электронном диске в ОП.

    9. Файл не имеет фиксированной длины, т.е. может увеличиваться или уменьшаться в процессе обработки.

    10. Перед работой файл необходимо открыть (функция fopen), а после работы закрыть (функция fclose).


    1   ...   19   20   21   22   23   24   25   26   ...   67


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