Работа с файлами данных в Pascal

Автор: Пользователь скрыл имя, 28 Декабря 2011 в 12:54, реферат

Описание работы

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

Работа содержит 1 файл

Документ Microsoft Office Word (4).docx

— 64.43 Кб (Скачать)
  • Оператор Read (F: File of AnyType; value1, value2,...: AnyType) считывает очередные компоненты файла F в переменные value1, value2,... соответствующего типа по порядку.
  • Оператор Write (F: File of AnyType; value1, value2,...: AnyType) записывает в файл F набор значений из переменных value1, value2,... в порядке перечисления.

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

 
  program Example;

(******************************************************

* Задача: скопировать  все отрицательные  числа из      *

* одного файла вещественных  чисел в другой.           *

******************************************************)   

var

  SrcFile, DestFile: File of real; {файл-источник и файл-результат}

  SrcFileName, DestFileName: string; {имена файлов}

  nextelem: real; {следующий компонент файла}

  ask: char 

(******************************************************

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

вещественными числами в заданном диапазоне

******************************************************)

procedure CreateFileOfReal;

var

  i, num: word;

  min, max, value, sign: real;

begin

  Rewrite(SrcFile); {открываем файл на запись}

  writeln('Введите количество компонентов файла '); readln(num);

  writeln('Введите нижнюю границу значений '); readln(min);

  writeln('Введите верхнюю границу значений '); readln(max);

  {если перепутаны границы, меняем их}

  if min>max then begin

    value:= min;

    min:= max;

    max:= value;

  end;

  {заполняем файл значениями}

  for i:=1 to num do begin

    value := random*(max-min)+min;

    sign := random;

    if sign>=0.5 then

      value := -value;

    write (SrcFile, value); {запись компонента в файл}

  end;

  Close(SrcFile); {закрываем файл - все данные сохранены}

end 

begin

  writeln('Введите имя исходного файла '); readln(SrcFileName);

  Assign(SrcFile, SrcFileName);

  writeln('Нужно ли предварительно заполнить его? (д/н)'); readln(ask);

  if (ask='y')or(ask='Y')or(ask='д')or(ask='Д') then

    CreateFileOfReal;

  writeln('Введите имя файла-результата '); readln(DestFileName);

  Assign(DestFile, DestFileName);

  {открываем файлы}

  {$I-}

  Reset(SrcFile);

  {$I+}

  if IOResult<>0 then begin

    writeln('Ошибка: невозможно открыть исходный файл.');

    exit;

  end;

  Rewrite(DestFile);

  {собственно копирование значений}

  while not EOF(SrcFile) do begin

    read (SrcFile, nextelem);

    write ('Следующее значение = ',nextelem:8:3);

    if nextelem<0 then begin

      write (DestFile, nextelem);

      writeln (' - копируем');

      end

    else

      writeln(' - не копируем');

  end;

  {закрываем оба файла - сохраняем данные}

  Close (SrcFile);

  Close (DestFile);

end.

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

 
repeat

  writeln('Введите имя копируемого файла '); readln(SrcFileName);

  Assign(SrcFile, SrcFileName);

  {$I-}

  Reset(SrcFile);

  {$I+}

  errcode:=IOResult;

  if errcode<>0 then

    writeln('Ошибка: невозможно открыть исходный файл. Повторите ввод.');

until (errcode=0);

Обратите внимание, что мы сохраняем значение IOResult в  дополнительной переменной errcode. Дело в том, что после опрашивания  системная переменная обнуляется, а  в нашем фрагменте ее значение используется в двух местах.

Ввод-вывод  для текстовых  файлов

Текстовый файл состоит из символов, организованных по строкам.

Операторы Read (F, x1, х2, ...) и Readln (F, x1, х2, ...) считывают из текстового файла F следующие от курсора значения в переменные х1, х2 и т.д. При этом Read считывает информацию и оставляет курсор на следующем байте, а Readln после ввода переводит курсор на начало следующей строки текстового файла, причем делает это и в том случае, если в предыдущей строке остались непрочитанные данные.

Например:

 
while not EOF (TextFile) do begin

  Read (TextFile, char1, char2); {считаем, что charN имеет тип char}  

n  Readln (TextFile, char3);

end;

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

Функция EOLn (F) : boolean - возвращает TRUE, если курсор в файле F стоит на символе конца строки #13. Эта функция используется только для текстовых файлов.

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

 
program Example;

(******************************************************

* Задача: вывести все  русские буквы  из текстового     *

* файла на экран                                       *

******************************************************)   

const

  RusLetters : set of char = ['а'..'п','р'..'я','А'..'Я'];

var

  TextFile: Text;

  TextFileName: string;

  ch: char;

  errcode: integer 

