Будь умным!


У вас вопросы?
У нас ответы:) SamZan.net

Файлы а Общие понятия о файлах Данные размещаемые программой в памяти компьютера исчезают при выключе

Работа добавлена на сайт samzan.net: 2015-07-05

Поможем написать учебную работу

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

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 21.5.2024

11. Файлы

а) Общие понятия о файлах

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

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

Под файлом понимается поименованная область памяти на внешнем носителе, предназначенная для хранения информации. Файл может быть связан с любым источником или потребителем информации (диском, принтером, клавиатурой и т.д.). В операционной системе файл имеет имя соответственно внешнему носителю. Например, на диске некоторый исполняемый файл может иметь имя  C:\Kurs1\Prog1.exe. Это имя файла в операционной системе.

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

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

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

Файл имеет много общего со статическим одномерным массивом, только размещается он не в оперативной, а во внешней памяти и не требует предварительного указания размера.

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

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

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

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

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

В языке С формат файлов ввода-вывода описан в заголовочном файле stdio.h. В момент выполнения программы на языке С автоматически открываются три потока: stdin (стандартный ввод, назначается клавиатура), stdout (стандартный вывод, назначается экран), stderr (выходной поток ошибок, обычно это экран).

С++ поддерживает всю систему ввода-вывода С и добавляет к ней дополнительные возможности, связанные с тем, что поток в С++ - это объект. Описание средств для создания потоков в С++ представлено в заголовочном файле iostream.h. Когда начинает работать программа на С++, открываются потоки cin (стандартный ввод – клавиатура), cout (стандартный вывод – экран), cerr (стандартная ошибка – экран).

Файловая система языков С и С++ состоит из двух уровней файлов: физических (диск, клавиатура, экран) и логических (в оперативной памяти компьютера).

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

Логический файл в С описывается как указатель на открываемый поток FILE * и служит средством взаимодействия с физическим файлом. Имя физического файла появляется в программе один раз, в тот момент когда происходит открытие файла, осуществляемое функцией fopen( ), и одновременно его связывание с логическим файлом. Понятие файла в оперативной памяти компьютера приобретает смысл только после его связи с внешним физическим файлом.

При работе с файлами можно использовать константы, определенные в stdio.h, например,

EOF – признак конца файла (EOF = -1);

NULL – значение указателя, которое не содержит адреса объекта

б) Текстовые файлы

Текстовый файл трактуется как совокупность строк переменной длины, причем в конце каждой строки стоит признак ее конца EOLN ( End Of Line – конец строки), а в конце всего файла – признак EOF (End Of File – конец файла). Эти признаки можно протестировать одноименными логическими функциями. При формировании текстовых файлов используются следующие системные соглашения:

EOLN – последовательность кодов #13 и #10;

EOF – код #26.

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

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

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

fopen (“имя_файла”, “режим_доступа”);

Режимы доступа приведены в таблице:

режим

описание

r

Открыть файл только для чтения, модификации файла запрещены

w

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

a

Открыть файл для дозаписи. Если файла с указанным именем не существует, он будет создан

r+

Открыть существующий файл для чтения и записи

w+

Создать новый файл для чтения и записи

a+

Открыть существующий файл для дозаписи и чтения

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

Пример – открыть текстовый файл для чтения

FILE *ft;                                                // объявили указатель на файловый поток

ft = fopen(“f1.txt”, “r”);                     // открыли файл f1.txt в текущем каталоге

При попытке открыть существующий файл можно допустить ошибку в его имени или в указании пути к файлу. Это вызовет ошибку исполнения программы. Необходимо осуществлять проверку возможности открытия файла. Такую проверку осуществлять легко, так как функция fopen() возвращает значение указателя файла в случае его успешного открытия и значение NULL (специальный нулевой указатель), если доступ к файлу невозможен. Поэтому достаточно написать:

if ((ft = fopen(“f1.txt”, “r”)) != NULL)

 {  // обработка файла

  }

Файлы, открываемые в режиме записи, также нуждаются в аналогичной проверке.

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

