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

Книга Лекции Паскаль

.pdf
Скачиваний:
18
Добавлен:
24.02.2016
Размер:
902.53 Кб
Скачать

Василькова И.В.

Лекции

Паскаль

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

8.1. Подпрограммы для работы со всеми типами файлов

Процедуры

assign(var f; filename : string)

Связывает логический файл f с физическим файлом, имя которого задано в строке filename.

close(var f)

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

erase(var f)

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

rename(var f; newname : string)

Переименовывает физический файл на диске, связанный с логическим файлом f.

reset(var f)

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

rewrite(var f)

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

Функции

eof(var f) : boolean

Возвращает значение true, если при чтении достигнут конец файла.

IOresult : integer

Возвращает целое число, соответствующее коду последней ошибки вводавывода. При нормальном завершении операции функция вернет значение 0. Функция IOresult работает только с ключом компиляции {$I-}.

41

Василькова И.В.

Лекции

Паскаль

8.2. Текстовые файлы

Текстовый файл представляет собой последовательность строк символов переменной длины. Каждая строка заканчивается символами перевода строки и возврата каретки (их коды: 13 и 10). Эти символы вставляются в физический файл при нажатии клавиши Enter. При чтении файла эти символы воспринимаются как разделитель.

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

append(var f)

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

read(f, список) readln(f, [список])

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

Процедуры записи в текстовый файл:

write(f, список) writeln(f, [список])

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

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

8.3. Бестиповые файлы

Бестиповые файлы предназначены для хранения участков оперативной памяти на внешних носителях. После описания файловой переменной

var имя : file;

ее требуется связать с физическим файлом с помощью процедуры assign. Чтение и запись производится через буфер "порциями", равными размеру буфера. Размер буфера, отличающийся от стандартного (128 байт), можно задать при открытии файла вторым параметром процедур reset и rewrite:

reset(var f : file; bufsize : word) rewrite(var f : file; bufsize : word)

Размер буфера должен находиться в пределах от 1 до 64 Kбайт.

Собственно чтение и запись выполняются с помощью процедур blockread и blockwrite:

blockread(var f : file; var x; count : word; var num : word); blockwrite(var f : file; var x; count : word; var num : word);

42

Василькова И.В.

Лекции

Паскаль

Процедура blockread считывает в переменную x количество блоков count. Длина блока равна размеру буфера. Значение count должно быть больше или равно 1. Необязательный параметр num возвращает количество прочитанных блоков.

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

Для бестиповых файлов применяется как последовательный, так и прямой доступ.

Пример #8.1.

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

program create_bfile;

var buf : array[1 .. 4] of real; f_in : text;

f_out: file;

i, k : integer;

name_in, name_out : string; begin

{$I-}

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

assign(f_in, name_in); reset(f_in);

if IOResult <>0 then begin

writeln('Файл ', name_in,' не найден'); exit

end;

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

assign(f_out, name_out); rewrite(f_out, sizeof(real) * 4);

{$I+}

i := 0;

while not eof(f_in) do begin inc(i);

read(f_in, buf[i]); if i = 4 then begin

blockwrite(f_out, buf, 1); i := 0; end;

end;

if i <> 0 then begin

for k := i + 1 to 4 do buf[k] := 0; blockwrite(f_out, buf, 1);

end;

close(f_in); close(f_out);

43

Василькова И.В.

Лекции

Паскаль

end.

8.4. Компонентные файлы

Компонентные файлы применяются для хранения однотипных элементов в их внутренней форме представления. Тип компонент задается после ключевых слов file of:

var имя : file of тип_компонент;

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

type mas = array [1 .. 100] of real; var a, b : mas;

f : file of mas;

begin

assign(f, 'some_file.dat'); rewrite(f);

...

write(f, a, b); close(f)

end.

За одну операцию записывается или считывается столько компонент, сколько перечислено в процедурах write или read.

Пример #8.2.

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

program tip_file; type

Complex = record d, m : real;

end;

var x : Complex; f1 : text;

f2 : file of Complex; i : byte;

begin

assign(f1, 'tipfile.dat'); reset(f1); assign(f2, 'tipfile.res'); rewrite(f2); while not eof(f1) do begin

read(f1, x.d, x.m); write(f2, x); end;

close(f1); close(f2); end.

44

Василькова И.В.

Лекции

Паскаль

8.5. Прямой доступ

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

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

Ниже приведено описание стандартных подпрограмм, используемых для реализации прямого доступа.

filepos(var f) : longint

Функция возвращает текущую позицию в файле f. Для только что открытого файла текущей позицией будет 0. После чтения или записи первого блока текущая позиция станет равной 1.

filesize(var f) : longint

Функция возвращает количество блоков в открытом файле f. seek(var f; n: longint)

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

truncate(var f)

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

Пример #8.3.

Программа, которая выводит на экран заданную по номеру запись из файла, сформированного в программе create_bfile

program get_bfile;

var buf

: array[1 .. 4] of real;

f

: file;

i, k

: integer;

filename : string; begin

{$I-}

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

assign(f, filename); reset(f, sizeof(real) * 4); if IOResult <>0 then begin

writeln('Файл ', filename, ' не найден'); exit

end;

45

Василькова И.В.

Лекции

Паскаль

 

 

 

{$I+}

