Алгоритмические языки высокого уровня. Курс лекций
.pdfзавершается с сообщением об ошибке, если указанный файл не най- ден (если f – типизированный файл, то процедурой Reset он от- крывается для чтения и записи одновременно).
Rewrite(f) – открывает для записи файл, с которым связана файловая переменная f. После успешного выполнения этой про- цедуры файл готов к записи в него первого элемента. Если указан- ный файл уже существовал, то все данные из него уничтожаются.
Close(f) – закрывает открытый до этого файл с файловой пе- ременной f. Вызов процедуры Close необходим при завершении работы с файлом. Если по какой-то причине процедура Close не будет выполнена, файл все же будет создан на внешнем устройстве, но содержимое последнего буфера в него не будет перенесено.
EOF(f): boolean – возвращает значение TRUE, когда при чтении достигнут конец файла. Это означает, что уже прочитан по- следний элемент в файле или файл после открытия оказался пуст.
Rename(f, NewName) – позволяет переименовать физический файл на диске, связанный с файловой переменной f. Переимено- вание возможно после закрытия файла.
Erase(f) – уничтожает физический файл на диске, который был связан с файловой переменной f. Файл к моменту вызова про- цедуры Erase должен быть закрыт.
IOResult – возвращает целое число, соответствующее коду последней ошибки ввода-вывода. При нормальном завершении опе- рации функция вернет значение 0. Значение функции IOResult необходимо присваивать какой-либо переменной, так как при каж- дом вызове функция обнуляет свое значение (функция IOResult работает только при выключенном режиме проверок ошибок ввода- вывода или с ключом компиляции {$I-}).
Пример процедуры определения наличия типизированного файла записей на диске
Описание. Если файла нет, то создается пустой файл, указатель устанавливается в его начало, если файл существует, то указатель просто устанавливается в его начало.
Program Test; Type
t_r=record fio:string[20]; {ФИО}
yb :integer; {Год рождения} p :real; {Зарплата}
81
end;
f_t= file of r_t; Procedure NoFile(var f:f_t);
{В процедурах файловые переменные указываются как выход-
ные - var} begin
Assign(f,'c:\mydir\my.dat'); {связывание файловой пере-
менной f с физическим файлом}
{$I-} {директива компилятора отключающая контроль ошибок ввода-вывода}
Reset(f); {попытка открыть файл}
{$I+} {директива компилятора включающая контроль ошибок ввода-вывода}
If IOResult<>0 then Rewrite(f); {если ошибка, то создать новый файл}
end;
Работа с типизированными файлами. Типизированный файл – это последовательность компонент любого заданного типа (кроме типа «файл»). Доступ к компонентам файла осуществляется по их порядковым номерам. Компоненты нумеруются, начиная с 0. После открытия файла указатель (номер текущей компоненты) стоит в его начале на нулевом компоненте. После каждого чтения или записи указатель сдвигается к следующему компоненту.
Write(f, список переменных) – записывает в файл f
всю информацию из списка переменных.
Read(f, список переменных) – процедура читает из фай- ла f компоненты в указанные переменные. Тип файловых компо- нент и переменных должны совпадать. Если будет сделана попытка чтения несуществующих компонент, то произойдет ошибочное за- вершение программы. Необходимо либо точно рассчитывать количе- ство компонент, либо перед каждым чтением данных делать провер- ку их существования (функция eof).
Seek(f, n) – процедура смещает указатель файла f на n-ю позицию. Нумерация в файле начинается с 0.
FileSize(f):longint – функция возвращает количество компонент в файле f.
FilePos(f):longint – функция возвращает порядковый номер текущего компонента файла f.
Truncate(f) – процедура отсекает конец файла, начиная с те- кущей позиции включительно.
82
Работа с текстовыми файлами. Текстовый файл – это совокуп-
ность строк, разделенных метками конца строки. Сам файл заканчи- вается меткой конца файла. Доступ к каждой строке возможен лишь последовательно, начиная с первой. Одновременная запись и чтение запрещены.
Чтение из текстового файла:
Read(f, список переменных); ReadLn(f, список переменных);
Процедуры читают информацию из файла f в переменные. Спо- соб чтения зависит от типа переменных, стоящих в списке. В пере- менную char помещаются символы из файла. В числовую перемен- ную пропускаются символы-разделители, начальные пробелы и счи- тывается значение числа до появления следующего разделителя. В переменную типа string помещается количество символов, равное длине строки, но только в том случае, если раньше не встретились символы конца строки или конца файла. Отличие ReadLn от Read в том, что в нем после прочтения данных пропускаются все оставшие- ся символы в данной строке, включая метку конца строки. Если спи- сок переменных отсутствует, то процедура ReadLn(f) пропускает строку при чтении текстового файла.
Запись в текстовый файл:
Write(f, список переменных); WriteLn(f, список переменных);
Процедуры записывают информацию в текстовый файл. Способ записи зависит от типа переменных в списке (как и при выводе на экран). Учитывается формат вывода. WriteLn от Write отлича- ется тем, что после записи всех значений из переменных записывает еще и метку конца строки (формируется законченная строка файла).
Append(f) – процедура открывает текстовый файл для добав- ления информации к его концу.
Работа с нетипизированными файлами. Нетипизированные файлы – это последовательность компонент произвольного типа.
Открытие нетипизированного файла:
Reset(f, BufSize) ; Rewrite(f, BufSize);
Параметр BufSize задает число байт, считываемых из файла или записываемых в него за одно обращение. Минимальное значение BufSize – 1 байт, максимальное – 64 К байт (если BufSize не указан, то по умолчанию он принимается равным 128).
Чтение данных из нетипизированного файла:
83
BlockRead(f, X, Count, QuantBlock);
Эта процедура осуществляет за одно обращение чтение в пере- менную X количество блоков, заданное параметром Count, при этом длина блока равна длине буфера. Значение Count не может быть меньше 1. За одно обращение нельзя прочитать больше чем 64 К байт. Необязательный параметр QuantBlock возвращает число блоков, прочитанных текущей операцией BlockRead. В случае успешного завершения операции чтения QuantBlock = Count, в случае аварийной ситуации параметр QuantBlock бу- дет содержать число удачно прочитанных блоков. Отсюда следует, что с помощью параметра QuantBlock можно контролировать правильность выполнения операции чтения.
Запись данных в нетипизированный файл:
BlockWrite(f, X, Count, QuantBlock);
Эта процедура осуществляет за одно обращение запись из пере- менной X количество блоков, заданное параметром Count, при этом длина блока равна длине буфера. Необязательный параметр QuantBlock возвращает число блоков, записанных успешно теку- щей операцией BlockWrite. Для нетипизированных файлов можно использовать процедуры Seek, FIlePos и FileSize, аналогично соответствующим процедурам типизированных файлов.
Пример программы
Описание: в программе создается файл прямого доступа, в файл вводятся данные, и осуществляется его вывод на экран.
Program Test; uses crt; type
student=record n: integer; name=string[10]; end;
var i:integer; s:student;
f:file of student; procedure create_file begin
assign(f, ‘c:\11.dat’); rewrite(f);
for i:=1 to 4 do begin
84
seek(f,i);
readln(S,n,s.name);
write(f,s);
end;
close(f);
end;
procedure write_file(i:integer); begin
assign(f,’c:\11.dat’);
reset(f);
seek(f,1);
readln(S,n,S,name);
write(f,s);
close(f);
end; begin
readln(i); case I of
1: create_file; 2:write_file; end;
assign(f,’c:\11.dat’); for i:=1 fo 4 do
begin seek(f,i); gotoxy(13,i);
write(S.name,S.name);
end;
close(f);
end.
4.2.5. Строки
Для обработки строковой информации в Turbo Pascal введен стро- ковый тип данных. Строкой в Pascal называется последовательность из определенного количества символов. Количество символов после- довательности называется длиной строки.
Синтаксис
var s: string[n]; var s: string;
где n – максимально возможная длина строки – целое число в диапа- зоне 1…255 (если этот параметр опущен, то по умолчанию он при- нимается равным 255).
Строковые константы записываются как последовательности сим- волов, ограниченные апострофами. Допускается формирование строк с использованием записи символов по десятичному коду (в виде
85
комбинации # и кода символа) и управляющих символов (комбина- ции ^ и некоторых заглавных латинских букв).
Пример: 'Текстовая строка' #54#32#61 'abcde'^A^M;
Пустой символ обозначается двумя подряд стоящими апострофа- ми (если апостроф входит в строку, то при записи он удваивается).
Переменные, описанные как строки с разными максимальными длинами, можно присваивать друг другу, хотя при попытке присво- ить короткой переменной длинную лишние символы будут отброше- ны. Выражения типа char можно присваивать любым строковым переменным.
Имеется простой доступ к отдельным символам строковой пере- менной: i-й символ переменной st записывается как st[i].
Если st – это 'Строка', то st[1] – это 'С', st[2] – это 'т', st[3] – 'р' и т.д.
Над строками определены операции:
• слияния (конкатенации), обозначается знаком +
a := 'Turbo'; b := 'Pascal'; c := a + b; пере-
менная c приобретет значение 'TurboPascal'.
• сравнения <, >, =, <>, <=, >=. Две строки сравниваются посим- вольно, слева направо, по кодам символов. Если одна строка короче другой, то недостающие символы короткой строки заменяются сим- волом с кодом 0.
Процедуры и функции для работы со строками
Delete(Var S:String; N,M:Integer) – удаляет M
символов из строки S, начиная с позиции N.
s := 'Система Turbo Pascal'; delete(s,8,6); {s будет равно 'Система Pascal'}
Insert(SubS:String; Var S :String; N:Integer) –
вставляет |
подстроку SubS в строку |
S, начиная с позиции N. |
s := |
'Система Pascal'; |
insert('Turbo ',s,9); |
{s будет равно 'Система Turbo Pascal'}
Str(X:Integer; Var S:String) – возвращает представ-
ление числа X в его символьной форме S.
Val(S:String; Var X, Code:Integer) – возвращает представление символов строки S в ее числовой форме X. Пара- метр Code содержит признак ошибки преобразования (если Code = 0, то это свидетельствует об успешно произошедшем пре-
86
образовании – ошибки нет). Процедура преобразует строковую за- пись числа, содержащуюся в S, в числовое представление, поме- щая результат в Х (Х может быть как целой, так и действительной переменной). Если в S встречается недопустимый (с точки зрения правил записи чисел) символ, то преобразование не происходит, а в Code записывается позиция первого недопустимого символа. Вы- полнение программы при этом не прерывается, диагностика не выда- ется.
Chr(X:Byte): Char – возвращает символ с заданным поряд- ковым номером X.
Сoncat(S1[,S2 ,...,SN]):String – выполняет сцепку
(конкатенацию) последовательности строк. Каждый параметр явля- ется выражением строкового типа. Если длина строки-результата превышает 255 символов, то она усекается до 255 символов. Данная функция эквивалентна операции конкатенации «+» и работает не- много менее эффективно, чем эта операция.
Copy(S:String; N, M:Integer):String – возвращает подстроку из строки S, начиная с позиции N и длиной M симво- лов.
s := 'Система |
Turbo Pascal'; |
|
s2 |
:= copy(s, |
1, 7); {s2 будет равно 'Система'} |
s3 |
:= copy(s, |
9, 5); {s3 будет равно 'Turbo'} |
s4 |
:= copy(s, |
15, 6); {s4 будет равно 'Pascal'} |
Length(S:String):Byte – возвращает количество симво- лов в строке S.
n := length('Pascal'); {n будет равно 6}
Ord(X:Char):LongInt – возвращает порядковый номер сим- вола X в таблице кодов символов.
Pos(SubS,S:String):Byte – возвращает номер позиции,
начиная с которой в строке S |
располагается подстрока SubS (если |
|
значение равно 0, то |
S |
не содержит SubS). |
s := 'Система Turbo Pascal';
x1 := pos('Pascal', s); {x1 будет равно 15}
x2 := pos('Basic', s); {x2 будет равно 0}
UpCase(c:char):char; Если c – строчная латинская буква, то функция возвращает соответствующую прописную латинскую букву, в противном случае строчной символ.
87
Пример программы
Описание: в программе в строке заменяются все вхождения под- строки child на подстроку children (метод решения – перебор всех символов строки – аналогично удалению и вставке элементов в одномерном массиве).
program zamena; var
s1,k,s,st:string; i,d: byte;
begin
writeln('введите строку'); readln(st);
s:='child';
d:=length(s);
s1:='children';
for i:=length(st)-d+1 downto 1 do begin
k:=copy(st,i,d); if k=s then
begin delete(st,i,d); insert(s1,st,i);
end;
end;
writeln('измененная строка: ',st); end.
4.3. Процедурные типы
Основное назначение этих типов – дать гибкие средства передачи функций и процедур в качестве фактических параметров обращения к другим процедурам и функциям.
Для объявления процедурного типа используется заголовок про- цедуры (функции), в котором опускается ее имя, например:
type
Prod = Procedure (a, b, c: Real; var d: Real); Proc2 = Procedure (var a, b) ;
Рrос3 = Procedure;
Func1 = Function: String;
Func2 = Function (var s: String): Real;
Существует два процедурных типа: тип-процедура и тип- функция.
88
Пример программы
Описание: иллюстрация механизма передачи процедур в качестве фактических параметров вызова при выводе на экран таблицы двух функций:
sin1(х) = (sin(x) + 1) * ехр(-х) cos1(x) = (cos(x) + 1) * exp(-x)
{Вычисление и печать значений этих функций реализуются в процедуре PRINTFUNC, которой в качестве параметров передают- ся номер позиции N на экране, куда будет выводиться очеред- ной результат (с помощью этого параметра реализуется вывод в две колонки), и имя нужной функции}
Uses CRT; type
Func = Function (x: Real) : Real; Procedure PrintFunc (XPos: Byte; F:Func) ;
{Осуществляет печать функции F . XPos - горизонтальная по- зиция начала вывода }
const
np = 20; {Количество вычислений функций} var
х : Real; i : Integer; begin {PrintFunc}
for i := 1 to np do begin
x := i * (2 * pi / np) ; GotoXY (XPos, WhereY) ; WriteLn (x:5:3, F(x):18:5) end
end; {PrintFunc}
Function Sin1fx: Real): Real; far; begin
sinl := (sin(x) + 1) * exp(-x) end;
Function Cos1(x: Real): Real; far; begin
cosl := (cos(x) + 1) * exp(-x) end;
begin {основная программа} ClrScr; {Очищаем экран}
PrintFunc (1, sin1); GotoXY (1,1); {Переводим курсор в ле-
вый верхний угол} PrintFunc (40, cos1) end.
Для установления правильных связей функций SIN1 и COS1 с процедурой PRINTFUNC они должны компилироваться с расчетом на дальнюю модель памяти. Вот почему в программу вставлены стан-
89
дартные директивы FAR сразу за заголовками функций. В таком ре- жиме должны компилироваться любые процедуры (функции), которые будут передаваться в качестве фактических параметров вызова.
Стандартные процедуры (функции) Pascal не могут передаваться рассмотренным способом.
В программе могут быть объявлены переменные процедурных ти- пов:
var
p1 : Proc1; f1, f2 : Func2;
р : array [1..N] of Proc1;
Переменным процедурных типов допускается присваивать в ка-
честве значений имена соответствующих подпрограмм. После такого присваивания имя переменной становится синонимом имени подпро- граммы:
type
Proc = Procedure (n: word; var a: Byte); var
ProcVar: Proc; x, у : Byte;
Procedure Procl(x: word; var y: Byte); far; begin
if x > 255 then
у:= x mod 255 else
у:= Byte(x) end;
begin {Главная программа} ProcVar := Proc1;
for x := 150 to' 180 do begin
ProcVar (x + 100, y); Write (y:8)
end end.
Такие присваивания допустимы и для параметров-функций:
type
FuncType = Function (i : Integer) : Integer; var
VarFunc : FuncType; i : Integer;
Function MyFunc (count : Integer) : Integer; far; begin
.......
end; {MyFunc}
90