Форматный ввод-вывод данных текстовых файлов

 Форматный вывод данных осуществляется с помощью функций printf() – для стандартного потока – вывода на экран,  fprintf() – для вывода данных в текстовый файл.

Формат printf( ) в общем виде:

printf(Control, arg1, arg2, …, argN);

Control – строка символов, заключенная в двойные кавычки, определяющая формат вывода, здесь могут быть указания на формат переменных arg1, arg2, … и остальные символы, которые выводятся без всякого форматирования.

Обозначения формата всегда начинаются с символа %, а заканчиваются символом типа форматирования:

d – для переменной типа int,

f – для переменных типа float,

s – для строк символов.

Между символом % и символом типа форматирования задается ширина поля вывода, количество знаков после точки (для вещественных) и так далее. Полное определение форматов можно посмотреть в справочниках.

Примеры.

printf(“Hello!\n”);

printf(“%4d %6.1f\n”, a1, b1);

Здесь \n – специальный символ (управляющий символ), он не имеет экранного отображения и используется для управления процессами. В данном случае \n служит для выбрасывания буфера функции printf() на экран и установки указателя строки экрана в начало следующей строки.

В первом примере на экран выводится Hello!

Во втором примере выводится значение целой переменной a1, под которую отводится 4 позиции и значение вещественной переменной b1, под которую отводится 6 позиций, причем 1 позиция – для вещественной части после точки.

Формат форматного вывода в файл:

fprintf(f, Control, arg1, arg2, …, argN);

Здесь f – указатель файлового потока, в который записывается информация. Смысл остальных параметров такой же, как и для функции printf().

Форматный ввод данных осуществляется с помощью функций scanf() – для стандартного потока – ввода c клавиатуры,  fscanf() – для чтения данных из текстового файла.

Формат scanf( ) в общем виде:

scanf(Control, arg1, arg2, …, argN);

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

Смысл строки Control тот же, что и для функции printf(). Так как arg1, arg2, … - фактические параметры функции, то при обращении к функции они должны задаваться своими адресами: имена массивов – своими именами, так как имена массивов – это указатели на их первые элементы, а те аргументы, которые не являются указателями, задаются как &arg.

Спецификация формата функции имеет вид:

% [*] [ширина] символ формата.

Здесь * - символ подавления ввода. Весь входной поток рассматривается как совокупность полей ввода. Если в спецификации указана *, то все поле, которое в данный момент обрабатывается функцией по заданному формату, пропускается.

Пример.

int i;

float x;

char m[100];

На клавиатуре набираем последовательность:

56 789 0123 45a72 и нажимаем <Enter>. Выполняем

scanf(“%2d %f %*d %2s”, &i, &x, m);

Функция выбирает первые два символа, интерпретирует их как целое число и присваивает значение первому аргументу:

i = 56.

Второй аргумент получит значение

x = 789.

Далее должно обрабатываться поле 0123 по третьему формату, но в формате есть символ подавления, поэтому поле пропускается. Далее получает значение массив:

m – два символа 4 и 5.  

Формат форматного ввода из файла:

fscanf(f, Control, arg1, arg2, …, argN);

Здесь f – указатель файлового потока, из которого читается информация. Смысл остальных параметров такой же, как и для функции scanf(). Функция fscanf (так же, как и scanf) возвращает количество удачно считанных чисел. Иногда имеет смысл ее использовать как

n = fscanf(…); // n – количество считанных чисел

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

Можно использовать функцию fcloseall() для закрытия всех открытых в программе файлов. У данной функции пустой список аргументов.

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

Пример.

#include <stdio.h>

void main()

{  FILE *f;

   int dig;

   if ((f = fopen(“f1.txt”, “r”)) == NULL)  

      {  printf(“Невозможно открыть файл!\n”);

          exit(0);

       }

   fscanf(f, “%d”, &dig);            // считать значение dig из файла

   fclose(f);                                 // закрыть файл

   f = fopen(“f2.txt”, “w”);         // открыть файл для записи

   fprintf(f, “Прочитали число %d”, dig);

   fclose(f);                                  // закрыть файл

}

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

