Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка вторая.doc
Скачиваний:
88
Добавлен:
05.06.2015
Размер:
1.66 Mб
Скачать

1.Организовать ввод фио только на русском языке.

Program Mnogestv5;

{Задача.Организовать ввод ФИО только на русском

языке.

Решение.Арсланов Ильдар,

ЦНИТ "Северная Звезда"

16.03.2000.}

Uses

Crt;

Var

litera:set of char;

Name,s:string;

ch:char;

Flag:boolean;

x,I:integer;

Begin

ClrScr;

Randomize;

litera:=[' ','А'..'п','р'..'я',#8];

Write('Введите фамилию,имя,отчество ');

Writeln;

Repeat{считатьName}

Repeat {считать в ch код клавиши}

ch:=readkey;

If ch=#8 {Если нажата клавиша BACKSPACE}

then

ch:=#8; {Заменяем неправильную букву}

if ch<>#13

Then

begin

Flag:=ch in litera;

If flag {если символ входит в множество}

Then

begin

name:=name+ch; {приклеить символ к name}

write(ch); {напечатать этот символ}

end

Else {иначе вверху}

begin

sound(345);

delay(3000);

nosound;

Writeln('Загрузите русский шрифт или');

Writeln('нажмите CTRL-SHIFT');

Writeln('и введите ваше имя ');

end;

end;

Until Flag; {завершить ввод очеред.символа}

Until ch=#13; {завершить ввод name т.к нажата ENTER}

Writeln;

Writeln('Здравствуйте, ',name);

Writeln('Сколько тебе лет ');

Readln(x);

Writeln('А мне,компьютеру ',random(100),' лет');

Readln;

End.

2. Описать множество Mn(1..50) и поместить в него все числа из диапазона A..B, делющиеся без остатка на k.

ProgramMnoj3;

{Задача. Описать множество Mn(1..50) и поместить в него все

числа из диапазона A..B, делющиеся без остатка на k.

Решение. Грушин Кирилл

Центр НИТ "Северная Звезда"

16.03.2000г.}

Uses

Crt;

Type

Chisla = Set of 1..50;

Var

i, k, A, B : integer;

Mn : Chisla;

Procedure Prov;

begin

If (A < 0) or (B < 0)

Then

begin

Sound (1000);

Write ('Неправильный ввод диапазона!!!');

Delay (800);

NoSound;

end;

end;

Procedure Vvod;

begin

Prov;

Mn := [];

For i := A to B do

begin

If i mod k = 0

Then

Mn := Mn + [i];

If i in Mn

Then

Writeln (i,' - Помещено')

Else

Writeln (i,' - Не помещено');

end;

end;

Begin

ClrScr;

TextColor (White);

Write('Введите диапазонA..Bчерез пробел...');

Readln(A,B);

Write ('Введите число k-делитель...');

Readln (k);

Vvod;

Readln;

End.

3. Решить ребус СОЛЬ + СОЛЬ = ЛОСЬ.

ProgramRebus2;

{Задача. Решить ребус СОЛЬ + СОЛЬ = ЛОСЬ.

Решение. Грушин Кирилл

Центр НИТ "Северная Звезда

20.03.2000г.}

Uses

Crt;

Type

Chisla = Set of 0..9;

Var

X : integer;

l, o, s, i : 0..9;

Mn1, Mn2 : Chisla;

Procedure Vivod;

begin

Writeln(' ',X:5); Writeln(' +');

Writeln(' ',X:5); Writeln(' ----');

Writeln(' ',l, o, s, i);

Writeln; Writeln; Writeln;

end;

Procedure Opred;

begin

Mn1 := [];

Mn2 := [];

For s := 1 to 5 do

begin

Mn1 := Mn1 + [s];

For o := 0 to 9 do

If not (o in Mn1)

Then

begin

Mn1 := Mn1 + [o];

For l := 0 to 9 do

If not (l in Mn1)

Then

begin

Mn1 := Mn1 + [l];

For i := 0 to 9 do

If not (i in Mn1)

Then

begin

Mn1 := Mn1 + [i];

X := 1000*s + 100*o + 10*l + i;

Mn2 := [l,o,s,i];

Mn1 := Mn1 - [i];

Vivod;

end;

Mn1 := Mn1 - [l];

end;

Mn1 := Mn1 - [o];

end;

Readln;

Mn1 := Mn1 - [s];

end;

end;

Begin

ClrScr;

TextColor (LightGreen);

Opred;

Readln;

End.

Комбинированный тип данных. Запись. Описание записи. Доступ к полям записи. Оператор With. Примеры решения задач.

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

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

Приведем пример описания переменной, имеющей структуру записи:

Var   Address : Record     HouseNumber : Integer;     StreetName : String[20];     CityName : String[20];     PeopleName : String; End;

Отметим, что поля StreetName и CityName имеют одинаковый тип: String[20]. Поскольку в описании эти поля могут располагаться в любом порядке, то можно сократить описание записи с полями одинакового типа. Сокращенное описание записи Address выглядит следующим образом:

Var   Address : Record     HouseNumber : Integer;     StreetName, CityName : String[20];     PeopleName : String; End;

Каждая компонента записи называется полем. В переменной записи Address поле с именем HouseNumber само является переменной типа Integer, поле StreetName - двадцатисимвольной строкой и т.д.

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

Оператор, который присваивает полю HouseNumber значение 45, выглядит так:

  Address.HouseNumber := 45;

Таким же образом присваиваются значения другим полям записи Address :

  Address.StreetName := 'Профсоюзная';   Address.CityName := 'Сургут';   Address.PeopleName := 'Петрова Алла Ивановна';

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

Предположим, имеется следующее описание:

Type   Date = Record     Day : 1..31;     Month : (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec);     Year : Integer;   End; Var   HisBirth, MyBirth : Date;

После приведенного описания переменные HisBirth и MyBirth имеют тип записи Date. Помимо действий над отдельными полями записей HisBirth и MyBirth можно выполнять операции над всей записью. Следующий оператор присваивания устанавливает равенство значений записей HisBirth и MyBirth :

  HisBirth := MyBirth;

Это присваивание эквивалентно следующей последовательности операторов:

  HisBirth.Day := MyBirth.Day;   HisBirth.Month := MyBirth.Month;   HisBirth.Year := MyBirth.Year;

Для переменных одного типа можно проверить выполнение отношения равенства или неравенства ("=", "<>"). После выполнения приведенных выше присваиваний следующее булево выражение будет иметь значение True:

HisBirth = MyBirth;

Рассмотрите пример описания процедуры, которая получает запись в качестве параметра-значения и печатает дату в сокращенной стандартной форме, используя формат (MM-DD-YYYY).

Procedure WriteDate(OneDate : Date); Begin   Write(Ord(OneDate.Month)+1);   Write('-');   Write(OneDate.Day:2);   Write('-');   Write(OneDate.Year:4); End;

Так как на тип компонент массива не накладывается ограничений, то можно использовать массив, компонентами которого являются записи. Посмотрите описание такого массива:

Var

  Birthdays : Array [1..Persons] of Date;

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

Например, следующий оператор печатает содержимое поля Year записи Birthdays[3]:

  Write(Birthdays[3].Year);

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

Задание. Рассмотрите следующие описания:

Type   Date = Record     Day : 1..31;     Month :1..12;     Year : 1..9999   End; Reminder = Record     Message : Array [1..5] of String;     Event : Date End; Var   Today : Date;   Memos : Array [1..100] of Reminder;   Calendar : Array [1..365] of Date;

Запишите в тетрадь, какой тип, если он определен, у следующих идентификаторов?

а) Today.Year б) Memos [2] в) Memos [4].Month г) Calendar [200] д) Memos [16].Message[2] е) Memos [16].Message[1],[2] ж) Calendar[1].Date з) Memos [10].Event

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

