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

Иванова Г.С. - Основы программирования

.pdf
Скачиваний:
2769
Добавлен:
02.04.2015
Размер:
13.53 Mб
Скачать

4. Структурные типы данных

case

 

 

Тип

h©i

 

 

 

 

переменной

 

 

 

 

 

Идентификатор]

 

 

 

 

переменной \<У

О

 

Значение

hGKDH

О

Тип

Идентификатор

константы

 

поля

 

поля

О

Рис. 4.37. Синтаксическая диаграмма <Вариантная часть записи>

Var М: record

case {вариантная часть}

byte of {тип констант для идентификации вариантов}

0:(by: array [0..3J of byte); {массив из 4 байт}

1:(wo: array [O..IJ of word); {массив из 2 слов}

2:(lo: longint); {переменная длиной 4 байта} end;...

с предварительным объявлением типа:

Туре

Figure = (Square, Triangle, Circle); {перечисляемый тип}

Paramf^" record

 

{тип ~ запись с вариантами}

X,Y: real;

{фиксированные поля}

case

 

{вариантная часть}

Fig:Figure

of { переменная и тип

Square:

 

идентифицирующих констант}

(Side: real);

Triangle:

(Sidel,Side2,Side3: real);

Circle:

(Radius: real);

end;

 

 

Var Param: Paramf; {объявление переменной}

Конкретное значение переменной типа «запись с вариантами» присваи­ вается точно так же, как и обычной записи: вводом с клавиатуры, с помощью литеральной константы и с помощью типизированной константы. Однако при объявлении инициализированной переменной для вариантной части за­ дается только один вариант.

141

Часть ]. Основы алгоритмизации и процедурное программирование

Например, пусть запись должна содержать либо данные о человеке, ли­ бо о корабле (так, Георгий Седов - это и имя человека, и название корабля). Для этого опишем следующую запись с вариантами

Туре

Forma = record {запись места прописки человека и корабля} case {вариантная часть}

boolean of {тип констант, идентифицирующих варианты}

{вариант для человека}

 

True: (Birthplace: string[40];

{место проживания}

{вариант для корабля}

 

False: (Country: stringf20J;

{страна}

EntryPort: string[20];

{порт}

EntryDate: array[L.3]

of word; {дата}

Count: word) {водоизмещение}

end;.,.

Типизированные константы для задания исходных данных двух записей: Object2 - сведения о человеке. Object 1 - сведения о корабле определяются так:

Const ObjectJ: Forma = (Country: 'Польша*;

EntryPort: 'Ленинград';

EntryDate: (16,3,89);

Count: 12);

Object2: Forma = (BirthPlace: 'Москва');...

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

Кроме того, при использовании записей с вариантами необходимо учи­ тывать некоторые особенности. Так, для размещения переменной типа за­ пись всегда отводится фиксированный объем памяти в соответствии с объе­ мом, занимаемым самым большим из вариантов, т. е. различные варианты размещаются на одном участке памяти, как бы «накладываясь» друг на дру­ га.

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

142

4. Структурные типы данных

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

Туре

Регет= record {запись с вариантами} case byte of

0:Wo:word; {переменная типа word}

1:Lodongint; {переменная типа longint}

2:Re:real; {переменная типа real}

end; Var OPerem;

Begin...

C.Lo:=0; {очищаем область}

C.Wo:=10; {в вариантное поле по шаблону целого без знака запи­ сываем число 10}

WriteLn(C.Lo:10);... {печатается содержимое вариантного поля по шаблону длинного целого}

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

Задания для самопроверки

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

Задание 2. Разработайте программу, которая формирует массив записей о сту­ дентах некоторой группы, содержащий следующую информацию: фамилию, оценки за последнюю сессию по четырем предметам и размер стипендии. Фамилию и от­ метки программа должна вводить с клавиатуры, а размер стипендии считать исходя из оценок: все «5» - повышенная (+ 25%), есть одна «4» - повышенная (+10%), нет троек - обычная стипендия, есть одна тройка - социальная стипендия (-15%), боль­ ше одной тройки - стипендия 0. После чего программа должна сортировать массив по размеру стипендии и выводить его на экран. Предусмотреть ввод размера обыч­ ной стипендии с клавиатуры.

143

5. МОДУЛЬНОЕ ПРОГРАММИРОВАНИЕ

Большие программы обычно разрабатывают и отлаживают по частям. Целесообраз­ но при.этом, чтобы каждая такая часть, называемая подпрограммой, была оформлена так, чтобы ее можно было использовать при решении аналогичной подзадачи в той же программе или даже при решении других задач. В Borland Pascal реализованы два типа подпрограмм: процедуры и функции.

5.1. Процедуры и функции

Процедуры и функции представляют собой относительно самостоятель­ ные фрагменты программы, соответствующим образом оформленные и снабженные именем (программные блоки). По правилам Borland Pascal про­ граммные блоки - такие же ресурсы, как типы и переменные. Соответствен­ но, они также должны быть описаны перед использованием в разделе описа­ ний программного блока, который их использует (основной программы или вызывающей подпрограммы). Каждый блок имеет такую же структуру, как основная программа, т.е. включает заголовок, раздел описаний и раздел опе­ раторов, но заканчивается не точкой, а точкой с запятой (рис. 5.1).

Заголовок блока определяет форму вызова подпрограммы. В разделе описаний блока объявляют внутренние локальные ресурсы блока (перемен­ ные, типы, внутренние подпрограммы). Раздел операторов содержит инст­ рукции подпрограммы в операторных скобках begin...end.

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

Заголовок

Раздел

• — — >

Раздел

блока

описаний

 

операторов

Рис. 5.1. Синтаксическая диаграмма конструкции <Программный блок>

144

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

- ^ procedure V Идентификатор

Список

параметров

,<7>

]•

- ^ function V Идентификатор

—I I \1^

[результата! \ ^ ^

Список

параметров

Рис. 5.2. Синтаксические диаграммы конструкций <ЗаголоБок процедуры> {а) и <Заголовок функции> (б)

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

Из основной программы данные могут быть получены:

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

явно - через параметры.

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

В свою очередь локальные ресурсы, объявленные в разделе описаний подпрограммы, из программного блока, в разделе описания которого она оп­ ределена, не доступны. В том случае, если в подпрограмме объявляется ре­ сурс, имя которого совпадает с именем глобального ресурса, соответствую­ щий глобальный ресурс в подпрограмме становится не доступным, «пере­ крывается».

Например, на рис. 5.3 в разделе описаний основной программы объявле­ на подпрограмма А, в разделе описаний которой объявлена подпрограмма В. Переменная х доступна в обеих подпрограммах, так как она не перекрывает­ ся. Переменная z основной программы в подпрограмме А не доступна, так как эта подпрограмма перекрывает глобальную переменную z локальной. В подпрограмме В используется значение z, определенное в подпрограмме А.

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

145

Часть 1. Основы алгоритмизации и процедурное программирование

Program ex;

Var xrreal; z:real;

-----t":

Procedui^ A; Var z:integer;

PrdeodurfesB;

Var irtfitegerK^

Begin i:=z; x:=5;

End;

B^gin \

-round(x);

End;

Begin

End.

Рис. 5.3. Перекрытие ресурсов в подпрограммах

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

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

var

о

 

Идентификатор U | O L J

ТИП

L / 7 V

'-*/ const V

О

11 V у

I параметра [ Т у ^

 

 

О

 

 

Рис. 5.4. Синтаксическая диаграмма конструкции <Список параметров>

146

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

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

В Borland Pascal параметры в подпрограмму могут передаваться тремя способами:

как значения - в подпрограмму передаются копии значений парамет­ ров, и никакие изменения этих копий не возвращаются в вызывающую про­ грамму;

как переменные - в подпрограмму передаются адреса фактических па­ раметров, соответственно все изменения этих параметров в подпрограмме на самом деле происходят с переменными, переданными в качестве фактичес­ ких параметров; такие параметры при описании помечаются служебным словом var; в качестве фактических значений параметров-переменных нель зя использовать литералы\

как неизменяемые переменные (именованные константы) - в подпро­ грамму, так же как и в предыдущем случае, передаются адреса фактических параметров, но при попытке изменить значение параметра компилятор выда­ ет сообщение об ошибке; такие параметры при описании помечаются слу­ жебным словом const.

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

<переменная>:=<имя функции>(<фактические параметры>).

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

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

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

147

Часть 1. Основы алгоритмизации и процедурное программирование

С

Начало

J

С Stf(x,y,z)

J

С

Начало

j

Г81р(х,у,г,5П

 

i

.

.

'

.

 

I

.

.

I

.

/

Ввод

 

p:=(x+y+z)/2

 

Ввод

 

 

p:=(x+y+z)/2

 

 

a,b,c,d,e

 

 

a,b,c,d,e

 

 

 

 

 

 

I

Z

 

 

 

 

 

/

Вывод

 

 

 

Stp

 

 

s=v:.

 

 

 

stMT..

 

 

 

 

 

Strf(.)+Stf(,

 

 

 

 

(a,b,e,SI)

 

 

 

{

п

j

i

 

 

 

Stp

 

 

 

 

Конец

Return

j

 

 

(

Return

j

 

 

 

 

 

 

 

(c,d,e,S2)

 

 

 

 

 

 

 

 

 

 

 

Вывод

 

 

 

 

 

 

 

 

 

 

 

SHS2

 

 

 

 

 

 

 

 

 

 

f

Конец

j

 

 

 

Рис. 5.5. Схемы алгоритмов программы определения площади четырехугольника с использованием функции {а) и процедуры (б)

Пример 5.1. Разработать программу, которая определяет плоидадь четы­ рехугольника по заданным длинам сторон и диагонали.

Будем считать площадь четырехугольника как сумму площадей двух треугольников, определенных по формуле Герона. Вычисление площади тре­ угольника оформим как подпрограмму. Исходные данные такой подпрограм­ мы - длины сторон треугольника. Подпрограмма не должна менять значения параметров, поэтому их можно передать как параметры-значения или пара­ метры-константы. Результат работы этой подпрограммы - скалярное значе­ ние, значит, она может быть реализована как функция. Однако ее также мож­ но реализовать как процедуру, которая возвращает результат через параметрпеременную. Схемы алгоритма данной программы с использованием под­ программ обоих типов приведены на рис. 5.5.

Ниже приведены тексты соответствующих программ.

Вариант с и с п о л ь з о в а н и е м

ф у н к ц и и :

Program

ex;

 

 

Var A,B,C,D,E:real;

{глобальные переменные}

{описание функции}

 

Function

Stf(const X,

Y,Z:real):real;

 

Varp:real;

{локальная

переменная}

begin

 

{раздел операторов функции}

p:=(X^Y+Z)/2;

 

 

Stf:=sqrt(p^(p^X)^(p-Yr(p^Z)):

end;

148

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

{раздел операторов основной программы}

Begin

WriteLnСВведите длины сторон и диагонали'); ReadLn(A,B,C,D,E);

]¥гИе1п('Пло1цадь четырехугольника', Stf(AjB,E)+Stf(CyD,E):7:3); End.

Вариант с и с п о л ь з о в а н и е м

п р о ц е д у р ы :

Program ex;

 

 

Var A,B,C,D,E:real; SJ,S2:real;

{глобальные переменные}

{описание процедуры}

 

Procedure Stp(const X, Y,Z:real;var S:real);

Varp.real;

{локальная переменная}

begin

{раздел операторов процедуры }

p:=(X+Y+Z)/2;

 

 

S: =sqrt(p *(p'X) Y;?- Y) *(p-Z)); end;

{раздел операторов основной программы}

Begin

WriteLnCВведите длины сторон и диагонали); ReadLn{A,B,C,D,E);

Stp(A,B,E,Sl); {вызов процедуры} Stp(CyD,E,S2); {вызов процедуры}

ЖгИеЬпСПлогцадь четырехугольника \S1+S2;7:3); End

Использование параметров структурных типов, таких, как массивы, строки (кроме типа string), множества, записи, файлы, имеет одну общую особенность: тип таких параметров должен быть предварительно объявлен в инструкции описания типа type.

Например:

Туре mas^arrayfl.JOJ о/real; str80=stringf80J;

procedure А (M:mas; fout:str80);...

Пример 5.2. Разработать подпрограмму суммирования элементов мас­ сива размерности п, п < 10.

Поскольку результат - скалярное значение, то будем использовать под­ программу-функцию. Описание типа «массив из 10 целых чисел» должно быть выполнено отдельно в разделе описаний. Новый тип mas затем исполь-

149

Часть I. Основы алгоритмизации и процедурное программирование

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

Program ex;

 

 

Type mas-arrayll.AO]

of integer; {тип «массив из 10 целых чисел»}

Var aimas;

 

 

i,n:integer;

 

 

Function sum(b:mas; n:integer).'integer;

Var s:integer;

i:integer;

Begin s:=0;

to n do

 

for i:=I

s:=s+b[ij;

sum:=s;

 

 

End;

Begin ReadLn(n);

for i:=l to n do Read(a[i]); ReadLn;

WriteLn(VyMMa= \sum(a,n));

End

5.2. Практикум. Выделение подпрограмм методом пошаговой детализации

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

Пример 5.3. Разработать программу исследования элементарных функ­ ций, которая для функций у = sin х, у = cos х, у = tg х, у = In х, у = е^ выпол­ няет следующие действия:

строит таблицу значений функции на заданном отрезке с заданным

шагом;

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

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

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

Меню функций (рис. 5.6, а) должно выводиться на экран при запуске программы. После ввода номера функции на экране должно появиться меню операций (рис. 5.6, б). Введя номер операции, пользователь должен увидеть на экране запрос на ввод данных, необходимых для выполнения этой опера­ ции (рис. 5.6, в'д). Задав данные, пользователь должен получить на экране

150