begin

  {вводим имя исходного файла}

  repeat

  writeln('Введите имя исходного файла '); readln(TextFileName);

  Assign(TextFile, TextFileName);

  {$I-}

  Reset(TextFile);

  {$I+}

  errcode:=IOResult;

  if errcode<>0 then

    writeln('Ошибка: невозможно открыть исходный файл. Повторите ввод.');

  until (errcode=0);   

  {выводим русские буквы}

  while not EOF (TextFile) do begin

    while not EOLn (TextFile) do begin

      Read (TextFile, ch);

      if ch in RusLetters then

        write(ch);

    end;

    Readln (TextFile);

  end;

end.

Как видите, каждую строку мы обрабатываем посимвольно  до конца, а затем переходим на следующую строку оператором Readln.

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

Правила ввода  информации из текстового файла:

  1. Аргументы операторов Read и Readln могут иметь целочисленный, вещественный, символьный, строковый тип или совместимые с ними. Сложные структурированные типы (массивы, множества, записи) вводятся только по элементам.
  2. При вводе числовых значений два числа считаются разделенными, если между ними есть хоть один пробел, символ табуляции (#9) или символ конца сроки (#13). Последовательность символов от текущего положения курсора до следующего разделителя преобразовывается в число, соответствующее типу переменной. Если такое преобразование невозможно, произойдет сбой. 
    Например, пусть первая строка текстового файла равна: '3.1415926 -38 Х'. Объявим переменные:
     
    var

      IntValue: integer;

      RealValue: real;

      CharValue: char;

  1. И введем значения этих переменных из файла:
     
    Reset (F);

    Readln (F, RealValue, IntValue, CharValue);

    Writeln (RealValue,' ', IntValue,' ', CharValue);

  1. На экран выведется следующее:
    3.1415926000Е+00 -38 Х
  1. При вводе символа никакие разделители не учитываются: в переменную запишется символ, на котором стоит файловый курсор, даже если это символ конца строки.
  2. Строковое значение вводится с позиции курсора. Считывание продолжается, пока количество символов не станет большим объявленного для строковой переменной или пока не встретится символ конца строки. Сам символ конца строки в переменную не записывается. 
    Например, пусть первая строка текстового файла такова: 'На всякого мудреца довольно простоты.'. Объявляем переменные:
     
    var

      str1: string;

      str2: string[18];

  1. Фрагмент программы последовательно вводит содержимое этой строки в обе переменные:
     
    Reset (F);

    Readln (F, str1);

    Reset (F);

    Readln (F, str2);

  1. После выполнения этих операторов строка str1 будет равна 'На всякого мудреца довольно простоты.' (ввод, пока не закончилась строка файла), а str2 - 'На всякого мудреца' (ввод, пока позволяет длина строковой переменной).

Как видно, Read и Readln применительно к текстовому файлу данных и консоли (вводу  с клавиатуры) действуют практически  одинаково.

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

 
program Example;

(******************************************************

* Задача: дан текстовый  файл, содержащий  программу на *

* некотором языке,  в котором один  оператор занимает   *

* строго одну строку. Проверить ее на  правильность    *

* скобочных конструкций.                              *

******************************************************)   

var

  Prg : text; {обрабатываемый файл}

  FileName : string;

  Opened, Closed : byte; {количество левых и правых скобок}

  StrNum: word; {номер строки}

  ch : char;

  ErrCode: integer 

begin

  writeln('Программа решает следующую задачу:');

  writeln('Дан текстовый файл, содержащий программу на ');

  writeln('некотором языке, в котором один оператор занимает');

  writeln('строго одну строку. Проверить ее на правильность');

  writeln('скобочных конструкций.');

  writeln;  

  repeat

    write('Введите имя проверяемого файла ');

    readln(FileName);

    Assign(Prg, FileName);

    {$I-}

    Reset(Prg);

    {$I+}

    ErrCode:= IOResult;

    if ErrCode<>0 then

      writeln('Ошибка: невозможно открыть файл. Повторите ввод.');

  until ErrCode=0 

  writeln('Проверяется файл "',FileName,'" :');

  StrNum:=1;

  while not EOF(Prg) do begin

    Opened:=0;

    Closed:=0;

    {считаем левые и правые скобки}

    while not EOLN(Prg) do begin

      read(Prg, ch);

      if ch='(' then

        Opened:=Opened+1

      else if ch=')' then

        Closed:=Closed+1;

    end;

    {проверяем их соответствие}

    if Opened>Closed then

      writeln('В [',StrNum,'] строке не хватает ',Opened-Closed,

              ' закрывающих скобок')

    else if Closed>Opened then

      writeln('В [',StrNum,'] строке не хватает ',Closed-Opened,

              ' открывающих скобок');

    readln(Prg); {переходим на следующую строку}

    StrNum:=StrNum+1;

  end;

  Close(Prg);

end.

Информация о работе Работа с файлами данных в Pascal