Приведем описание массива, компоненты которого являются записями:

Var   Payroll : array [1..Workers] of     record       FirstName, LastName : string;       Residence : record         HouseNumber : real;         StreetName, CityName : string;         StateName : Array [1..2] char;         ZipCode : integer;     end;       Phone : record         AreaCode, Exchenge : 1..999;         Line : 1..9999;         rnd;       PayScale : 'A' ..'G'; end;

Отметим, что два поля Residence и Phone являются записями. Как выполнить обращение к полям этих записей? Как распечатать условный шифр рабочего № 7? Поскольку это поле располагается во вложенной записи, то следует указать как имя самой записи, так и имя записи, в которую данная запись входит.

  write (Payroll[7].Residence.ZipCode);

Аналогично приведенное присваивание корректирует шифр рабочего № 23:

  Payroll[23].Phone.AreaCode :=804;

Оператор if, представленный ниже, выполняет проверку инициала рабочего № 58:

  if Payroll[58].LastName[1] in ['T'..'Z'] Then ...

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

Общая форма записи:

  with <имя переменной> do <оператор>

В рамках оператора, определяемого внутри оператора With, к полям определяемой переменной можно обращаться просто по имени. Например,

with Payroll[7].Residence do   ZipCode := 2345; for i := 1 to Workers do   with Payroll[i] do     if PayScale < 'G'       then         PayScale := Succ(PayScale);

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

  with Payroll[14].Residence do     begin       writeln(HouseNumber,' ',StreetName);       writeln(CityName,',',StateName,',' ,ZipCode);     end;

В рамках составного оператора, следующего за with, каждое обращение к имени поля автоматически связывается с записью Payroll[14].Residence. Печать адресов всех рабочих выполняется при помощи следующего оператора цикла:

for i := 1 to Workers do   with Payroll[i].Residence do     begin       writeln(HouseNumber,' ',StreetName);       writeln(CityName,',',StateName,',' ,ZipCode);     end;

Операторы with могут быть вложенными. Приведенные ниже три оператора эквивалентны друг другу:

  1. Payroll[i].Residence.HouseNumber := 50;

  2. with Payroll[i].Residence do   HouseNumber := 50;

  3. with Payroll[i] do   with Residence do     HouseNumber := 50;

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

with Payroll[5] do   with Payroll[17]do     PayScale :='A';

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

Рассмотрите решение задачи.

Задача. В массиве хранятся данные об учениках класса: школа, фамилия, класс. Вывести список учеников, которые учатся в восьмом классе.

Program LipovsevM; Uses   Crt; Type Uchenik=record       Shkola : integer;       Fam : string[15];       Klass : integer;     end; Var   I,n,a,j : integer;   Massiv : array[1..100] of Uchenik; Рrocedure Poisk; Begin   for i:=1 to n do     if massiv[i].klass=8       then         with massiv[i] do           writeln(Shkola:4,' ',Fam:15,' ',klass); End; Begin   ClrScr;   writeln('Введите число учеников ');   write('->');   read(n);   for i:=1 to n do     begin       writeln('Введите через пробел номер школы и фамилию ученика ');       write('->');       with massiv[i] do         begin           readln(Shkola,Fam);           write('Введите класс ученика (только число) ->');           read(Klass);         end;     end;   writeln('Ученики 8-ых классов:');   writeln('Школа Фамилия Класс');   writeln('---------------------------------');   Poisk;   ReadKey; End.

Записи, рассмотренные выше - это записи с фиксированными частями. Они имеют в различных ситуациях строго определенную структуру. Соответственно записи с вариантами в различных ситуациях могут иметь различную структуру.

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

Const   Kol = 1000; Type   Entry = Record       Autor, Title, Publisher, City : String;       Year : 1..2000;   End; Var   List : Array[1..Kol] of Entry;

Что произойдет, если некоторые из входов не являются ссылками на книги, а содержат ссылки на журнальные статьи. Если ограничиваться только записями с фиксированными частями, то следует описать различные массивы для каждого вида записей. Использование записей с вариантами позволяет образовать структуру, каждый вход которой соответствует содержанию записи. Опишем новый тип, в котором перечислены различные входы:

Type EntryType= (Book,Magazine);

Теперь можно привести скорректированное описание Entry

Type   Entry = Record       Autor, Title : String;       Year : 1..2000;       Case EntryType of         Book : (Publisher, City : String);         Magazine : (MagName : String,         Volume, Issue : Integer)     End;

Это описание делится на две части: фиксированную и вариантную. Поля Autor, Title, Year составляют фиксированную часть. Оставшаяся часть описания Entry образует вариантную часть, структура которой, подобно хамелеону, может меняться в пределах двух альтернативных определений.

Первая строка вариантной части представляет оператор Case, который отличается тем, что в качестве селектора применяется идентификатор типа. Значения EntryType используются в качестве имен двух альтернатив определения записи. Когда эта компонента имеет значение Book, можно обращаться к следующим полям:

  Autor,Title,Year,Publisher,City

С другой стороны, когда она принимает значение Magazine, то можно обращаться к таким полям:

  Autor, Title, Year, MagName, Volume, Issue

В такой ситуации возникает естественный вопрос: как программа может хранить информацию о текущем состоянии каждой записи? Другими словами, каким образом можно узнать , что List[3] содержит ссылку на книгу, а List[4] - ссылку на журнал?

Естественное решение этой проблемы заключается в добавлении в каждой записи нового поля, называемого полем тега. Язык Паскаль позволяет за счет совмещения задать описание поля тега в сокращенной форме:

Type   Entry = Record       Autor, Title : String;       Year : 1..2000;       Case TAG : EntryType of         Book : (Publisher, City : String);         Magazine : (MagName : String,         Volume, Issue : Integer)     End;

Поле, названное TAG, является переменной типа EntryType. Когда запись содержит ссылку на книгу, TAG следует присвоить значение Book. Когда запись содержит ссылку на журнал, TAG следует присвоить значение Magazine.

Рассмотрите последовательность операторов, где в RefList[12] помещается ссылка на книгу:

RefList[12].TAG := Book; RefList[12].Autor := 'Thomas Hobbes'; RefList[12].Title := 'Leviathan'; RefList[12].Year := 1651; RefList[12].Publisher := 'Andrew Crooke'; RefList[12].City := 'London';

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

Procedure PrintRef(Citation : Entry); Begin   Writeln(Citation.Autor);   Writeln(Citation.Title);   Writeln(Citation.Year);   If Citation.TAG = Book     Then       Writeln(Citation.Publisher,', ',Citation.City)     Else       Begin         Writeln(Citation.MagName);         Writeln(Citation.Volume'-',Citation.Issue)       End; End;

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

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

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

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

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

Рассмотрите два примера решения задачи с вариантами.

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