Строко - ориентированный ввод-вывод

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

Пример.

#include <stdio.h>

void main()

{  char s[80];

   FILE *fp;

   fp = fopen(“input.dat”, “r”);

   fscanf(fp, “%s”, s);

   printf(“Первое слово файла -%s”, s);

   fclose(fp);

}

Существуют стандартные функции ввода-вывода символов через поток и ввода-вывода строк через поток, причем это могут быть как стандартные потоки ввода-вывода stdin (ввод с клавиатуры) и stdout (вывод на экран), так и файловые потоки.

Для ввода символов из потока stdin используется функция, прототип которой имеет вид:

int getchar(void);

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

int fgetc(FILE *stream);  // из файла

Функция считывает один символ  из файла. В случае ошибки ввода-вывода функция возвращает значение EOF.

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

int putchar(int c);

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

int fputc(int c, FILE *stream);  // в файл

Функция выводит в соответствующий поток символ с. В случае ошибки ввода-вывода функция возвращают значение EOF.

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

char *gets(char *s, int n);    // ввод строки с клавиатуры

char *fgets(char *s, int n, FILE *stream);       // чтение из файла

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

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

int puts(const char *s);                       // вывод строки на экран

int fputs(const char *s, FILE *stream);        // вывод строки в файл

Терминальный символ строки (завершающий ноль) не выводится.

Пример 1.

#include <stdio.h>

#include <string.h>

int main ()

{  FILE *pfs;

   char rbuf[127] = “”;

   pfs = fopen(“dat.txt”, “wt”);

   fputs(strcpy(rbuf, “Пример работы с файлом.\n”), pfs);

   fputs(strcpy(rbuf, “Последняя строка файла.\n”), pfs);

   puts(“Произведена запись в файл dat.txt двух строк.”);

   fclose(pfs);

   pfs = fopen(“dat.txt”, “rt”);

   puts(“\nСодержимое файла dat.txt:”);

   while (!feof(pfs))

     { fgets(rbuf, sizeof(rbuf) – 1, pfs);

        printf(“очередная строка: %s”, rbuf);

      }

    fclose(pfs);

    puts(“\nКонец программы”);

    return 0;

}

Пример 2.

В каждой строке файла input.txt заменить все буквы “А” на “Б” и вывести измененный текст в файл output.txt.

#include <stdio.h>

int main ()

{  FILE *fin, *fout;

   char s[80];

   int I;

   fin = fopen(“input.txt”, “r”);

   fout = fopen(“output.txt, “w”);

   while (fgetc(s, 80, fin) != NULL)    // читаем строку

   {  i = 0;  // начинаем обрабатывать строку с s[0]

       while (s[i] != ‘\0)   // пока не конец строки

       {   if (s[i] == ‘А’) s[i] = ‘Б’;    // меняем символ

            i++;             // переходим к следующему символу

        }

        fprintf(fout, “%s”, s);       // выводим строку в файл

     }

   fclose(fin);

   fclose(fout);

    return 0;

}

в) Двоичные файлы

Текстовые файлы не являются единственно возможным способом хранения информации на диске. Можно запоминать информацию в двоичном (бинарном) виде.

Способ хранения двоичных данных в файлах имеет два важных преимущества:

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

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

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

Открыть файл для бинарной обработки можно посредством вызова функции fopen(), но ко всем режимам доступа добавляют строчную латинскую букву b. Режимы доступа одинаковы для текстовых и двоичных файлов.

FILE *fb = fopen(“bin_f.dat”, “wb”);   - откроет файл для записи в двоичном режиме

FILE *fb = fopen(“bin_f.dat”, “r + b”);   - откроет файл для чтения и записи

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

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

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

Последовательный доступ к элементам двоичных файлов

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

Функция ввода данных из файла (чтения из файлового бинарного потока) имеет такой прототип:

int fread (void *ptr, unsigned size, int k, FILE *stream);

