Функции для работы с типизированными файлами
Для работы с типизированными файлами используются следующие
функции:
FileSize(файловая переменная) - текущий размер файла – количество записей в файле,
FilePos(файловая переменная) - номер текущей записи в файле – позиция указателя текущей записи (нумерация записей начинается с нуля, номер последней записи на единицу меньше текущего размера файла),
и процедуры:
Seek(файловая переменная, номер) - перемещение указателя на запись с заданным номером (нумерация записей начинается с нуля),
Truncate(файловая переменная) - усечение файла после текущей записи: все записи в файле после текущей удаляются, и после нее ставится метка конца файла EOF,
Erase(файловая переменная)- уничтожение файла – стирание его с диска.
Пример: открыть файл, созданный предыдущей программой, определить его конечный размер, номер начальной записи, поставить указатель на третью запись (по номеру), вывести ее на экран, усечь файл, начиная с нее и вывести новый файл на экран:
Программа:
Program File_1;
Uses CRT;
Var n : Integer;
f_int : File Of Integer;
Begin
ClrScr;
Assign(f_int, ‘d:\User\f_int.dat’);
ReSet(f_int); открываем файл для чтения
While Not(EOF(f_int)) Do пока не конец файла:
Begin
Read(f_int, n); читаем из неговn очередную запись
Write(n:5); и выводим значениеn на экран
End;
WriteLn;
n := FileSize(f_int); n – размер файла- количество записей в нем
WriteLn(‘Размер файла равен ’, n);
ReSet(f_int); ставим указатель на начальную запись
n := FilePos(f_int); n – номер начальной записи в файле
WriteLn(‘Номер начальной записи равен ’, n);
Seek(f_int, 3); ставим указатель на запись с номером3
Read(f_int, n); читаем из файла в переменнуюn текущую запись
WriteLn(‘Запись с номером 3 равна ’, n);
Truncate(f_int); удаляем из файла все записи послетекущей
ReSet(f_int); открываем файл для чтения - ставим указатель
на начальную запись
While Not(EOF(f_int)) Do снова читаем файл и выводим его наэкран
Begin
Read(f_int, n);
Write(n:5);
End;
WriteLn;
Close(f_int); закрываем файл
ReadLn;
End.
На экран будет выведено:
3 -1 5 12 -6
Размер файла равен 5
Номер начальной записи равен 0
Запись с номером 3 равна 12
3 -1 5 12
Текстовые файлы
Текстовые файлы представляют собой последовательность строк различной длины, каждая из которых заканчивается меткой EOLn – End Of Line – конец строки (последовательность символов #13#10). В конце файла стоит метка EOF – End Of File.
Запись данных в текстовый файл практически не отличается от вывода данных на экран терминала. Чтение же данных из текстового файла имеет свои особенности.
Объявить текстовый файл можно двумя способами:
1. указанием его имени и типа в разделе описания переменных:
Var f_text : Text; объявлен текстовый файлf_text,
f_text – имя логического файла – файловой переменной
Внимание! При описании файла его размер не указывается.
2. указанием его типа в разделе определения типов TYPE и имени – в разделе описания переменных:
Type TFile_text = Text;
Var f_text : TFile_text;
Перед началом работы с файлом необходимо связать имя логического файла (файловую переменную) с физическим файлом на внешнем носителе:
Assign(имя файловой переменной, ‘путь к физическому файлу’);
Assign(f_text,’D:\User\f_text.txt’);
f_text – имя файловой переменной (логического файла),
D:\User\f_text.txt - полный путь к физическому файлу на внешнем носителе: диск D:, директория (папка) User,
файл f_text.txt
Внимание! Желательно совпадение имени физического файла и имени файловой переменной; расширение имени текстового файла всегда .txt.
После установления пути к физическому файлу его можно открыть:
а) открытие нового файла для записи в него данных:
ReWrite(f_text);
При этом на внешнем носителе создается новый физический файл с заданным именем. Если файл с таким же именем уже существовал, то он очищается,
б) открытие существующего файла для чтения из него данных:
ReSet(f_text);
При этом на внешнем носителе отыскивается файл с заданным именем и, если он найден, то указатель текущей записи становится в начало файла ,
в) открытие существующего файла для записи в его конец новых строк:
Append(f_text);
При этом на внешнем носителе отыскивается файл с заданным именем и, если он найден, то указатель текущей записи становится в конец файла.
Запись в открытый для записи файл осуществляется операторами:
Write( файловая переменная, имя записываемой переменной);
WriteLn( файловая переменная, имя записываемой переменной);
Во втором случае после записи в файл значения переменной текстовый курсор переходит в начало новой строки (как на экране терминала).
В текстовый файл можно записывать данные только целого, вещественного, символьного типа или строки.
Пример: создать текстовый файл и записать в него
1. номер учебной группы
2. фамилию студента
3. имя студента
4. его оценку по информатике
5. средний балл сдачи сессии
Данные вводить с экрана. Все данные записывать в файл с новых строк.
Интерфейс:
Номер группы: ИС-09
Фамилия: Иванов
Имя: Иван
Оценка:4
Ср. балл:4.12
Программа:
Program File_2;
Uses CRT;
Var ocenka : 2..5; оценка
sr_ball : Real; средний балл
name : String[15]; фамилия или имя
nomer : String[10]; номер группы
f_text : Text; текстовый файл
Begin
ClrScr;
Assign(f_text, ‘d:\User\f_text.txt’);
ReWrite(f_text); открываем файл для записи
Write(‘Номер группы:’);
ReadLn(nomer); вводим номер группы
WriteLn(f_text, nomer); записываем его в файл
Write(‘Фамилия:’);
ReadLn(name); вводим фамилию
WriteLn(f_text, name); записываем ее в файл с новой строки
Write(‘Имя:’);
ReadLn(name); вводим имя
WriteLn(f_text, name); записываем его в файл с новой строки
Write(‘Оценка:’);
ReadLn(ocenka); вводим оценку
WriteLn(f_text, ocenka:3); записываем ее в файл с новой строки в 3 позициях
Write(‘Ср. балл:’);
ReadLn(sr_ball); вводим средний балл
WriteLn(f_text, sr_ball:6:2); записываем его в файл с новой строки в 6 позициях
Close(f_text); закрываем файл
ReadLn;
End.
Структура созданного файла:
ИС-09
Иванов
Иван
4.12
Внимание! Все данные желательно записывать в текстовый файл форматным
способом.
Чтение данных из открытого для чтения файла осуществляется операторами:
Read( файловая переменная, имя переменной);
ReadLn( файловая переменная, имя переменной);
Во втором случае после чтения из файла значения переменной текстовый курсор переходит в начало новой строки (как на экране терминала).
Внимание! Переменная, указанная в операторах чтения, должна совпадать по типу со считываемым из файла значением.
Пример: прочитать из созданного ранее файла информацию и вывести ее на экран.
Программа:
Program File_3;
Uses CRT;
Var ocenka : 2..5; оценка
sr_ball : Real; средний балл
name : String[15]; фамилия или имя
nomer : String[10]; номер группы
f_text : Text; текстовый файл
Begin
ClrScr;
Assign(f_text, ‘d:\User\f_text.txt’);
ReSet(f_text); открываем файл для чтения
ReadLn(f_text, nomer); читаем из файла номер группы
WriteLn(nomer); выводим его на экран
ReadLn(f_text, name); читаемиз файла фамилию
WriteLn(name); выводим ее на экран
ReadLn(f_text, name); читаем из файла имя
WriteLn(name); выводим его на экран
ReadLn(f_text, ocenka); читаем из файла оценку
WriteLn( ocenka:3); выводим ее на экран
ReadLn(f_text, sr_ball); читаем из файла средний балл
WriteLn( sr_ball:6:2); выводим его на экран
Close(f_text); закрываем файл
ReadLn;
End.
На экран будет выведено:
ИС-09
Иванов
Иван
4.12
Внимание! Функции и процедуры, используемые при работе с типизированными файлами (FileSize, FilePos, Seek, Truncate), для текстовых файлов не используются.
Сложнее работать с текстовыми файлами, в каждой строке которых записаны разнотипные данные.
Пример: создать текстовый файл baza.txt, в каждой строке которого хранить следующие данные:
1. номер учебной группы
2. фамилию студента
3. имя студента
4. его оценку по информатике
5. средний балл сдачи сессии
Другими словами, необходимо создать базу данных на основе текстового файла.
Заполнить эту базу данных информацией о нескольких студентах, конец ввода данных – вместо очередного номера группы просто нажать на клавишу ввода (ввести строку нулевой длины).
Интерфейс:
Номер группы: ИС-09
Фамилия: Иванов
Имя: Иван
Оценка:4
Ср. балл:4.12
Номер группы: ПО-09
Фамилия: Петров
Имя: Петр
Оценка:5
Ср. балл:4.27
Номер группы: ЗИ-09
Фамилия: Сидоров
Имя: Сидор
Оценка:3
Ср. балл:3.42
Номер группы:
Программа:
Program File_4;
Uses CRT;
Var ocenka : 2..5; оценка
sr_ball : Real; средний балл
name : String[15]; фамилия или имя
nomer : String[10]; номер группы
baza : Text; текстовый файл
Begin
ClrScr;
Assign(baza, ‘d:\User\baza.txt’);
ReWrite(baza); открываем файл для записи
Repeat
Write(‘Номер группы:’);
ReadLn(nomer); вводим номер группы
If (Length(nomer) = 0) если длина строки с номером группыравна нулю (сразу нажата клавиша ENTER),
Then Break; то выходим из цикла ввода
Write(baza, nomer:10); если нет, тозаписываем его в файл в 10 позициях (по описанию переменной nomer)
Write(‘Фамилия:’);
ReadLn(name); вводим фамилию
Write(baza, name:15); записываем ее в файл в той же строке в 15 позициях
Write(‘Имя:’);
ReadLn(name); вводим имя
Write(baza, name:15); записываем его в файл в той же строке в 15 позициях
Write(‘Оценка:’);
ReadLn(ocenka); вводим оценку
Write(baza, ocenka:3); записываем ее в файл в той же строке в 3 позициях
Write(‘Ср. балл:’);
ReadLn(sr_ball); вводим средний балл
WriteLn(baza, sr_ball:6:2); записываем его в файл в 6 позициях и переходим на новую строку
Until (False); псевдобесконечный цикл с постусловием
Close(baza); закрываем файл
ReadLn;
End.
Структура созданного файла:
ИС-09 Иванов Иван 4 4.12
ПО-09 Петров Петр 5 4.27
ЗИ-09 Сидоров Сидор 3 3.42
10 позиций 15 позиций 15 позиций 3 поз. 6 поз.
Внимание! Все данные необходимо записывать в текстовый файл форматным
способом, иначе их нельзя будет прочитать из этого файла. Записываемые числовые данные необходимо разделять хотя бы одним пробелом.
В данном случае для записи в файл выделяется
1. для номера группы - 10 позиций,
2. для фамилии или имени - 15 позиций,
3. для оценки - 3 позиции,
4. для среднего балла - 6 позиций.
При чтении разнотипных данных из текстового файла, записанных в одной строке, необходимо учитывать следующие особенности:
1. строки читаются в соответствии с их описанием: если строка описана как String[10], то будут прочитаны ровно 10 позиций,
2. числа читаются до разделителя (пробела, запятой, признака конца строки),
3. в списке ввода оператора чтения Read (ReadLn) формат переменных не указывается.
Пример: прочитать из созданного ранее файла информацию и вывести ее на экран.
Программа:
Program File_3;
Uses CRT;
Var ocenka : 2..5; оценка
sr_ball : Real; средний балл
fam, name : String[15]; фамилия или имя
nomer : String[10]; номер группы
baza : Text; текстовый файл
Begin
ClrScr;
Assign(baza, ‘d:\User\baza.txt’);
ReSet(baza); открываем файл для чтения
While NOT(EOF(baza)) Do
Begin
ReadLn(baza, nomer, fam, name, ocenka, sr_ball); читаем из файла очередную строку с данными
WriteLn(nomer:10, fam:15, name:15, ocenka:3, sr_ball:6:2 ); выводим ее на экран
End;
Close(baza); закрываем файл
ReadLn;
End.
На экране появится:
ИС-09 Иванов Иван 4 4.12
ПО-09 Петров Петр 5 4.27
ЗИ-09 Сидоров Сидор 3 3.42
Конечно, правильное чтение данных из текстового файла возможно только тогда, когда мы точно знаем структуру этого файла.
Записи
На начальных этапах развития программирования, при решении математических, экономических или инженерных задач программисты, как правило, обходились десятком переменных, которые обрабатывались разными алгоритмами. С течением времени объемы обрабатываемых данных стали расти. Приходилось обрабатывать не один-два десятка чисел, а целые таблицы. К тому же таблицы стали содержать не только числовую, но и текстовую информацию. И тут на помощь пришли новые типы данных – массивы, строки, множества. С их помощью можно объединить несколько объектов под одним именем, а затем обращаться к ним поэлементно. Основное требование при создании таких структур – однотипность объединяемых объектов. Однако сложность многих реальных ситуаций требует для своего отражения более гибких средств программирования.
Практика показала, что для обработки больших совокупностей однотипных данных такая структура, как массив, очень полезна. Но массив полезен тогда, когда обрабатывается однотипная информация. Реальные задачи в большинстве своем имеют дело с обработкой данных различных типов: информация по кадрам, статистические данные, бухгалтерский учет, экономические задачи. В этих задачах существенно то, что совместно обрабатывается числовая и текстовая информация, причем, как правило, размерность обрабатываемых данных даже одного типа весьма различна. Например, для хранения данных об одном студенте (номер учебной группы, фамилия, имя, оценка по информатике, средний балл сдачи сессии) нельзя использовать один массив, так как эти данные разнотипны: номер группы, фамилия, имя – строки, оценка – целое, средний балл – вещественное. Конечно, можно использовать несколько массивов: один - для хранения номеров групп, второй – для хранения фамилий и имен, третий – для хранения оценок, четвертый – для хранения средних баллов и так далее. Связь между этими массивами можно установить с помощью индексов. При этом необходимо будет решать сложную задачу целостности информации. Например, если произвести сортировку фамилий во втором массиве по алфавиту, то соответствующим образом необходимо переставить элементы остальных массивов, чтобы фамилии соответствовали остальным данным. Это достаточно сложная задача.
Так возникла необходимость в особой структуре данных, которая позволила бы одновременно хранить и обрабатывать данные различных типов.
Для работы с данными различных типов, но объединенных в одну структуру под одним именем, в Паскале введен новый тип данных – запись.
Записи могут состоять из компонентов различных типов, называемых полями. Каждое поле можно рассматривать как отдельную переменную, имеющую свое имя.
В отличие от ранее рассмотренных типов данных, тип записи описывается в разделе определения типов:
Type TStudent = Record
nomer, fam, name : String[15];
ocenka : 2..5;
sr_ball : Real;
End;
Внимание! Описание записи заканчивается словом End, для которого нет слова Begin.
Описан тип записи с именем TStudent, имеющий поля:
nomer, fam, name - номер группы, фамилия и имя – строки длиной 15 символов,
ocenka - оценка по информатике – интервал от 2 до 5,
sr_ball - средний балл сдачи сессии – вещественное.
Таким образом, при описании полей указываются их имена и через двоеточие – типы. Описание заканчивается словом End.
После определения типа записи можно описать разные базовые структуры этого нового типа в разделе описания переменных:
Var stud_1 : TStudent;
gruppa : Array [1..15] Of TStudent;
baza_gruppa : File Of TStudent;
Описанная переменная stud_1 имеет те же поля, что и запись типа TStudent. Чтобы обратиться к любому поля, необходимо написать имя переменной и через точку – имя поля. Поле записи определенного типа может являться операндом в любых выражениях того же типа, то есть к нему могут применяться операции, допустимые для переменных данного типа:
stud_1.nomer := ‘ИС-09’;
stud_1.fam := ‘Иванов’;
stud_1.name := ‘Ваня’;
stud_1.ocenka := 4;
stud_1.sr_ball := 4.12;
Поскольку обращение к каждому поля записи осуществляется по его имени, то при определении типа записи порядок указания ее полей может быть произвольным. Имя поля в любых операторах указывается явно и, в отличие от индексов элементов массива, его вычислить нельзя. Поля, как самостоятельные имена, вне записи не существуют, поэтому указывать в операторах только имена полей без имени записи нельзя:
.nomer := ‘ИС-09’; это неправильно!
.fam := ‘Иванов’; это неправильно!
Для упрощения работы с записями в Паскале введен специальный оператор, позволяющий сократить написание имен записей – оператор присоединения:
With x Do
оператор;
где With - служебное слово c,
x - имя переменной-записи,
Внутри этого оператора поля переменной-записи обозначаются без имени самой записи:
With stud_1 Do
Begin
nomer := ‘ИС-09’;
fam := ‘Иванов’;
name := ‘Ваня’;
ocenka := 4;
sr_ball := 4.12;
End;
Внимание! Запись может быть введена с клавиатуры и выведена на экран только по полям, а не целиком, то есть в операторах ввода и вывода ReadLn и WriteLn нельзя указывать имя записи без имени поля:
ReadLn(stud_1); это неправильно!
WriteLn(stud_1); это неправильно!
ReadLn(stud_1.ocenka); это правильно!
WriteLn(stud_1.ocenka); это правильно!
Записи могут являться элементами массивов, то есть разрешены массивызаписей, например, описанный выше массив gruppa. Каждый элемент этого массива – отдельная запись со всеми полями, определенными при ее описании. При обращении к элементу такого массива указывается имя массива, индекс элемента и через точку – имя поля:
gruppa[5].nomer := ‘ИС-09’;
gruppa[5].fam := ‘Иванов’;
gruppa[5].name := ‘Ваня’;
gruppa[5].ocenka := 4;
gruppa[5].sr_ball := 4.12;
В этом случае тоже можно использовать оператор присоединения:
With gruppa[5] Do
Begin
nomer := ‘ИС-09’;
fam := ‘Иванов’;
name := ‘Ваня’;
ocenka := 4;
sr_ball := 4.12;
End;
При работе с файлами записей (базами данных) необходимо учитывать то, что для ввода и вывода элементов такого файла – отдельных записей – необходимо использовать рабочую переменную-запись, имеющую такие же поля, что и элементы файла. Для ввода очередного элемента в данный файл сначала необходимо заполнить все поля рабочей переменной, например, операторами ввода:
ReadLn(stud_1.nomer);
ReadLn(stud_1.fam);
ReadLn(stud_1.name);
ReadLn(stud_1.ocenka);
ReadLn(stud_1.sr_ball);
а затем записать эту переменную в файл целиком:
Write(baza_gruppa, stud_1);
Очередная запись читается из файла тоже целиком:
Read(baza_gruppa, stud_1);
после этого ее можно, например, вывести на экран по полям:
With stud_1 Do
WriteLn(nomer:10, fam:15, name:15, ocenka:3, sr_ball:6:2);
В данном случае запись выведена в одну строку форматным способом.
Поле записи может иметь любой разрешенный в Паскале тип и структуру (массив, множество, файл, строку), в том числе может представлять собой в свою очередь запись.
Пример: создать базу данных (файл записей), в которой можно было бы хранить следующие данные о студентах:
учебная группа,
личные данные:
фамилия,
имя,
отчество,
дату рождения:
год,
месяц,
день,
адрес:
город,
улица,
дом,
корпус,
квартира,
телефон.
данные о нескольких студентах (конец ввода – нажатие на клавишу ENTER при запросе номера учебной группы). Прочитать базу данных и вывести на экран номера учебных групп, фамилии, имена и отчества студентов.
Интерфейс:
Группа: ИС-09
Фамилия: Иванов
Имя: Иван
Отчество: Иванович
Год рождения: 1993
Месяц рождения: 2
День рождения: 23
Город: Иркутск
Улица: Трилиссера
Дом: 123
Корпус: 2
Квартира: 45
Телефон: 235347
Группа:
На экран будет выведено:
ИС-09 Иванов Иван Иванович
Программа:
Program Baza_student;
Uses WinCrt;
Type TKadr = Record основная запись
gruppa : String[10];
fio : Record запись в записи
fam, name : String[10];
otch : String[15];
End;
adres: Record запись в записи
gorod, ulica : String[20];
korp, dom, kv: String[5];
telefon : String[10];
End;
data : Record запись в записи
den : 1..31;
mes : 1..12;
god : 1900..2000;
End;
End;
Var student : TKadr;
baza : File Of TKadr;
Begin
ClrScr;
Assign(baza, 'D:\User\baza_student.dat');
ReWrite(baza); открываем файл для записи
Repeat начало цикла ввода
With student Do оператор присоединения
Begin
Write('Группа: ');
ReadLn(gruppa);
If (Length(gruppa)=0) если номер группы не введен,
Then Break; то выходим из цикла ввода
Write('Фамилия: ');
ReadLn(fio.fam);
Write('Имя: ');
ReadLn(fio.name);
Write('Отчество: ');
ReadLn(fio.otch);
Write('Год рождения: ');
ReadLn(data.den);
Write('Месяц рождения: ');
ReadLn(data.mes);
Write('День рождения: ');
ReadLn(data.den);
Write('Город: ');
ReadLn(adres.gorod);
Write('Улица: ');
ReadLn(adres.ulica);
Write('Дом: ');
ReadLn(adres.dom);
Write('Корпус: ');
ReadLn(adres.korp);
Write('Квартира: ');
ReadLn(adres.kv);
Write('Телефон: ');
ReadLn(adres.telefon);
End; конец оператора присоединения
Write(baza, student); запись в базу данных
Until (False); конец цикла ввода
ReSet(baza); открываем файл для чтения
While Not(EOF(baza)) Do пока не конец файла
Begin
Read(baza, student); читаем данные из файла
With student Do и выводим на экран форматным способом
WriteLn(gruppa:10, fio.fam:10, fio.name:10, fio.otch:15);
End;
Close(baza); закрываем файл
ReadLn;
End.
На практике часто бывает удобно сделать некоторые поля записи изменяемыми (вариантными).
Например, если имеются две записи с одинаковыми полями, различающихся только одним полем, то эти две записи можно представить одной, а различающиеся поля сделать вариантными. Тип и структура вариантного поля изменяются в зависимости от значения особого поля записи, называемого селектором (переключателем). В качестве селектора можно использовать поле любого упорядоченного типа: целого, символьного, интервального или перечисляемого. Конкретные значения, принимаемые селектором, называются ключами вариантов.
Записи с вариантными полями называются записями с вариантами. Вариантные поля в них описываются после неизменяемых. Наличие вариантного поля указывается конструкцией:
Case селектор: тип Of
ключ-1: (варимант-1);
ключ-2: (вариант-2);
ключ-3: (вариант-3);
……………………
ключ-n:(вариант-n);
End;
Тип селектора и перечень его возможных значений задаются в разделе определения типов Type.
Например, положение точки на плоскости можно задавать прямоугольными (x, y) или полярными (r, φ) координатами. Тогда запись с вариантами coord может быть описана так:
Type TDecpol = (decart, polar);
TCoord = Record
Case wid : TDecpol Of
decart : (x, y : Real);
polar : (r : Real; fi : 0..360);
End;
End;
Var coord : TCoord;
Селектором в данном случае является поле перечисляемого типа coord.wid , принимающее только два значения – decart и polar. При значении селектора decart поля переменной coord будут следующими:
coord.x ,coord.y типа Real,
а при значении поля polar – следующими:
coord.r типа Real,
coord.fi типа 0..360.
При использовании записей с вариантами необходимо руководствоваться следующими правилами:
ü все имена полей должны быть различными, даже если они встречаются в разных вариантах,
ü если вариант пустой (для него поля нет), то он записывается так:
ключ : ();
ü любой список полей может иметь только одну вариантную часть, которая должна следовать за фиксированной частью записи,
ü в свою очередь, каждый вариант может содержать в себе вариантную часть, то есть допускаются вложенные варианты.
Подпрограммы
Современный процесс программирования представляет собой коллективное промышленное изготовление программных продуктов на основе новых технологий программирования.
Одной из таких технологий является метод структурногопрограммирования, предполагающий, что структура программы должна отражать структуру решаемой задачи, а алгоритм решения должен быть ясно виден из текста программы.
Метод структурного программирования предполагает:
· проектирование программ на основе метода пошаговой детализации (нисходящее программирование),
· использование модульного программирования,
· структурное кодирование программы.
Основой метода пошаговой детализации является идея программирования “сверху вниз” с постепенной разбивкой исходной задачи на ряд более мелких подзадач, при этом выполняется последовательное уточнение: сначала задача определяется в общих чертах, затем происходит постепенное уточнение ее структуры. На очередном шаге каждая подзадача, в свою очередь, разбивается на ряд других. Решение отдельного фрагмента сложной задачи может представлять собой самостоятельный программный блок – подпрограмму. Поэтому программу решения сложной задачи при нисходящем программировании можно представить как иерархическую совокупность относительно самостоятельных модулей-подпрограмм. В этом и заключается идея модульного программирования.
Структурное кодирование должно обеспечить максимальное удобство для восприятия и понимания программы человеком. При прочтении программы должна четко прослеживаться логика ее работы. Основная структурная теорема утверждает: алгоритм любой сложности можно реализовать, используя только три конструкции (структуры) - цепочку (следование), ветвление и цикл. Существенной особенностью этих структур является то, что каждая из них имеет только один вход и только один выход, что обеспечивает логическую последовательность структуры программы. Все эти структуры определяются рекурсивно: каждая из входящих в структуру групп операторов может быть одним оператором, группой операторов и может быть любой из допустимых структур – допускается вложение структур.
Длинная программа вообще подобна блюду с макаронами: потянешь за одну макаронину – обязательно что-то поползет в другом месте. Одним из способов разбиения длинных, необозримых программ на обозримые, более короткие, является использование подпрограмм.
В алгоритмах часто встречаются однотипные участки, на которых процесс вычислений носит одинаковый характер, но требует использования различных значений переменных. Для каждого из таких повторяющихся участков может быть составлена отдельная программа, причем в такой форме, что к ней можно было бы обратиться из любого места основной программы, и после ее выполнения вернуться обратно в то место, откуда она была вызвана. Такая отдельная программа, связанная с основной, называется подпрограммой.
Подпрограмма, произведя вычисления при заданных (входных) значениях аргументов, обеспечивает возврат с вычисленными (выходными) значениями в то же место основной программы, откуда подпрограмма вызывалась. Такое построение программы облегчает процесс программирования – большая программа разбивается на отдельные небольшие части, которые легко читаются и понимаются, чем облегчается их отладка и тестирование.
Таким образом, подпрограмма представляет собой относительно самостоятельную программу, которая может быть написана отдельно от других программ, а затем подключена к основной.
Примером подпрограмм являются стандартные функции или библиотечные подпрограммы, имеющиеся в программном обеспечении любого компьютера. В отличие от таких подпрограмм, в дальнейшем мы будем рассматривать подпрограммы, которые создает программист для решения конкретных задач.
В Паскале различают два типа подпрограмм:
1. подпрограммы-функции,
2. подпрограммы-процедуры.
Подпрограммы-функции
Набор стандартных функций Паскаля, как и других алгоритмических языков, ограничен, поэтому в нем предусмотрены средства создания дополнительных функций самим программистом. Обращаться к таким функциям можно, как и к стандартным, по имени, указывая при этом необходимые значения аргументов.
Функции располагаются в основной программе между разделом описания переменных Var и Begin основной программы. Функции используются для вычисления единственного значения, присваиваемого имени самой функции. Это значение вычисляется внутри самой функции по нужному алгоритму с помощью переменных (аргументов), называемых формальными параметрами.
Как и все программы в Паскале, функция состоит из заголовка, блока описаний и блока операторов:
Function Geron(x, y, z : Real):Real; заголовок функции
Var p : Real; описание локальных переменных
Begin начало блока операторов
p := (x + y + z)/2.0;
Geron := Sqrt(p*(p – x)*(p – y)*(p – z)); вычисленное значениеприсваивается имени функции
End;
Внимание! После оператора End ставится точка с запятой.
Эта функция вычисляет площадь треугольника по формуле Герона – по трем его сторонам.
Заголовок функции
Function Geron(x, y, z : Real):Real;
начинается со слова Function , за которым следует ее имя, в данном случае Geron. После имени функции в скобках перечисляются имена и типы аргументов функции – входных данных или формальных параметров. В данном случае это x, y, z типа Real. Если имеются формальные параметры нескольких типов, то они группируются по типам, а между типами ставятся точки с запятой. Заголовок заканчивается указанием типа самой функции, то есть типа результата, вычисляемого этой функцией. В данном случае это Real.
Аргументы функции называются формальными параметрами лишь потому, что они определяют только способ вычисления значения функции, реализацию алгоритма. При обращении к функции в основной программе формальные параметры автоматически заменяются фактическими параметрами или их конкретными значениями, для которых необходимо произвести вычисления:
s := Geron(3.0, 4.0, 5.0);
В данном случае формальные параметры x, y, z функции Geron заменяются соответственно фактическими аргументами 3.0, 4.0, 5.0 , для которых и вычисляется значение функции. Вычисленное значение присваивается имени самой функции Geron и далее - переменной s. В этом примере s = 6.0.
Вся программа, использующая функцию Geron, может иметь следующий вид:
Program Primer;
Uses CRT;
Var a, b, c, s : Real; описание фактических (глобальных) параметров
Function Geron(x, y, z : Real):Real; заголовок функции
Var p : Real;
Begin
p := (x + y + z)/2.0;
Geron := Sqrt(p*(p – x)*(p – y)*(p – z));
End; конец функции
Begin начало основной (головной) прогр