Program LipovsevM; Uses   Crt; Type   Uchenik=record       Name:string[10];       Fam:string[15];       Otch:string[15];       Ulica:string[20];       Dom:string[5];       Kvartira: integer;       case tel: boolean of         False:();         True:(Telefon:string[15]);     end; Var   Massiv : array[1..100] of Uchenik;   I,n : integer;   Otvet : 0..1; Begin   ClrScr;   TextColor(9);   write('Введите число учеников->');   readln(n);     for i:=1 to n do       begin         with massiv[i] do           begin             write('Введите имя ',i,'-го ученика ->');             readln(name);             write(''Введите фамилию ',i,'-го ученика ->');             readln(fam);             write(''Введите отчество ',i,'-го ученика ->');             readln(otch);             write(''Введите улицу ',i,'-го ученика ->');             readln(ulica);             write(''Введите дом ',i,'-го ученика ->');             readln(dom);             write(''Введите квартиру ',i,'-го ученика ->');             readln(kvartira);             write('Есть ли у ',i,'-го ученика телефон (0-нет, 1-да->');             readln(otvet);               if otvet=1                 then                   begin                     tel:=True;                     write(''Введите телефон ',i,'-го ученика ->');                     readln(telefon);                   end;           end; End;   TextColor(red);   writeln('Список учеников, до которых нельзя дозвониться:');     for i:=1 to n do       begin       with massiv[i] do         if tel=False           then             begin               writeln('Имя:',name);               writeln('Фамилия:',fam);               writeln('Отчество:',otch);               writeln('Улица:',ulica);               writeln('Дом:',dom);               writeln('Квартира:',kvartira);             end;       end;   ReadKey; End.

Задание. Будьте готовы объяснить решение предыдущей задачи и последующей учителю. Если затрудняетесь в чтении алгоритма решения задачи, то обратитесь за помощью к учителю.

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

Program SedihA; Uses   Crt; Type   TypePubl = (Book,Journal,Newspaper);   Litter = record       Title : string[50];       Author : string[50];       case V : TypePubl of         Вook : (YearB : integer);         Journal : (Num : 1..12;         YearJ : 1900..2000);         Newspaper : (Day : 1..31;         Month : 1..12;         YearN : integer);     end; Const   Count = 10; Var   Katalog : array [1..count] of Litter;   NumArray : 1..count;   YesLitter : Boolean;   Vybor : byte;   Edition : Type_Publ;   CountFind : integer; Procedure InputData; Begin   writeln;   writeln('Введите данные о литературе ', NumArray,' :');   write('Введите число, указывающее вид издания: ');   Write('1-книга, 2-журнал, 3-газета : '); readln(Vybor);   case Vybor of     1 : Katalog[NumArray].v:=Book;     2 : Katalog[NumArray].v:=Journal;     3 : Katalog[NumArray].v:=Newspaper;   end;   with katalog[NumArray] do     begin       write('Фамилия автора? ');       readln(Author);       write('Название? ');       readln(Title);       case v of         Book : begin           write('Год издания ? ');           readln(YearB);         end;         Journal : begin           write('Номер ? ');           readln(Num);           write('Год издания ? ');           readln(YearJ);         end;         Newspaper : begin           write('Дата издания: День? ');           readln(Day);           write('Месяц? ');           readln(Мonth);           write('Год? ');           readln(YearN);         end;       end;     end; End; Procedure WriteData; Begin   writeln;   with Katalog[NumArray] do     begin       writeln('Название : ',Тitle);       writeln('Фамилия автора: ',Аuthor);       case v of         Book : writeln('Год издания : ',YearB);           Journal: begin           writeln('Номер : ', Num);           writeln('Год издания : ',YearJ);         end;         Newspaper : writeln('Дата издания: День: ',Day,' Месяц: ',Month,'Год: ',YearN);       end;     end; Еnd; Procedure FindLitter; Begin   writeln('Поиск литературы по типу издания: ');   writeln;   write('1-книга, 2-журнал, 3-газета: ');   readln(Vybor);   case Vybor of     1 : Edition:=Book;     2 : Edition:=Journal;     3 : Edition:=Newspaper;   end;   YesLitter:=False;   CountFind:=0;   for num_array:=1 to count do     if katalog[num_array].v = edition       then         begin           YesLitter:=True;           CountFind:=CountFind+1;           WriteData;         end;       if not YesLitter         then           writeln('В иблиотеке нет такой литературы')         else           writeln('Всего в библиотеке ',CountFind,' таких изданий'); End; Begin   ClrScr;   for NumArray:=1 to Count do     InputData;   writeln;   FindLitter; End.

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

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

  • брусья,

  • вольные упражнения,

  • прыжки на дорожке,

  • прыжки через коня;

  • для юношей

  • кольца,

  • перекладина,

  • для девушек

  • бревно

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

а) показавших лучший результат по каждому виду; б) показавших лучший результат по всем видам многоборья, в) не получивших ни одного призового места.

  1. Составьте прайс-лист магазина "Техника", включающий в себя марку предприятия-производителя, страну-производитель и ,в зависимости от этих данных, наименования товара, его цену, количество единиц товара на складе. Составьте программу, которая обеспечивает ввод полученной информации, распечатку ее в виде таблицы. Выведите на экран меню, а затем информацию о товаре в зависимости от запроса покупателя.

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

  3. Составьте банк данных членов своей семьи и (или) ближайших родственников, включающий в себя имя, отчество, степень родства, и в зависимости от введенной информации в поле <МолодойСтарый> придумайте варианты полей (например, хобби, любимый анекдот, количество медалей, количество внуков, любимый напиток, любимая девочка, лучший друг, объем имеющегося наследства). Информацию о каждом родственнике оформите в программе в виде записи с вариантами. Совокупность записей объедините в массив. Составьте программу, которая обеспечивает ввод полученной информации, распечатку ее в виде таблицы. Выведите на экран меню, а затем информацию о родне в зависимости от Вашего запроса.

  4. Составьте банк данных своих одноклассников, включающий в себя фамилию, имя, почтовой и (или) электронный адрес, телефон, а также в зависимости от поля <Друг> наличие соответствующей дополнительной информации по своему усмотрению. Информацию о каждом товарище оформите в программе в виде записи с вариантами. Совокупность записей объедините в массив. Составьте программу, которая обеспечивает ввод полученной информации, распечатку ее в виде таблицы. Выведите на экран меню, а затем информацию о друзьях в зависимости от Вашего запроса.

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

  6. Составьте банк данных районного отдела милиции, включающий в себя фамилию, имя и отчество нарушителя, дату рождения, и в зависимости от поля <Судимость> наличие соответствующей дополнительной информации по своему усмотрению (например, наличие клички, мера наказания, срок заключения). Информацию о каждом нарушителе оформите в программе в виде записи с вариантами. Совокупность записей объедините в массив. Составьте программу, которая обеспечивает ввод полученной информации, распечатку ее в виде таблицы. Выведите на экран меню, а затем информацию в зависимости от Вашего запроса.

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

  • фамилию, имя, отчество;

  • номер телефона;

  • адрес;

  • наличие задолженности по оплате (в массиве по всем месяцам года).