true do begin

 

while

 

writeln('Введите номер записи или -1 для

окончания');

 

readln(k);

 

if

(k > filesize(f)) or (k < 0) then begin

 

writeln('Такой записи

в файле нет',); exit

end;

seek(f, k); blockread(f, buf, 1);

for i:= 1 to 4 do write(buf[i]:6:1); end;

close(f);

end.

9. Модульное программирование

9.1. Подпрограммы

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

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

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

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

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

inc(i); writeln(a, b, c);

{

вызовы процедур }

y := sin(x) + 1;

{

вызов функции }

Внутри подпрограмм можно описывать другие подпрограммы. Они доступны только из той подпрограммы, в которой они описаны. Рассмотрим правила описания подпрограмм.

46

Василькова И.В.

Лекции

Паскаль

9.2. Процедуры

Структура процедуры аналогична структуре основной программы:

procedure имя [(список параметров)];

{ заголовок }

разделы описаний

 

begin

 

раздел операторов

 

end;

 

Пример #9.1.

Найти разность средних арифметических значений двух вещественных массивов из 10 элементов.

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

program

dif_average;

 

const n

= 10;

 

type

mas = array[1 .. n] of real;

 

var

a,

b : mas;

 

 

i : integer;

 

 

dif, av_a, av_b : real;

 

procedure average(x : mas; var av : real);

{1}

 

var i : integer;

 

 

begin

 

 

 

av := 0;

 

 

 

for i := 1 to n do av := av + x[i];

 

 

 

av := av / n;

{2}

 

 

end;

begin

i := 1 to n do read(a[i]);

 

 

for

 

 

for

i := 1 to n do read(b[i]);

{3}

 

average(a, av_a);

 

average(b, av_b);

{4}

 

dif

:= av_a - av_b;

 

writeln('Разность значений ', dif:6:2)

end.

Описание процедуры average расположено в строках с {1} по {2}. В строках, помеченных цифрами {3} и {4}, эта процедура вызывается

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

47

Василькова И.В.

Лекции

Паскаль

9.3. Функции

Описание функции отличается от описания процедуры незначительно:

function имя [(список параметров)] : тип; {заголовок } разделы описаний

begin

раздел операторов имя := выражение;

end;

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

Пример #9.2.

Найти разность средних арифметических значений двух вещественных массивов из 10 элементов.

program dif_average1;

 

const n =

3;

 

type mas = array[1 .. n] of real;

 

var

 

 

 

a, b : mas;

 

i

: integer;

 

dif

: real;

 

function average(x : mas) : real;

{1}

var i

 

: integer;

{2}

av : real;

 

begin

 

 

 

av := 0;

 

for i := 1 to n do av := av + x[i];

{3}

average := av / n;

end;

 

 

 

begin

 

 

 

for i := 1 to n do read(a[i]);

 

for i := 1 to n do read(b[i]);

{4}

dif := average(a) - average(b);

writeln('Разность значений ', dif:6:2) end.

Оператор, помеченный комментарием {1}, представляет собой заголовок функции. Тип функции определен как вещественный, потому что такой тип имеет среднее арифметическое элементов вещественного массива. Оператор {3} присваивает вычисленное значение имени функции. В операторе {4} функция вызывается дважды: сначала для одного массива, затем для другого.

48

Василькова И.В.

Лекции

Паскаль

9.4.Глобальные и локальные переменные

ВIBM PC-совместимых компьютерах память условно разделена на так называемые сегменты. Адрес каждого байта составляется из номера сегмента и смещения относительно его начала.

Длина адресов сегмента и смещения – 16 бит, поэтому размер сегмента не может превышать 216 байт (64K). При вычислении адреса байта в оперативной памяти адрес сегмента сдвигается на 4 двоичных разряда влево,

и к нему прибавляется смещение (рис. 9.1). Таким образом, длина адреса составляет 20 бит, и с помощью него можно адресовать память объемом 220 байт (1 мегабайт).

Рис. 9.1.

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

Рис. 9.2.

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

49

Василькова И.В.

Лекции

Паскаль

подпрограммы, кроме тех подпрограмм, в которых описаны локальные переменные с такими же именами.

Внутри подпрограмм описываются локальные переменные. Они располагаются в сегменте стека, причем распределение памяти происходит в момент вызова подпрограммы, а ее освобождение – по завершении подпрограммы. Значения локальных переменных между двумя вызовами одной и той же подпрограммы не сохраняются и эти переменные предварительно не обнуляются. Локальные переменные могут использоваться только в подпрограмме, в которой они описаны, и всех вложенных в нее.

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

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

9.5. Виды параметров подпрограмм

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

Важно запомнить, что в заголовке подпрограммы нельзя вводить описание нового типа, там должны использоваться либо имена стандартных типов, либо имена типов, описанных программистом ранее в разделе type.

ВПаскале четыре вида параметров:

значения;

переменные;

константы;

нетипизированные параметры.

Кроме того, по другим критериям можно выделить особые виды параметров:

открытые массивы и строки;

процедурные и функциональные параметры;

объекты.

9.5.1. Параметры-значения

Параметр-значение описывается в заголовке подпрограммы следующим образом:

имя : тип; Например, передача в процедуру Р величины целого типа записывается так:

procedure P(x : integer);

50