- •Центр Компьютерного Обучения
- •Подпрограммы: процедуры.
- •1. Структурное программирование и технология нисходящего программирования.
- •2. Подпрограммы в языке Pascal. Понятие «процедура».
- •3. Формальные и фактические параметры.
- •4. Параметры-значения и параметры-переменные (входные и выходные параметры) подпрограмм, механизм передачи параметров (можно перенести на Занятие 2, если не хватит времени).
- •5. Локальные и глобальные переменные, область действия переменных
- •Подпрограммы: функции
- •Функция не имеет выходных параметров, она возвращает единственное значение (результат);
- •Рекурсия
- •Строковый тип данных – String
- •6. Для обработки строковых данных можно использовать стандартные процедуры и функции, описание которых можно найти в [1] или в любом справочнике по Pascal.
- •1. Общие сведения.
- •5. Доступ к компонентам файла.
- •Дополнительно (на усмотрение преподавателя!!!) процедуры Rename и Erase.
- •Текстовые файлы
- •1. Назначение.
- •Типизированные файлы
- •Динамические структуры данных
- •1. Статическая и динамическая память.
- •Распределение памяти.
- •2. Статические и динамические переменные.
- •Статическая переменная:
- •4. Доступ к переменной по указателю.
- •5. Управление динамической памятью (процедуры New и Dispose).
- •Формирование с помощью указателей однонаправленного списка по принципу стека, поиск элемента
- •Однонаправленный список
- •Пояснения к программе
- •Формирование с помощью указателей однонаправленного списка по принципу «очереди», поиск элемента
- •Пояснения к программе
- •Удаление элемента из линейного однонаправленного списка
Типизированные файлы
1. Назначение.
Типизированные файлы состоят из компонентов определенного типа и предназначены для хранения больших массивов однотипных данных. Типизированные файлы являются файлами прямого доступа, т. е. возможно обращение к произвольному компоненту, т. к. длина любого компонента строго постоянна.
2. Описание файловых переменных для типизированных файлов.
Файловая переменная, обозначающая типизированный файл, описывается следующим образом:
Var
<имя_файловой_переменной> : File of <тип_компонентов>;
где <тип_компонентов> - любой стандартный тип, определенный в Pascal (кроме файлового) либо тип, определенный пользователем в разделе Type (кроме файлового).
Пример.
Type Stroka=Srtring[15];
Var
F1 : File of Integer; {файл с целочисленными компонентами}
F2 : File of Stroka; {файл со строковыми компонентами}
3. Процедуры и функции работы с типизированными файлами.
а) К типизированным файлам применимы процедуры Assign, Reset, Rewrite, Close, Rename, Erase и функция Eof.
б) Функция FileSize.
Назначение: |
определение числа компонентов (размера файла). |
Синтаксис: |
FileSize( F ), где F – файловая переменная. |
Описание работы: |
|
Примечание: |
|
в) Функция FilePos.
Назначение: |
определение текущей позиции указателя обработки. |
Синтаксис: |
FilePos( F ), где F – файловая переменная. |
Описание работы: |
= FileSize( F ). |
Примечание: |
|
г) Процедура Seek.
Назначение: |
непосредственный доступ к заданному компоненту файла прямого доступа. |
Синтаксис: |
Seek( F, N ), где F – файловая переменная, N – номер нужного компонента, представляет собой целое число в диапазоне от 0 до 231-1. |
Описание работы: |
Seek(F, FileSize(F)). |
Примечание: |
|
д) Процедура Truncate.
Назначение: |
усечение файла |
Синтаксис: |
Truncate( F ), где F – файловая переменная. |
Описание работы: |
процедура Truncate отсекает часть файла от текущего положения указателя до конца, при этом текущая позиция файла становится концом файла. |
Примечание: |
|
Задача 1. Создать файл Lab.dat из 20 целых чисел.
Program Dat; Uses Crt; Var F : File of Iinteger; i, j: Integer; Begin Assign(F, ‘Lab.dat’); {$I-} Rewrite(F); {$I+} If Ioresult <>0 Then Begin Writeln (‘Нет места на диске’); Halt; End; Randomize; For i:=1 to 20 Do Begin j:=Random(100); Write(F, j); End; Close(F); End. |
{файловая переменная} {рабочие переменные}
{установление связи F с внешним файлом} {отключение контроля ошибок ввода/вывода} {открытие файла для записи} {включение контроля ошибок ввода/вывода} {если Ioresult 0}
{то вывод «На диске нет места»} { и окончание работы программы}
{формирование типизированного файла}
{закрытие файла}
|
Связь между файловой переменной и внешним файлом устанавливается процедурой Assign. Открытие файла для записи осуществляется процедурой Rewrite. Если на диске нет места, то на экране появляется соответствующее сообщение и файл не создается. При наличии места на диске с помощью оператора For создается файл из 20 целых чисел. При этом каждый раз используется генератор случайных чисел, который инициализируется процедурой Randomize. Запись в файл производится через переменную j, т. к. с помощью процедуры Write (Writeln) в типизированный файл можно записать только значение переменной, выражения в этом случае использовать нельзя.
Задача
Заменить нулем все компоненты с нечетными номерами файла Lab.dat, созданного с помощью программы Dat.
Program Prim; Uses Crt; Var F: File of Iinteger; Name: String; Size, i, II, j: Integer; Procedure Wywod; Begin While not Eof(F) Do Begin Read(F, J); Write(J, ‘ ’); End; Writeln; End; Begin Repeat Write(‘Входной файл >’); Readln(Name); Assign(F, Name); {$I-} Reset(F); {$I+} II:= Ioresult; If II<>0 Then Writeln(‘Файл’,Name,’ не найден’); Until II=0; Wywod; Writeln(‘Для продолжения нажать Enter’); Readln; Size:=FileSize(F); For i:=1 to (Size div 2) Do Begin Seek(F, 2*i - 1); j:=0; Write(F, j); End; Writeln(‘Результирующий файл’); Seek(F, 0); Wywod; Close(F); Readln; End. |
{файловая переменная} {имя файла} {рабочие переменные} {процедура вывода файла на экран}
{в цикле} {ввод имени файла Lab.dat}
{установление связь F с внешним файлом} {отключение контроля ошибок ввода/вывода} {открытие файла для чтения для записи} {включение контроля ошибок ввода/вывода} {присваивание II значения Ioresult} {если II 0} {то вывод сообщения «Файл…не найден»} {постусловие: пока не открыт нужный файл} {вывод исходного файла}
{Size = число компонентов в файле}
{в цикле по i} {перемещение указателя к следующему} {нечетному компоненту}
{замена нулем нечетного компонента} {конец цикла For}
{перемещение указателя в начало файла} {вывод полученного файла} {закрытие файла}
|
Объяснить (!!!). Открытие файла для чтения осуществляется стандартной процедурой Reset. С помощью процедуры Reset можно также открыть файл для его корректировки. Значение стандартной функции Ioresult присваивается рабочей переменной II, так как после повторного обращения к функции Ioresult (после вывода сообщения «Файл не найден») ее значение меняется, т. к. вывод на экран всегда корректен. Если открывается несуществующий файл на диске, то на экране появится сообщение «Файл … не найден» и снова будет запрашиваться имя входного файла. В данном примере надо ввести имя файла Lab.dat. С помощью стандартной функции Filesize определяется число компонентов в файле. Для перемещения указателя обработки к заданному компоненту используется процедура Seek. При определения длины файла оператором
Size:=Filesize(F);
и организации доступа к компонентам файла с помощью операторов вызова процедуры Seek
Seek(F, 2*I-1) (Seek(F, 0))
используются переменная Size типа Integer и выражение 2*i - 1 типа Integer. Для вывода на экран результирующего файла текущую позицию в файле надо переместить в начало. Для этого применяется процедура
Seek(F, 0);
Внутренняя процедура Wywod используется для вывода исходного и результирующего файлов.
Входной файл
Lab.dat 61
41 37 91 81 15 60 10 51 5 98 18 32 84 42 46 77 75 99 62
Результирующий
файл 61
0 37 0 81 0 60 0 51 0 98 0 32 0 42 0 77 0 99 0
Результаты выполнения программы Prim.
Тип – запись
1. Реальные данные об объектах часто описываются величинами разных типов. Например, товар на складе описывается следующими величинами: наименование (String), количество (Integer), цена (Real), наличие сертификата качества (Boolean) и т. д. В этом случае возникает необходимость хранить и обрабатывать совокупности данных различного типа, поэтому приходится использовать отдельные массивы для каждого типа данных, а для установления соответствия между ними вводятся соответствующие индексы. Такой подход не очень удобен и существенно усложняет написание программы. В Pascal существует другой способ решения таких задач – использование комбинированного типа данных, который называется запись. Запись – это структурированный тип данных, состоящий из фиксированного числа компонентов одного или нескольких типов.
2. Определение типа записи начинается идентификатором Record и заканчивается зарезервированным словом End. Между ними заключен список компонентов, называемых полями, с указанием идентификаторов (имен) полей и типа каждого поля (см. ниже). Тип запись можно описывать:
а) в разделе описания типов
Type
<имя_типа_записи> = Record
<имя_поля_1> : <тип_поля_1>;
< имя_поля_2> : < тип_поля_2>;
…
< имя_поля_k> : < тип_поля_k>;
End;
Var
<имя_переменной> : <имя_типа_записи>;
б) явно в разделе описания переменных
Var
<имя_переменной> : Record
<имя_поля_1> : <тип_поля_1>;
< имя_поля_2> : < тип_поля_2>;
…
< имя_поля_k> : < тип_поля_k>;
End;
Пример 1.
Type
Car = Record {объявление записи из 4-х полей}
Number : Integer; {номер}
Marka : String[20]; {марка}
FIO : String[40]; {фамилия и инициалы владельца}
Address : String[60]; {адрес владельца}
End; {окончание описания записи}
Var
M, V : Car; {объявление переменных типа- запись}
Идентификатор (<имя_поля_...>) поля должен быть уникален только в пределах записи, т. е. в разных записях поля могут иметь одинаковые имена. Однако во избежание ошибок лучше делать его уникальным в пределах всей программы.
<тип_поля_...> - любой стандартный тип языка Pascal, включая тип запись, т. е. поле записи может быть в свою очередь записью. Если в качестве <тип_поля_...> используется тип, определенный пользователем, то он должен быть объявлен до описания записи.
Из записей одного типа можно составлять массивы
Пример 2.
Type
Person = Record
FIO : String[20];
Age : Integer;
Prof : String[30];
End;
Var
List : Array[1..50] of Person;
3. Обращение к значению поля осуществляется с помощью составного имени, которое состоит из имени переменной типа запись и идентификатора поля, разделенных точкой. Например, чтобы получить доступ к полям записи Car (см. пример 1), надо написать:
M.Number, M.marka, M.FIO, M.Address.
Составное имя можно использовать везде, где допустимо применение типа поля (применение данных такого же тира, как и поле записи). Для присваивания полям значений используется оператор присваивания.
Пример.
а) присваивание полям записи значений в программе (см. пример 1):
M.Number :=1678;
M.Marka :=’ГАЗ-24’;
M.FIO :=’Иванов И. И.’;
M.Address :=’Ул. Пушкина 12-31’;
б) присваивание полям одной записи значений полей другой записи (см. пример):
V:=M;
Обращение к полям записи имеет несколько громоздкий вид, что неудобно при использовании длинных идентификаторов. Для решения этой проблемы в Pascal предназначен оператор присоединения With … Do:
With <переменная_типа_запись>
Do <оператор>;
где <переменная_типа_запись> - имя переменной типа запись, с полями которой нужно работать, <оператор> - простой или составной оператор языка Pascal. Один раз указав имя переменной типа запись в операторе With, можно в пределах этого оператора работать с именами полей как с обычными переменными, т. е. без указания перед идентификатором поля имени переменной, определяющей запись.
Пример.
With M
Do Begin
Number :=1678;
Marka :=’ГАЗ-24’;
FIO :=’Иванов И. И.’;
Address :=’Ул. Пушкина 12-31’;
End;
Примечание. Оператор присоединения действует только на поля записи, указанной в операторе присоединения. Все поля, относящиеся к другой записи, используются только с указанием идентификатора записи.
4. Операции с записями:
ввод записи с клавиатуры:
Read(M.Number, M.Marka, M.FIO, M.Address);
вывод записи на экран монитора:
Writeln(M.Number:4, M.Marka:7, M.FIO:12, M.Address:25);
чтение записи из текстового файла:
Read(<имя_файла>, M.Number, M.Marka, M.FIO, M.Address);
вывод значения переменной в текстовый файл:
Writeln(<имя_файла>, M.Number:4, M.Marka:7, M.FIO:12, M.Address:25);
сравнение записей:
If M.Fam <> V.Fam
Then …
Если операции с записью производятся в пределах оператора присоединения, то указываются только имена полей записи, указанной в операторе присоединения. Во всех остальных случаях обязательно полное указание имени поля записи (составное имя).
Задача
Ввести с клавиатуры и записать в типизированный файл Swed.dat данные о студентах, содержащие следующие сведения: фамилию, имя, отчество, год рождения.
Program Primer; Uses Crt; Type Anketa = Record Fam, Nm, Ot : String[15]; Born : Integer; End; Var F : File of Anketa; A : Anketa; S : Char; Begin Assign(F,’Swed.dat’); Rewrite(F); Clrscr; Repeat With A Do Begin Write(‘Фамилия: ’); Readln(Fam); Write(‘Имя: ’); Readln(Nm); Write(‘Отчество: ’); Readln(Ot); Write(‘Год рождения: ’); Readln(Born); End; Write(F, A); Writeln(‘Продолжить (y/n)’); Readln(S); Until Upcase(S)=’N’; Close(F); End. |
{объявление типа - запись}
{файловая перем. типизированного файла} {А - запись} {символьная переменная}
{установление связи между F и Swed.dat} {открытие файла на запись}
{в цикле} {для записи А} {ввод значений полей записи А} {с клавиатуры}
{запись записи А в файл} {вывод запроса на продолжение} {ввод ответа с клавиатуры} {пока не нажата ‘N’ или ‘ n’} {закрытие файла}
|