Предусмотрите в программе варианты полей в зависимости от заполнения поля <Задолженность по оплате> (например, размер долга, отключение от междугородней сети, подсчет пени и другое). По введенной информации и запросу пользователя предусмотреть в программе вывод предупреждения абонентов, имеющих задолженность, и какое-либо поощрение ответственным плательщикам.

  1. Составить программу, собирающую данные об авиакомпаниях и выдающую справку туристу до запрашиваемого места. Справка должна содержать:

  • название авиакомпании;

  • название рейса;

  • номер рейса;

  • тип самолета;

  • даты вылета (содержатся в массиве);

  • наличие мест в 1 и 2 классах.

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

  1. Познакомившись с содержанием предыдущих задач придумайте свою интересную задачу и решите ее.

Сортировка записей.

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

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

Program Ski; Uses   Crt; Type   inf= record       num: byte;       name,strana: string[30];       rez: real;     end; Var   m: array [1..100] of inf;   i,j,k,l: integer; Procedure Input; Begin   write('Введите количество участников соревнований: ');   readln(k);   for i:=1 to k do     with m[i] do       begin         write('Введите номер участника: ');         readln(num);         write('Введите фамилию: ');         readln(name);         write('Какую страну представляет: ');         readln(strana);         write('Показанный результат: ');         readln(rez);         writeln;       end; End; Procedure Vich; Var   o: real;   n,s:string;   nm: byte; Begin   ClrScr;   for i:=1 to k-1 do     for j:=i+1 to k do       begin         if m[j].rez<m[i].rez           then             begin               o:=m[j].rez;{Меняем результаты}               m[j].rez:=m[i].rez;               m[i].rez:=o;               nm:=m[j].num;{Меняем номера}               m[j].num:=m[i].num;               m[i].num:=nm;               n:=m[j].name;{Меняем фамилии}               m[j].name:=m[i].name;               m[i].name:=n;               s:=m[j].strana; {Меняем страны}               m[j].strana:=m[i].strana;               m[i].strana:=s;             end;       end; End; Procedure Output; Begin   for i:=1 to k do     with m[i] do       begin         writeln('',i,'-ое место занял:');         writeln('участник под номером: ',num);         writeln('Его фамилия: ',name);         writeln('Представляет страну : ',strana);         writeln('Показанный результат: ',rez:3:1);         writeln;       end; End; Begin   ClrScr;   Input;   Vich;   Output;   ReadKey; End.

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

  • сортировка вставкой;

  • сортировка выбором;

  • сортировка методом простого обмена;

  • сортировка с помощью рекурсии.

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

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

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

  3. Составить программу, выдающую справку о номере квартиры, в которой проживает жилец. В доме имеется N квартир и проживает M человек. Пользователь вводит фамилию жильца. Если в доме поживает несколько жильцов с такой фамилией, то выдается сообщение о необходимости ввести инициалы. Если инициалы у нескольких жильцов совпадают, то необходимо ввести год рождения. Если с такими данными найдется один жилец (несколько), то вывести номер (номера) квартир, где он (они) проживают и все введенные о нем (них) сведения. Если жильца с такой фамилией нет, то вывести сообщение об этом.

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

  • месяц анализа данных;

  • фамилию, имя, отчество;

  • номер телефона;

  • адрес;

  • имеющиеся льготы по оплате;

  • абонентская плата;

  • стоимость междугородних разговоров;

  • стоимость дополнительных платных услуг.

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

  1. Составить программу, собирающую данные об авиакомпаниях и выдающую справку туристу до запрашиваемого места. Справка должна содержать:

  • название авиакомпании;

  • название рейса;

  • номер рейса;

  • тип самолета;

  • даты вылета (содержатся в массиве);

  • наличие мест в 1 и 2 классах;

  • стоимость перелета.

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

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

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

Иванов Александр билет № 12 (отлично)

Вывести информацию о результатах экзамена в следующем виде:

Количество экзаменуемых - 25 Сдали на "отлично" - 7 Сдали на "хорошо" - 10 Сдали на "удовлетворительно" - 7 Сдали на "неудовлетворительно" - 1 Не явились - нет

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

  2. Составить программу, организующую заполнение массива записями, содержащими информацию о здоровье детей в лагере отдыха. Запись должна содержать поля:

  • фамилия, имя ребенка;

  • дата прибытия в лагерь;

  • вес ребенка (на день прибытия, через 10 дней, через 20 дней);

  • рост ребенка;

  • возраст;

  • номер отряда;

  • наличие хронических заболеваний.

Вывести данные о детях, увеличивающих свой вес и о детях, которые худеют.

  1. Познакомившись с содержанием предыдущих задач придумайте свою интересную задачу и решите ее.

Понятие подпрограммы. Процедуры и функции. Стандартные подпрограммы. Примеры употребления подпрограмм в решении задач.

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

Подпрограммы решают три важные задачи:

  • избавляют от необходимости многократно повторять в тексте программы аналогичные фрагменты;

  • улучшают структуру программы, облегчая ее понимание;

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

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

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

  2. Иногда слишком много мелочей закрывают главное. Полезно убрать в подпрограмму подробности, заслоняющие смысл основной программы.

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

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

  5. Все, что Вы сделали хорошо в одной программе, Вам захочется перенести в новые. Для повторного использования таких частей лучше сразу выделять в программе полезные алгоритмы в отдельные подпрограммы.

Подпрограммы могут быть стандартными, т.е. определенными системой, и собственными, т.е. определенными программистом.

Стандартная подпрограмма (процедура или функция) - подпрограмма, включенная в библиотеку программ ЭВМ, доступ к которой обеспечивается средствами языка программирования. Вызывается она по имени с заданием фактических параметров с типом описанным при описании данной процедуры в библиотечке процедур и функций.

Из набора стандартных процедур и функций по обработке одного типа информации составляются модули. Каждый модуль имеет своё имя (мы уже хорошо знакомы с модулями Crt, Graph). Доступ к процедурам и функциям модуля осуществляется при подключении этого модуля (Uses Crt, Graph).

Help содержит подробные описания предусмотренных средой программирования процедур и функций. Для вызова помощи при работе со стандартными процедурами и функциями нужно поставить на имя подпрограммы курсор и нажать клавиши <Ctrl+F1>. Описание процедур и функций в Help строится по стандартному принципу.

Задание. Вызовите помощь по функции Cos и рассмотрите предоставленную информацию.

Сначала идет краткое описание подпрограммы (в одну фразу). Далее под словом Declaration (Объявление) следует интерфейсная часть процедуры или функции, которая особенно часто необходима для определения типа переменных при обращении к ним. Далее под словом Target приводятся платформы, на которых может использоваться подпрограмма: Windows, real (реальный режим DOS), protected (защищенный режим DOS). После слова Remarks следуют заметки, содержащие необходимые детали использования. В разделе See Also приведены имена подпрограмм, связанных с данной по смыслу или по совместному применению. Если перемещать курсор по этим именам (они выделяются курсорной рамкой), то выбрав одно из них (нажать клавишу <Enter>), можно получить справку по следующей функции. Каждая процедура и функция сопровождается примером применения, переключение к которому дает последняя строка программы. Любой текст из Help может быть скопирован в редактируемый файл обычными приемами копирования через буфер. Копирование примеров или заголовков функций облегчает работу.

Существует другой способ получения помощи по процедурам и функциям. Для этого нужно использовать пункт меню Help/Reserved words (зарезервированные слова) или Help/Standard units (стандартные модули).