Здесь ptr – указатель переменной любого типа, в которую читается запись,

         size – длина записи в байтах,

         k – количество считываемых записей размером size,

         stream – имя указателя, связанного с бинарным файлом.

Функция fread читает k записей длины size из входного потока stream и помещает их в заданный буфер – массив или структуру. После этого указатель файла, связанный с потоком stream, увеличивается на количестве прочитанных байтов = size*k.

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

Вывод записей производится функцией fwrite(), прототип которой:

int fwrite (const void *ptr, unsigned size, int k, FILE *stream);

Назначение формальных параметров этой функции аналогично параметрам функции fread(). Функция выводит r записей из переменной *ptr в файл, связанный с указателем stream. Указатель файла, связанный с потоком stream, увеличивается на количество выведенных байтов.

Возвращаемое значение – количество записей, реально помещенных в файл, оно может быть меньше k, если имела место ошибка.

Пример

Записать в двоичный файл массив целых, случайно выбранных чисел.

#include <stdio.h>

#include <stdlib.h>

void main()

{  FILE *f_out;

   int number[20];

   f_out = fopen(“int.dat”, “wb”);

   if (!f_out)

     { puts(“Нельзя создать файл!\n”);

        exit(1);

      }

    for (int i = 0; i < 20; i++)

      number[i] = rand() %10 – 50;

    fwrite(&number, sizeof(int), 20, f_out);

    fclose(f_out);

}

Это оптимальный способ доступа с точки зрения скорости записи массива на диск.

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

К файлам с произвольным доступом предъявляется одно обязательное требование: их компоненты должны иметь одинаковую длину. Об этом следует позаботиться в момент создания файла.

Для организации произвольного доступа используют функцию fseek(), ее прототип:

int fseek (FILE *stream, long offset, int nach);

Здесь stream – указатель файлового потока,

          offset – смещение указателя в байтах относительно начала, заданного параметром nach,

           nach – начальная точка, от которой производится смещение.

Функция перемещает указатель файла, связанный с потоком stream, на новое место, которое определяется значениями offset и nach. Следующая операция ввода-вывода будет выполнена, начиная с той позиции, на которую будет перемещен указатель.

Параметр nach может иметь значение одной из следующих констант:

значение

описание

SEEK_SET

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

SEEK_END

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

SEEK_CUP

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

При использовании функции fseek() следует соблюдать осторожность, так как попадание за пределы файла может не приводить к генерации ошибок.

Положение курсора в файле можно определить с помощью функции feof():

int feof (FILE *stream);

Возвращаемое значение функции:

  •  нуль, если конец файла  достигнут,
  •  не нуль, если конец файла не достигнут.  

 

 

PAGE  9




1. политология этимологически образован сочетанием двух греческих слов- politike ~ государственные дела и logos ~ з
2. Тема- Республика как форма государственного правления Руководитель- подполковник юстиции Л
3. Система применения удобрений
4. вариант сочинения- Многие художники изображали зиму но лишь Нисский решился на необычный эксперимент ~ он пе
5. Реферат- Специфика анализа Интернет-контента
6. Способи картометричних робіт
7. Tests дававшей отцу римской семьи право ldquo;распоряжатьсяrdquo; жизнью своих детей как жизнью рабов; он им ее ldquo
8. The socialist workers party 1951-1979
9. I Актуальность темы
10. Биогенные элементы в организме человека.html
11. 10 знаменитых большевико
12.  Поняття про волю
13. Проблемы борьбы с терроризмом
14.  Союз Советских Социалистических Республик продолжает существовать деюре
15. логическая операция перехода от родового понятия к видовому например ldquo;поэтrdquo; ldquo;великий поэтrdquo; ldq
16. тематические формулы
17. Конституционное разграничение законодательной компетенции между федерацией и её субъектами в Соединенных Штатах Америки и Германии
18. Реферат- Классическая философия
19. нафтові чи синтетичні оливи 3 Як називаються пластичні мастила загушені натрієвим милом консталіни 4 Як
20. Эффективность функционирования органов муниципального образования