1 Лекция 8 8.0. Подпрограммы 8.1. Основные понятия Подпрограмма – логически законченная часть программы, которую по имени можно вызывать в разные места программы неограниченное число раз. Она решает часть общей задачи. У нее есть имя, которое используется при вызове подпрограммы в основную программу. Подпрограммы бывают 2 видов: – процедуры и – функции. Процедура не возвращает значений (например, рисует) или возвращает несколько значений (корни квадратного уравнения). Функция возвращает одно значение. Программа без структурных элементов называется монолитной. Минимальный элемент такой программы - оператор. Она сложна в разработке, отладке и сопровождении. Структурированная программа называется модульной. Она содержит более крупные компоненты - подпрограммы. Модульная программа проще создается, более понятна. Модульная программа может иметь иерархическую структуру. Работа с подпрограммой включает 2 этапа: - описание подпрограммы; - вызов подпрограммы. Преимущества подпрограммы: 1. в программе нет дублирования кода; 2. повышается надежность программы; 3. улучшается «читаемость» программы; 4. облегчается процесс отладки. Различают подпрограммы: – без параметров, – с параметрами. 8.2. Процедурный тип Процедурный тип расширяет традиционное понятие подпрограмм, позволяя обращаться с подпрограммами как с переменными. Используется в программировании, где структура программы отражает структуру решаемой задачи. В результате алгоритм решения ясно виден из исходного текста. Процедурный тип это внешние данные, используемые подпрограммой. Процедурный тип объявляется следующим образом: type <имя1> = procedure; <имя2> = procedure(<список параметр.>); <имя3> = function (список параметров) : <тип результата>; Этот тип определяет процедуру без параметров, процедуру с параметрами или функцию. Например: type Proc1 = Procedure; // Тип – процедура без параметров Proc2 = Procedure(x,y : real); //Тип – процедура с параметрами 2 Func1 = Function(x,y : real): real; //Тип – функция 8.3. Сравнение вариантов Рассмотрим 2 варианта решения одной и той же задачи: вывод текстовых блоков с вставкой стандартного разделителя из трех строк из набора символов “ * ” в конце. 1 –й вариант (Монолитная программа) program Example1; {$APPTYPE CONSOLE} uses SysUtils; var i, j : integer; begin Writeln('Text 1'); // Вывод 1 текста for j :=1 To 3 Do begin // Вывод строки из 20 символов “ * ” for i :=1 To 20 Do write( ' * ' ); writeln; end; Writeln('Text 2'); //Вывод 2 текста for j :=1 To 3 Do begin // Вывод строки из 20 символов “ * ” for i :=1 To 20 Do write( ' * ' ); writeln; end; readln end. Начало 2 – й вариант (Модульная программа) program Example2; {$APPTYPE CONSOLE} uses SysUtils; Procedure DrawStr; // Процедура “Рисовать строки” var i, j : integer; begin for j :=1 To 3 Do begin // Вывод строки из 20 символов “*” for i :=1 To 20 Do write( ' * ' ); writeln; // Перейти к следующей строке end; end; begin //основная программа Writeln( ' Text 1 ' ); // Вывод 1 текста DrawStr; // Вывод строк разделителя Writeln( ' Text 2 ' ); // Вывод 2 текста DrawStr; // Вывод строк разделителя readln 1 Объявление процедуры DrawStr 2 3 4 j=1..3, 1 i=1..20, 1 Вывод ' * ' Конец Начало 1 Вывод Текст1 2 п/п DrawStr 3 Вывод Текст2 4 п/п DrawStr Конец 3 end. 8.4. Аргументы и параметры Параметры - данные, с которыми работает подпрограмма. Это внутренние данные для подпрограммы и перечисляются в ее заголовке с указанием типов. Они связаны с аргументами. Аргументы - данные, передаваемые в подпрограмму или возвращаемые из нее. Это внешние для подпрограммы данные, с которыми имеет дело вызывающая часть программы. В подпрограмме им соответствуют параметры. Указываются в списке аргументов при обращении к подпрограмме и являются фактическими параметрами. Синонимы: Параметры = формальные параметры, Аргументы = фактические параметры. -----------------------------------------------------Для аргументов и параметров надо соблюдать: - одинаковое количество (An=Pn) , - одинаковый порядок следования (A1-P1, A2-P2..) - совместимость типов. Все формальные параметры разделяются на 4 категории: – параметры-значения – в списке параметров указывается их тип, например (x,y : real); передаются через стек в виде копий и остаются неизменными в подпрограмме; – параметры-константы – в списке параметров снабжаются служебным словом (const s : real); передаются подпрограмме в виде копий с помощью адресов, изменяться подпрограммой не могут; – параметры-переменные – в списке параметров снабжаются служебным словом (x,y:byte; var ss : real); инструкции подпрограммы могут изменить значение переменной, являющейся фактическим параметром; – параметры процедурного типа – в списке задаются именами и являются параметрами-значениями. 8.5. Области действия имен Структура подпрограммы идентична структуре программы. Имена, объявленные в главной программе являются глобальными. Они доступны во всех внутренних точках, в том числе и в подпрограммах. Имена, объявленные в подпрограмме являются локальными. Они доступны во всех внутренних точках подпрограммы. Локальное имя во внешней программе недоступно. Память под них выделяется автоматически в момент вызова подпрограммы. Если используются одинаковые локальное и глобальное имя, то внутри процедуры локальное имя блокирует глобальное. Формат доступа к глобальному имени: <имя программы>.<глобальное имя> //имя составное 4 Чтобы получить доступ к такому глобальному имени в подпрограмме его надо указывать составным. 8.6. Функция Объявление функции в общем виде Function <Имя> (p1,p2:T1;...):T; // Заголовок функции: Имя функции var //объявление локальных переменных - параметров begin -----------// тело функции Имя :=<выражение>; //или Result := <выражение>; //глобальное имя -----------end; -------------------------------------------------------Имя - имя функции (имя существительное) используется для ее вызова, T - тип возвращаемого функцией результата. p1, p2 - имена формальных параметров, значение которых используются для вычисления значения функции. Объявляется в заголовке функции. Конкретные значения параметры получают во время работы программы в результате вызова функции из основной программы. T1 - их тип. Обращение при обычном синтаксисе. Форма вызова функции: program Example3; {$APPTYPE CONSOLE} uses SysUtils; var // Объявление аргументов. a1: integer; a2,a3: real; Function MyFunc(p1: integer; p2: real): real; //Заголовок функции // Разделы локальных определений begin //Тело функции MyFunc:=<выражение>; ... end; begin //Основная программа ............... a3:=3+MyFunc(a1,a2); //Вызов функции по имени в выражении ............... end. ----------------------------------------------------Соответствия: p1 - a1, p2 - a2 5 Задача1 . Написать функцию, проверяющую, является ли целое число, введенное с клавиатуры четным. Программа должна использовать эту функцию, проверять является ли число четным или нет, и выводить соответствующее сообщение. Начало program Example4; {$APPTYPE CONSOLE} 1 Объявление функции Сhet нет да 2 n mod 2=0 ? uses SysUtils; var m: integer; //вводимое с клавиатуры число function Chet(n:integer): boolean; //Заголовок функции begin //Тело функции Chet if n mod 2 = 0 then Chet:=True else Chet:=False; end; begin // Основная программа repeat read(m); // Проверка условия на четность числа m // с помощью функции Chet if chet(m) then writeln(m,' - chetnoe chislo') else writeln(m,' - nechetnoe chislo'); until m=0; readln end. 3 4 Сhet=False Сhet=True Конец Начало 1 Ввод числа m да 2 Chet(m) ? 4 m - нечетное 3 m - четное нет 5 нет m=0 да Конец 8.7. Процедуры Объявление процедуры в общем виде Procedure <Имя>( p1, p2 : T1; ... // Параметр-значение var p3, p4 : T2; ... // Параметр-переменная const p5, p6 : T3; ...); //Параметр-константа var //объявление локальных переменных - параметров begin //тело процедуры end; -------------------------------------------------------- Имя - имя процедуры (глагол) подпрограмму-, используется для ее вызова var - признак параметров-переменных, const -признак параметров констант; 6 p1, p2, p3, p4, p5, p6 - имена параметров, T1, T2, T3 - их типы. Обращение. Форма вызова процедуры: program Example5; {$APPTYPE CONSOLE} uses SysUtils; var // Объявление аргументов a1: integer; a2 : real; {..........…..} Procedure MyProc( var p1: integer; p2 : real); //Разделы локальных определений begin //Тело подпрограммы end; begin // Основная программа {...............} MyProc(a1, a2); //Вызов процедуры по имени в строке кода {...............} end. ---------------------------------------------------------- Начало Соответствия: p1 - a1, p2 - a2 Задача2. Вывести таблицу квадратных корней. Для оформления таблицы использовать процедуру Line. program Example6; {$APPTYPE CONSOLE} uses SysUtils; var i:integer; Procedure Line(n:integer; c:char); var k:integer; begin for k:=1 to n do write(c); writeln; end; begin writeln('Tabl kvadratnyx korney'); Line(15,'='); writeln('Chislo | Koren'); Line(15,'='); for i:=1 to 5 do begin writeln(i:5,' ',sqrt(i):6:2); Line(15, '-'); end; 1 Объявление процедуры Line Line 2 k=1..n, 1 3 Вывод символа Конец Начало 1 Вывод Заголовка 2 п/п Line 3 Вывод шапки табл. 4 5 46 п/п Line k=1..n, 1 Вывод c 7 п/п Line Конец 7 readln end. 8.8. Процедура или функция? Процедура и функция два способа оформления подпрограммы. Одну и ту же подпрограмму можно оформить как процедуру или как функцию. Пример вычисления сопротивления цепи (Sopr), состоящей из трех параллельных сопротивлений (R1, R2, R3). Procedure SoprPar(r1, r2, r3:real; var sr:real); begin sr := (r1+r2+r3)/(r1*r2*r3); end; Function SoprPar(r1, r2, r3:real; var sr:real):real; var sr : real; begin sr := (r1+r2+r3)/(r1*r2*r3); SoprPar:=sr; end; Оформление подпрограммы в виде функции более предпочтительно, т.к. целью вычисления является получение одного значения. Правило: Если подпрограмма должна изменить значение только одной переменной основной программы, то ее следует оформить как функцию, в остальных случаях подпрограмму следует оформить как процедуру. 9. Модули Модуль – повторное использование функций и процедур. Создание модуля: Командой File => New => Unit (Файл => Новый => Модуль) в редактор кода проекта добавляется страничка с заготовкой модуля, которая затем заполняется кодом: unit MayUnit; interface implementation ... end. Шаблон модуля: // имя модуля изменяется после его сохранения //описательная часть // реализация // код модуля Использование модуля MayUnit : Добавить этот модуль по имени к проекту в список модулей. program Blank; {$APPTYPE CONSOLE} uses SysUtils, MayUnit; var ... begin 8 ... end. //код проекта Работа с модулем: 1. Создать консольное приложение командой Файл => Новый => Другое => Console Application. 2. Cохранить проект в папке KR командой Файл => Сохранить проект как…=> Blank. 3. Создать модуль для преобразования кодов символов из одной кодировки в другую. Для этого выполнить команду Файл => Новый => Модуль. В редакторе кода проекта возникает дополнительная страничка с заготовкой модуля. Заполнить ее кодом: unit Unit1; //Заголовок модуля, после сохранения имя меняется на другое interface // Раздел описания uses SysUtils; // Ссылка на подключаемые модули function Rus(mes:string):string; // Заголовок функции Rus с переменной mes implementation // Раздел реализации function Rus(mes:string):string; //Преобразует строку Windows под строку MSDOS var i:integer; //Номер обрабатываемого символа begin // Тело функции for i:=1 to length(mes) do case mes[i] of // Оператор выбора 'А'..'п': mes[i] := chr(ord(mes[i])-64); //преобразование символов в коды 'р'..'я' : mes[i] := chr(ord(mes[i])-16); //преобразование символов в коды 'Ё' : mes[i] := chr(ord(mes[i])+72); //преобразование символа в код 'ё' : mes[i] := chr(ord(mes[i])+57); //преобразование символа в код end; result:=mes; //возвращаемый результат в переменную result end; end. 4. Сохранить код модуля командой Файл => Сохранить как…в папке KR под именем RusTrans.pas. Заголовок модуля Unit1 изменится на RusTrans. 5. Выполнить компиляцию модуля RusTrans.pas с помощью команды Проект => Компилировать Blank. В папке проекта KR появится файл компилированного модуля RusTrans.dcu, а в проекте Blank в разделе Uses добавится строка с его именем. program Blank; {$APPTYPE CONSOLE} uses SysUtils, RusTrans in 'RusTrans'; begin {Main : Insert code here } ..... writeln(Rus('Я студент ПГАТИ')); readln; end. 6. В разделе исполнения проекта Blank между операторными скобками begin… end для проверки работы модуля RusTrans внести строку кода с любым текстом, например writeln(Rus('Я студент')). 9 7. Запустить проект на исполнение командой Выполнить => Выполнить, и убедиться, что при подключении модуля, проблема с отображением букв кириллицы решена. 8. Удалить введенную для проверки работоспособности строку. Сохранить изменения в проекте, щелкнув по кнопке Сохранить на панели Инструментов. 9. В соответствующие разделы проекта в вести переменные, процедуры и код для решения поставленных задач. 01- ☺ 2- ☻ 3- ♥ 4- ♦ 5- ♣ 6- ♠ 789 - Tab 10 11 - ♂ 12 - ♀ 13 14 - ♫ 15 - ☼ 16 - ► 17 - ◄ 18 - ↕ 19 - ‼ 20 - ¶ 21 - § 22 - ▬ 23 - ↨ 24 - ↑ 25 - ↓ 26 - → 27 - ← 28 -∟ 29 - ↔ 30 -▲ 31 - ▼ 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 - 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 - ! " # $ % & ' ( ) * + , . / 128 - А 129 - Б 130 - В 131 - Г 132 - Д 133 - Е 134 - Ж 135 - З 136 - И 137 - Й 138 - К 139 - Л 140 - М 141 - Н 142 - О 143 - П 144 - Р 145 - С 146 - Т 147 - У 148 - Ф 149 - Х 150 - Ц 151 - Ч 152 - Ш 153 - Щ 154 - Ъ 155 - Ы 156 - Ь 157 - Э 158 - Ю 159 - Я 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 - а б в г д е ж з и й к л м н о п 128 - Ђ 129 - Ѓ 130 - ‚ 131 - ѓ 132 - „ 133 - … 134 - † 135 - ‡ 136 - € 137 - ‰ 138 - Љ 139 - ‹ 140 -Њ 141 -Ќ 142 -Ћ 143 –Џ 144 - ђ 145 - ‘ 146 - ’ 147 - “ 148 - ” 149 - • 150 - – 151 - — 152 - ˜ 153 - ™ 154 - љ 155 - › 156 -њ 157 -ќ 158 -ћ 159 -џ 160 161 - Ў 162 - ў 163 - Ј 164 - ¤ 165 - Ґ 166 - ¦ 167 - § 168 - Ё 169 - © 170 - Є 171 - « 172 -¬ 173 -174 -® 175 -Ї 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 - ░ ▒ ▓ │ ┤ ╡ ╢ ╖ ╕ ╣ ║ ╗ ╝ ╜ ╛ ┐ 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 - @ A B C D E F G H I J K L M N O 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 - └ ┴ ┬ ├ ─ ┼ ╞ ╟ ╚ ╔ ╩ ╦ ╠ ═ ╬ ╧ 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 - P Q R S T U V W X Y Z [ \ ] ^ _ Базовая таблица кодировки ASCII 96 - ` 97 - a 98 - b 99 - c 100 - d 101 - e 102 - f 103 - g 104 - h 105 - i 106 - j 107 - k 108 - l 109 - m 110 - n 111 - o 112 - p 113 - q 114 - r 115 - s 116 - t 117 - u 118 - v 119 - w 120 - x 121 - y 122 - z 123 - { 124 - | 125 - } 126 - ~ 127 - ⌂ 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 - р с т у ф х ц ч ш щ ъ ы ь э ю я 240 - Ё 241 - ё 242 - Є 243 - є 244 - Ї 245 - ї 246 - Ў 247 - ў 248 - ° 249 - ∙ 250 - · 251 - √ 252 - № 253 - ¤ 254 - ■ 255 - 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 - а б в г д е ж з и й к л м н о п ГОСТ - альтернативная кодировка MS DOS 208 - ╨ 209 - ╤ 210 - ╥ 211 - ╙ 212 - ╘ 213 - ╒ 214 - ╓ 215 - ╫ 216 - ╪ 217 - ┘ 218 - ┌ 219 - █ 220 - ▄ 221 - ▌ 222 - ▐ 223 - ▀ Кодировка Windows 1251 176 - ° 177 - ± 178 - І 179 - і 180 - ґ 181 - µ 182 - ¶ 183 - · 184 - ё 185 - № 186 - є 187 - » 188 -ј 189 -Ѕ 190 -ѕ 191 -ї Начало i=1mes Да mes[i]=chr(ord (mes[ i ])-64) Да mes[i]=chr(ord (mes[ i ])-16 mes[i]= 'А'..'п'? Нет mes[i]= 'р'..'я'? Нет result=mes Конец 192 - А 193 - Б 194 - В 195 - Г 196 - Д 197 - Е 198 - Ж 199 - З 200 - И 201 - Й 202 - К 203 - Л 204 - М 205 - Н 206 - О 207 - П 208 - Р 209 - С 210 - Т 211 - У 212 - Ф 213 - Х 214 - Ц 215 - Ч 216 - Ш 217 - Щ 218 - Ъ 219 - Ы 220 - Ь 221 - Э 222 - Ю 223 - Я 240 241 242 243 244 245 245 247 248 249 250 251 252 253 254 255 - р с т у ф х х ч ш щ ъ ы ь э ю я