Задание. Рассмотрите список процедур и функций, выберите какие-либо и просмотрите предлагаемую информацию.

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

Существует два способа объединения программ и подпрограмм:

  1. Текст подпрограмм может быть приведен в разделе описания использующей их программы.

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

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

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

  • подпрограмма начинается с заголовка, содержащего имя подпрограммы, передаваемые в нее и возвращаемые от нее периметры, запись заголовка подпрограммы отличается от заголовка программы;

  • подпрограмма кончается не точкой, а точкой с запятой.

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

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

Например, вызов функции

M:= MIN (X, Y)

вернет в основную программу значение наименьшего из двух чисел и это значение будет присвоено переменной M.

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

Определение. Глобальными называются переменные, объявленные в основной программе и доступные как программе, так и всем ее подпрограммам.

Определение. Локальными называются переменные, объявленные внутри подпрограммы и доступные только ей самой.

Обмен информацией между основной программой и подпрограммой может осуществляться только с помощью глобальных переменных.

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

Если говорить о плюсах использования в программировании подпрограмм, то можно назвать следующие:

  1. Программы с использованием подпрограмм позволяют реализовать один из самых прогрессивных методов программирования - структурное программирование.

  2. Программа становится более читаемой.

  3. Экономия памяти, которая получается из-за того, что память для хранения переменных, используемых в подпрограммах, выделяется только на время работы подпрограммы.

В языке Паскаль выделяют два вида подпрограмм: процедуры (Procedure) и функции (Function). Любая программа может содержать несколько процедур и функций. Структура любой подпрограммы аналогична структуре всей программы. Подпрограмма должна быть описана до того, как будет использована в программе или другой подпрограмме.

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

Тогда общая структура программы выглядит так:

Рrogram hh;    Label; {описание меток}   Const; {описание констант}   Type; {описание типов}   Var; {описание переменных}   Procedure; {описание процедур}   Function; {описание функций} Begin   . . .   . . . end.

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

Обращение к подпрограмме - переход к выполнению подпрограммы с заданием информации, необходимой для ее выполнения и возврата.

Подпрограмма вызывается по своему имени с указанием необходимых параметров.

На этом занятии рассмотрим примеры организации наиболее простого вызова подпрограмм.

Задание. Рассмотрите решение предложенных задач, наберите на компьютере, проверьте работоспособность, внесите свои изменения и дополните своими комментариями.

Задача 1. Написать программу, состоящую из трех подпрограмм и основной программы. Подпрограммы должны организовывать ввод чисел, вычисление их суммы и вывод результата.

Program AkulovE; Uses   Crt; Var   x, y : LongInt; Procedure Input; Begin   TextColor(12);   writeln('По вызову активизировалась процедура "Input"',#10);   TextColor(7);   writeln('Введите два числа через пробел - ');   readln(x, y); End; {  - - - - - - - - - - - - - - - - - - - -} Procedure Summa; Begin   TextColor(14);   writeln('Для сложения подключилась процедура "Summa"',#10);   x:=x+y; End; {  - - - - - - - - - - - - - - - - - - - -} Procedure Output; Begin   TextColor(10);   writeln('Заключительная часть. Процедура "Output"',#10,#13);   TextColor(7);   writeln('Их сумма - ',x); End; {  - - - - - - - - - - - - - - - - - - - -} Begin   ClrScr;   Input;   Summa;   Output;   readln; End.

Задача 2. Найти среднее арифметическое двух чисел.

Program Fadeev; Uses   Crt; Var   A, B : integer;   Rez :real; {  - - - - - - - - - - - - - - - - - - - -} Function SredArif(A, B:integer):real; Begin   SredArif:=(A+B)/2; End; {  - - - - - - - - - - - - - - - - - - - -} Begin   ClrScr;   write('Введите два числа ');   readln(A,B);   Rez:=SredArif(A,B);   write('Cреднее арифметическое этих чисел равно ',Rez:5:3);   readln; End.

Формальные и фактические параметры. Вызов по ссылке и по значению. Локальные и глобальные переменные и подпрограммы

Формальные и фактические параметры

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

Все формальные параметры можно разбить на четыре категории:

  • параметры значения (эти параметры в основной программе подпрограммой не меняются );

  • параметры - переменные ( эти параметры подпрограмма может изменить в основной программе );

  • параметры-константы ( используются только в версии 7.0);

  • параметры-процедуры и параметры-функции (т.е. процедурного типа).

Для каждого формального параметра следует указать имя и, как правило, тип, а в случае параметра-переменной или параметра-константы - его категорию. Имена параметров могут быть любыми, в том числе и совпадать с именами объектов программы. Необходимо лишь помнить, что в этом случае параметр основной программы с таким именем становится недостурным для непосредственного использования подпрограммой. Тип формального параметра может быть практически любым, однако в заголовке подпрограммы нельзя вводить новый тип. Например, нельзя писать

  function Max( A: array[ 1..100 ] of real ): real;

Чтобы правильно записать этот заголовок, следует в основной программе ввести тип-массив, а затем использовать его в заголовке:

  type tArr =array [ 1..100 ] of real;   function Max ( A: tArr ) : real;

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

Вызов по ссылке и по значению

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

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

Приведем примеры:

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

Procedure SetDate (Year, Month, Day : Word);

имеет три передаваемых в подпрограмму величины. Ее вызов в основной программе может иметь различные формы:

  • SetDate (MyYear, MyMonth, MyDay); где MyYear, MyMonth, MyDay - переменные типа Word, которые описаны в основной программе и должны иметь при обращении к процедуре определенные значения. При вызове процедуры эти значения присваиваются внутренним переменным процедуры Year, Month, Day.

  • SetDate (MyYear+1, MyMonth div 2, MyDay); при вызове процедуры используются арифметические выражения, которые вычисляются при вызове. В подпрограмму поступает результат вычислений.

  • SetDate (1999, 1, 31); где в подпрограмму передаются значения констант.

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

Приведем пример.

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

  Procedure GetDate (Var Year, Month, Day : Word);

Она имеет три переменные, передаваемые по ссылке. Если мы аналогично предыдущему случаю, вызовем эту процедуру из основной программы командой

  Procedure GetDate (MyYear, MyMonth, MyDay);

процедура разместит свои переменные Year, Month, Day в тех же ячейках памяти, что и переменные основной программы MyYear, MyMonth, MyDay. После завершения подпрограммы эти переменные сохраняют полученные в процедуре значения.

В 7 версии Borland Pascal предусмотрен новый механизм передачи в подпрограмму параметров по значению. Этот механизм используется, если значение параметра не должно изменяться - это параметры-константы.

Объявление параметра-константы в заголовке подпрограмм имеет вид

  const <имя константы>:<тип константы>

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

  • константа может быть задана в явном виде;

  • может быть указана переменная или выражение совместимого с константой типа.

Например, Procedure Primer (Const x : byte).

Внимание! При вызове процедур необходимо следить за соответствием типов данных в вызывающей программе и подпрограмме.

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

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

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

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

Пример.

  procedure Inp ( Max, Min: real ; N: Word );   function Mult (X, Y: integer): real;

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

  Inp(Abs (Z), - Abs (T), 2 * K);   M:=Mult(X + Y, X - Y);   MA:=MAX( B, 5 );

Локальные и глобальные переменные и подпрограммы.

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

Рассмотрим две почти одинаковые программы.

Program Variant1;     Var   X : real; Procedure writeX; Var   x : real; Begin   write(x) End; Begin   X := Pi;;   writeX End.

Program Variant2; Var   X : real; Procedure writeX; Begin   write(x) End; Begin   X := Pi;   writeX End.

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

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

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

Возникает вопрос, какова роль локальных переменных, нельзя ли все переменные описать как глобальные?

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

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

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

Задание. Найдите в приведенных выше примерах локальные и глобальные переменные, формальные и фактические параметры, какие параметры переданы по ссылке, а какие - по значению.

Процедуры

Структура процедуры имеет следующий вид:

Procedure <имя процедуры>(формальные параметры : их тип); Var   (локальные переменные) begin   . . . end;

Процедура вызывается по имени:

  <имя процедуры> (фактические параметры);

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

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

Заголовок процедуры может выглядеть так:

  PROCEDURE GG(a,b,c:integer); вызываться так: GG(3,n,m)

Здесь a,b,c-формальные параметры, а 3, n, m-фактические параметры

Таким образом в процедуру передаются значения: a=3, b=n, c=m

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

Например:

Procedure express(a,b,c : real; var x,y:real); Var   z : real; begin   z:=a+ b+ c;   x:=sqr(z);   y:=sqrt(z); end ;

Эту процедуру можно вызвать следующим образом:

  express(7.6, 6.8, 9.5, x1, x2);

Формальные входные параметры a, b, c принимают значения соответствующих фактических параметров a=7.6; b=6.8; c=9.5.

При этих значениях выполняется процедура. Результатом выполнения процедуры являются x, y, которые передают свои значения соответствующим фактическим параметрам x1, y1. Таким образом в основной программе будем иметь x1=20, y1=22.

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

Рассмотрите примеры решения задач.

Задача 1. Описать пpоцедуpу "аналитического" сложения обыкновенных дpобей, вычисляющую по числам P1,Q1,P2,Q2, являющимися числителями и знаменателями дробей и последняя дpобь несокpатима. Результат вывести в виде

 P1      P2       P ---- + ----  = ---  Q1     Q2      Q

Program Kudashev_Artem; Uses   Crt; Var   P1, Q1, P2, Q2, P, Nod_2, Celaya : Longint;   Dop_1, Dop_2 : integer; {  - - - - - - - - - - - - - - - - - - - -} Procedure Nod(A,B : Longint;Var Nod_2 : Longint); Begin   Nod_2:=A*B; End; {  - - - - - - - - - - - - - - - - - - - -} Procedure Vivod_Otveta(Celaya,P1,Q1,P2,Q2,P,Nod_2,X,Y:integer); Var   i : integer; Begin   if P > Nod_2     then       begin         Celaya:=P div Nod_2;         P:=P mod Nod_2;       end     else       begin         Gotoxy(X+1,Y);         write(P1);         Gotoxy(X+10,Y);         write(P2);         if P = 0           then             begin               Gotoxy(X+1,Y+1);               write('---- + ---- = ',Celaya,'');               Gotoxy(X+1,Y+2);               write(Q1);               Gotoxy(X+10,Y+2);               write(Q2);             end           else             begin               for I:=10 downto 2 do                 begin                   if ((P mod I) = 0) and ((Nod_2 mod I) = 0) then                     begin                       P:=P div I;                       Nod_2:=Nod_2 div I;                     end;                 end;               Gotoxy(X+19,Y);               write(P);               Gotoxy(X+1,Y+1);               write('---- + ---- = ',Celaya,' ------');               Gotoxy(X+1,Y+2);               write(Q1);               Gotoxy(X+10,Y+2);               write(Q2);               Gotoxy(X+19,Y+2);               write(Nod_2);             end;       end; End; {  - - - - - - - - - - - - - - - - - - - -} Procedure Podshet(P1, Q1, P2, Q2 : Longint); Begin   Nod(Q1,Q2,Nod_2);   Dop_1:=Nod_2 div Q1;   Dop_2:=Nod_2 div Q2;   P:=(Dop_1*P1)+(Dop_2*P2);     if P > Nod_2       then         begin           Celaya:=P div Nod_2;           P:=P mod Nod_2;         end; End; {  - - - - - - - - - - - - - - - - - - - -} Begin   Clrscr;   Q1:=0;   Q2:=0;   Textcolor(LightCyan);   writeln(' P1 P2 P');   writeln('---- + ---- = ---');   writeln(' Q1 Q2 Q');   writeln;   write('Введите P1 -> ');   readln(P1);   while Q1 = 0 do     begin       write('Введите Q1 -> ');       readln(Q1);       if Q1 = 0         then           writeln('Число Q1 не должно pавнятся 0');     end; write('Введите P2 -> '); readln(P2); while Q2 = 0 do   begin     write('Введите Q2 -> ');     readln(Q2);     if Q2 = 0       then         writeln('Число Q2 не должно pавнятся 0');   end; Podshet(P1,Q1,P2,Q2); Vivod_Otveta(Celaya,P1,Q1,P2,Q2,P,Nod_2,2,10); readkey; End.

Задача 2. Для заданного N составить алгоритм вычисления значения выражения:

  (1*1)          (2*2)          (3*3)             (N*N) --------- * ---------- * --------- *...* --------- (1+(3*3))  (2+(3*3))    (3+(3*3))      (N+(3*3))

Program Kudashev_Artem; Uses   Crt; Var   N, Ch, Zn, Celaya : Longint; {  - - - - - - - - - - - - - - - - - - - -} Procedure Podshet(N : Longint; Var Chislitel, Znamenatel : Longint); Var   A, Z : integer; Begin   Chislitel:=1;   Znamenatel:=1;   for A:=1 to N do     begin       Chislitel:=Chislitel*(A*A);       Znamenatel:=Znamenatel*(9+A);       for Z:=2 to 10 do         begin           if ((Chislitel mod Z) = 0) and ((Znamenatel mod Z) = 0)             then               begin                 Chislitel:=Chislitel div Z;                 Znamenatel:=Znamenatel div Z;               end;         end;     end; End; {  - - - - - - - - - - - - - - - - - - - -} Begin   Clrscr;   TextBackground(Black);   Textcolor(Yellow);   write('Введите N -> ');   read(N);   Podshet(N,Chl,Zn);   Celaya:=Ch div Zn;   Chislitel:=Ch mod Zn;   writeln('Ответ');   writeln(' ',Ch);   writeln('',Celaya,' ---------');   writeln(' ',Zn);   readkey; End.

Задание. Приготовьтесь объяснить решение задач учителю. 

Задачи для самостоятельного решения

  1. Написать программу подсчета суммы М введенных с клавиатуры чисел.

  2. Составить программу поиска большего из трёх чисел, с использованием процедуры поиска большего из двух чисел.

  3. Напишите программу (процедуру), которая будет возвращать значение среднего арифметического двух своих параметров а и b.

  4. Написать процедуру, меняющую значения двух переменных а и b местами.

  5. Используя процедуру обмена значений двух переменных, упорядочьте по возрастанию переменные a, b, c.

  6. Определить длину окружности L и площадь круга S. Радиус окружности задается с клавиатуры. Вычисление S и L оформить в виде процедуры.

  7. Постройте диалоговой алгоритм, позволяющий выводить несколько графиков по выбору в одной системе координат. Для построения графиков используйте подпрограммы.

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

Тема: 

Функции.

Другой вид подпрограммы-функция-оформляется аналогично процедуре. Отличительные особенности функции: она имеет только один результат выполнения (но может иметь несколько входных параметров); результат обозначается именем функции и передаётся в основную программу.

Функция оформляется в следующем виде:

Function <имя функции>(формальные параметры: тип): тип значения функции; Var   . . . Begin   . . . End ;

Вызывается функция по её имени с указанием фактических параметров.

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

Пример. Пусть требуется найти (x!-y!)*d!.

Напомним, что х! представляет собой произведение n чисел натурального ряда : х! = 1*2*3*......*х

Function fac(n:integer): integer; Var   p,i: integer; Begin   p:=1;   for i:=2 to n do     p:=p*i;   fac:=p; End ;

Вызвать можно так: f:=(fac(x)-fac(y))*fac(d).

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

Различие между процедурами и функциями.

Функции - это процедуры особого характера, результатом работы которых является некоторое значение, подобное переменной.

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

Program ProcedureAndFunction; Uses   Crt; Var   a, b, SumNumbers : integer; Procedure Summa1(Var Sum: integer; a, b : integer); Begin   Sum:= a+b; End; {  - - - - - - - - - - - - - - - - - - - -} Function Sum(a, b : integer) : integer; Begin   Sum:= a+b; End; {  - - - - - - - - - - - - - - - - - - - -} Begin   ClrScr;   a := 12;   b := 15;   Summa1(SumNumbers, a, b);   writeln ('С помощью процедуры сумма чисел равна ',SumNumbers);   writeln ('С помощью функции сумма чисел равна ',Sum(a, b)); End.

Вызов процедуры производится по ее имени. Наряду с параметрами-значениями a и b, которые подлежат сложению, в списке параметров присутствует параметр-переменная Sum, который содержит возвращаемое процедурой значение - сумму.

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

Объявление функции

  Function Sum(a, b : integer) : integer;

внешне похоже на объявление переменной Sum типа integer. Тип функции объявляется следом за списком параметров - после закрывающейся скобки этого списка и двоеточия.

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

  SumNumbers:= Sum(a,b);

Если не обращать внимания на наличие списка параметров, то этот оператор выглядит как присвоение переменной SumNumbers значения переменной Sum. Компилятор, кончно же, знает, что Sum - это имя функции (т.к. определение предшествует использованию) и организует вычисления соответствующим образом. Точно так же, как константа или переменная, вызов функций может использоваться в списках параметров оператора write (см. программу), что для процедур невозможно.

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

Итак, из вышесказанного возьмите на заметку следующее.

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

Задачи для самостоятельного решения

  1. Найти сумму цифр числа.

  2. Найти первую цифру числа.

  3. Найти количество делителей числа.

  4. Найти числа из промежутка от А до В, у которых больше всего делителей.

  5. Найти сумму всех делителей числа.

  6. Определить, является ли число совершенным, то есть равно ли оно сумме своих делителей, кроме самого себя.

  7. Определить, является ли число простым.

  8. Среди чисел из интервала от А до В найти все простые.

  9. Составьте программу, проверяющую, является ли число палиндромом (например, число 12421 - палиндром).

  10. Определить, является ли число автоморфным, то есть квадрат этого числа заканчивается этим же числом, например, числа 6 и 25, т.к. их квадратами являются числа 36 и 625.

Решение задач

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

  1. Даны координаты вершин четырехугольника ABСВ. Найти сумму длин его диагоналей. Данные для ввода: A(0,1), B(2,5), C(4,8), D(2,0).

  2. Найти сумму площадей треугольников ABC и МНР, заданных координатами вершин. Данные для ввода: А(0;1), В(3;1), С(4;2), М(6;7), Н(4;3), Р(3;8).

  3. Найти сумму периметров треугольников ABC и МНР, заданных координатами вершин. Данные для ввода: А(0;1), В(3;1), С(4;2), М(6;7), Н(4;3), Р(3;8).

  4. Вычислить 1!+2!+3!+......+N! . Вычисление факториала организовать как функцию fact(var r:integer):longint.

  5. Составить программу поиска большего из трёх чисел, с использованием процедуры поиска большего из двух чисел.

  6. Определить длину окружности С и площадь круга S, удаление L центра окружности от начала координат О. Координаты центра окружности равны X и Y, радиус R. Вычисление С, S, L оформить в виде процедуры.

  7. Составьте функцию для определения значений n!, m!,(n-m)!

  8. Напишите функцию CUBЕ, которая возвращает куб ее числового параметра.

  9. Напишите функцию, которая возвращает объем сферы, радиус которой передается как параметр.

  10. Для заданного х составить алгоритм вычисления значения выражения:

  11. Для заданного х составить алгоритм вычисления значения выражения:

  12. Напишите функцию CUBЕ, которая возвращает куб ее числового параметра.

  13. Составьте программу для определения значений n!, m!,(n-m)!

  14. Вычислить 1!+2!+3!+......+N! . Вычисление факториала организовать как функцию fact (var r:integer) : longint.

  15. Напишите функцию, которая возвращает объем сферы, радиус которой передается как параметр.

  16. По координатам вершин двух треугольников, определите их площадь и выведите на печать площадь максимального треугольника.Вычисление длины стороны, площади треугольника оформите в виде функций.

  17. Дана отрезки а, b, c, d. Для каждой тройки отрезков, из которых можно построить треугольник, напечатайте площадь данного треугольника. Воспользуйтесь функциями определения возможности создания треугольника и вычисления площади.

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

  19. Напишите функцию логического типа, проверяющую, являются ли все цифры, входящие в натуральную запись, числа N различными.

  20. Даны два натуральных числа. Проверить, является ли второе число перевертышем первого.

  21. Составьте программу подсчета числа всех натуральных чисел, меньших М, квадрат суммы цифр которых равен Х.

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

  23. Составьте программу нахождения наименьшего натурального N-значного числа Х (X>=10), равного утроенному произведению своих цифр.

  24. Дано натуральное число. Определите, сколько четных цифр используется в записи этого числа.

  25. Дана последовательность К чисел. Определите, сколько чисел этой последовательности содержит в своей записи все цифры больше некоторого числа n введенного с клавиатуры.

  26. Для последовательности вводимых с клавиатуры чисел, выведите суммы цифр каждого введенного числа. Признак конца ввода - число -1.

Для любознательных

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

Опережающее описание процедуры (директива Forward)

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

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

Возможность создавать "опережающее описание" для процедур позволяет решать проблемы следующего рода: предположим, в некоторой программе Вы используете две процедуры с именами Proc1 и Proc2, причем процедура Proc1 использует вложенную процедуру Proc2, а процедура Proc2 в свою очередь использует процедуру Proc1. Т.к. Вы не можете использовать необъявленную ранее процедуру, то у Вас возникает проблема, связанная с необходимостью развязать "зацикленные" друг на друге процедуры Proc1 и Proc2. Использование директивы Forward при объявлении процедуры Proc1 позволяет решить эту проблему.

Program Primer; . . . {  - - - - - - - - - - - - - - - - - - - -} Procedure Proc1 (список формальных параметров); Forward;{заголовок первой процедуры} Procedure Proc2 (список параметров); {заголовок второй процедуры} Begin{Основной блок процедуры Proc2}   . . .   Proc1 (список фактических параметров); {Вызов процедуры Proc1}   . . . End; {  - - - - - - - - - - - - - - - - - - - -} Procedure Proc1 (список параметров); Begin{Основной блок процедуры Proc1}   . . .   Proc2 (список фактических параметров); {Вызов процедуры Proc2}   . . . End; {  - - - - - - - - - - - - - - - - - - - -} Begin   . . . {Тело основной программы} End.

Процедуры с ближним и дальним адресом вызова

Турбо Паскаль поддерживает две модели вызова процедур - ближнюю Near и дальнюю Far. Между этими двумя моделями существует ряд различий. Процедуры, созданные с использованием модели Near, получаются более быстродействующими, но могут быть вызваны только из модуля, в котором они описаны.

Процедуры, созданные с использованием модели Far, могут быть вызваны из любого места программы. Недостатком этих процедур является их медлительность.

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

Параметры-процедуры и параметры-функции

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

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

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

Процедуры и функции должны быть объявлены с директивой Far (использование дальнего типа вызова подпрограмм) и откомпилированы в состоянии {$F+}. А также они не должны быть:

  • стандартной подпрограммой;

  • вложенной подпрограммой;

  • Inline процедурой или функцией (п/программы, записанные в машинных кодах);

  • Interrupt процедурой или функцией (п/программы обработки прерываний).

При использовании параметров-процедур или параметров-функций в списке перед соответствующими формальными параметрами указывается зарезервированное слово Procedure или Function.

Например,

  Procedure Exampl(k,l : integer; Var M : real; Procedure Prob; Function Step : real);

В списке формальных параметров процедуры Exampl:

k, l - параметры-значения; M - параметр-переменная; Prob - параметр-процедура; Step - параметр-функция.

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

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

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

Program ProcType; Type   Func=Function(x, y : integer) : integer;{Описание процедурного типа} {$F+};{Директива компилятору на использование дальнего типа вызова п/программ} {  - - - - - - - - - - - - - - - - - - - -} Function Add(x, y :integer) : integer; Begin   Add := x+y; End; {  - - - - - - - - - - - - - - - - - - - -} Function Mult(x, y :integer) : integer; Begin   Mult := x+y; End; {  - - - - - - - - - - - - - - - - - - - -} Function Funny(x, y :integer) : integer; Begin   Funny := (x+y)*(x-y); End; {  - - - - - - - - - - - - - - - - - - - -} {$F-}; Procedure Tab(w,h : integer; Operation : Func); Var   x, y : integer; Begin   for y := 1 to w do     begin       for x := 1 to w do         write(Operation(x,y):5);         writeln;     end; End; {  - - - - - - - - - - - - - - - - - - - -} Begin   Tab(10,10,Add);   Tab(10,10,Mult);   Tab(10,10,Funny); End.

В данной программе процедура Tab представляет собой общее действие, выполняемое над параметрами-функциями Add, Mult, Funny. После запуска программы сначала вызывается процедура Tab для фактических параметров 10, 10 и Add, в результате чего формальным параметрам х и y присваиваются значения чисел 10 и 10, а формальному параметру Operation процедурного типа Func присваивается имя фактической функции Add. В результате этого на экран будет выведена таблица сложения от 1 до 10. Затем процедура Tab вызывается к исполнению для фактических параметров 10, 10 и параметра-функции Mult, в результате этого на экран будет выведена таблица умножения от 1 до 10. Аналогично вызов процедуры Tab с параметрами 10, 10 и Funny даст в результате на экране таблицу произведения суммы на разность чисел от1 до 10.

Задание. Введите текст этой программы, запишите полученный файл на диск и откомпилируйте его. после того как компиляция выполнится успешно, исполните программу в пошаговом режиме с заходом в процедуры и пронаблюдайте за вызовом функций вычисления суммы, произведения двух чисел или произведения их суммы и разности. Обратите внимание на исполнение оператора write(Operation(x,y):5), как в зависимости от фактического значения параметра-функции Operation процедурного типа Func осуществляется вызов различных функций Add, Mult или Funny. Попробуйте удалить строку с директивой компилятору об использовании дальнего типа вызова или возьмите в фигурные скобки описание процедурного типа Func и пронаблюдайте за результатом. В случае появления ошибок нажатием клавиши F1 получите справку о причинах ошибки и рекомендацию на коррекцию.

Модули, созданные программистом.

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

Таким образом мы подошли к понятию модуля Unit. До сих пор Вы имели дело с встроенными модулями. Теперь Вы научитесь подключать к программе библиотеки, которые были созданы Вами.

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

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

Модуль модно разделить на несколько разделов: заголовок, интерфейсная часть, реализационная часть, инициализационная часть.

Заголовок модуля

 Unit <Имя модуля>;   {$N+} <Глобальные директивы компилятора>;

Интерфейсная часть

Interface

Uses<список подключаемых модулей>; Const<описания констант, определенных в данном модуле и доступных для других модулей>; Type<описания типов, определенных в данном модуле и доступных для других модулей>; Var<описания переменных, определенных в данном модуле и доступных для других модулей>; Procedure<Заголовки процедур, определенных в данном модуле и доступных для других модулей>; Function<Заголовки функций, определенных в данном модуле и доступных для других модулей>;

Реализационная часть

Implementatoin

Uses<список подключаемых модулей>; Const<описания констант, определенных в данном модуле и недоступных для других модулей>; Type<описания типов, определенных в данном модуле и недоступных для других модулей>; Var<описания переменных, определенных в данном модуле и недоступных для других модулей>; Procedure<реализация процедур, определенных в данном модуле и доступных для других модулей>; Function<реализация функций, определенных в данном модуле и доступных для других модулей>; Procedure<реализация процедур, определенных в данном модуле и недоступных для других модулей>; Function<реализация функций, определенных в данном модуле и недоступных для других модулей>;

Инициализационная часть

Begin<Слово Begin необходимо, если имеются операторы в следующей части программы>   <часть модуля, исполняемая при его подключении (необязательна)> End.

Заголовок модуля

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

При выборе имени модуля необходимо учитывать одну особенность: имя модуля должно совпадать с именем файла, в котором он хранится, а значит имя модуля не может состоять более чем из 8 символов. А также не забывайте, что имя не должно совпадать с именами объектов (процедур, функций и др.).

Интерфейсная часть

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

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

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

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

Примечание. Интерфейсная часть может быть пуста.

Реализационная часть

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

Реализационная часть также может быть пустой.

Инициализационная часть

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

Примечание. Создание собственного модуля не является обязательным для учащегося.

Тема: 

Примеры решения задач.

  1. Вывести все совершенные числа в данном диапазоне.

programsov1;

{

Задача. Вывести все совершенные числа в данном диапазоне.

}

var

a, b, i, j, s: longint;

begin

write('Введите диапазон для вывода совершенных чисел: ');

readln(a,b);

writeln('Совершенные числа в данном диапазоне:');

for i := a to b do

begin

s := 0;

for j := 1 to i - 1 do

if i mod j = 0 then

s := s + j;

if s = i then

writeln(i);

end;

readln;

end.