Ответы на вопросы по языкам программирования. Вопросы к экзамену. Инф Вопросы для подготовки к экзамену (3 курс) Метод нисходящего проектирования программы
Скачать 0.64 Mb.
|
Инф Вопросы для подготовки к экзамену (3 курс) Метод нисходящего проектирования программы. Метод нисходящего проектирования предполагает последовательное разложение общей функции обработки данных на простые функциональные элементы ("сверху-вниз"). В результате строится иерархическая схема, отражающая состав и взаимоподчиненность отдельных функций, которая носит название функциональная структура алгоритма (ФСА) приложения. Последовательность действий по разработке функциональной структуры алгоритма приложения: определяются цели автоматизации предметной области и их иерархия (цель-подцель); устанавливается состав приложений (задач обработки), обеспечивающих реализацию поставленных целей; уточняется характер взаимосвязи приложений и их основные характеристики (информация для решения задач, время и периодичность решения, условия выполнения и др.); определяются необходимые для решения задач функции обработки данных; выполняется декомпозиция функций обработки до необходимой структурной сложности, реализуемой предполагаемым инструментарием. Подобная структура приложения (рис. 18.2) отражает наиболее важное - состав и взаимосвязь функций обработки информации для реализации приложений, хотя и не раскрывает логику выполнения каждой отдельной функции, условия или периодичность их вызовов. Разложение должно носить строго функциональный характер, т.е. отдельный элемент ФСА описывает законченную содержательную функцию обработки информации, которая предполагает определенный способ реализации на программном уровне. Функции ввода-вывода информации рекомендуется отделять от функций вычислительной или логической обработки данных. По частоте использования функции делятся на: однократно выполняемые; повторяющиеся. Степень детализации функций может быть различной, но иерархическая схема должна давать представление о составе и структуре взаимосвязанных функций и общем алгоритме обработки данных. Широко используемые функции приобретают ранг стандартных (встроенных) функций при проектировании внутренней структуры программного продукта. Метод нисходящего проектирования программ основан на идее уровней абстракции, которые становятся уровнями модулей в разрабатываемой программе. На этапе проектирования строится схема иерархии, которая изображает эти уровни и позволяется сконцентрироваться сначала на том, что надо сделать в программе, затем разрабатывать решение. При этом методе проектирования исходная задача, подлежащая решению, делится на ряд подзадач, которые подчиняются главной задаче. Это разбиение называют декомпозицией. Далее эти задачи делятся еще на более мелкие и т.д. до тех пор, пока не получатся задачи, для решения которых требуются небольшие модули 3-5 строк. Такой метод позволяет упростить решение сложных задач. Паскаль имеет различные средства для деления программы на части. На верхнем уровне деления (больших задач) – это модули, на нижнем уровне (элементарных подзадач) – это процедуры и функции. Понятие подпрограммы. Виды подпрограмм. Подпрограммой называется именованная, логически законченная группа операторов языка, которую можно вызвать для выполнения по имени любое количество раз из различных мест программы. Определение. Подпрограмма – это отдельная функционально независимая часть программы. Любая подпрограмма обладает той же структурой, которой обладает и вся программа. Подпрограммы решают три важные задачи: • избавляют от необходимости многократно повторять в тексте программы аналогичные фрагменты; • улучшают структуру программы, облегчая ее понимание; • повышают устойчивость к ошибкам программирования и непредвидимым последствиям при модификациях программы. В языке Паскаль для организации подпрограмм используются подпрограммы-процедуры и подпрограммы-функции, которые, в зависимости от целей программирования, могут размещаться следующим образом: Ÿ головная программа и подпрограммы расположены в одном программном модуле; Ÿ подпрограммы расположены в отдельных файлах и включаются в основной файл посредством директивы компилятора; Ÿ подпрограммы организуются как оверлейные структуры и поочередно загружаются в одно и то же место памяти; Ÿ подпрограммы пишутся на машинном коде и затем включаются в программу; Ÿ подпрограммы располагаются во внешней библиотеке и вызываются из основной программы. Все процедуры и функции языка Паскаль разделяются на встроенные и описанные пользователем. Встроенные (стандартные) процедуры и функции являются частью языка и могут вызываться по имени без предварительного определения в разделе описаний. Различают 9 основных групп встроенных процедур и функций. Для обозначения типов данных аргументов используются сокращения: IBR – целочисленный (I), байтовый (B), вещественный тип (R); S – любой из скалярных типов, кроме вещественного. Существует две категории подпрограмм: процедуры и функции. Процедура — это подпрограмма, которая не возвращает через своё имя результата работы, поэтому она вызывается как отдельный оператор. Процедура «общается с внешним миром» через список параметров. Часть из них будут входными, часть — выходными, т.е. результатом работы. Функция — это подпрограмма, которая через имя возвращает результат своей работы. Функция вызывается в выражении, а не как отдельный оператор. Через список параметров она может получить входные данные и вернуть результаты работы. Традиционно подпрограмму оформляют в виде функции, если результатом работы является одиночный объект (число, символ, строка). Пример алгоритмов, которые удобно оформить функцией: вычисление значения определенного интеграла, нахождение минимального числа в массиве, подсчет количества пробелов в строке и т.д. Если результатом работы подпрограммы является несколько объектов, или выходным данным является массив, то необходимо использовать процедуру, так как через имя подпрограммы можно вернуть только один простой объект (число, адрес, символ), а через список параметров — любое количество и одиночных и составных объектов. Возврат результата одновременно и через имя, и через список параметров плох, так как вводит пользователя подпрограммы в некоторое заблуждение относительно того, что может изменить подпрограмма. Процедуры. Описание и правила вызова. В языке Паскаль, как и в большинстве языков программирования, предусмотрены средства, позволяющие оформлять вспомогательный алгоритм как подпрограмму. Это бывает необходимо тогда, когда какой-либо подалгоритм неоднократно повторяется в программе или имеется возможность использовать некоторые фрагменты уже разработанных ранее алгоритмов. Кроме того, подпрограммы применяются для разбиения крупных программ на отдельные смысловые части в соответствии с модульным принципом в программировании. Для использования подалгоритма в качестве подпрограммы ему необходимо присвоить имя и описать алгоритм по правилам языка Паскаль. В дальнейшем, при необходимости вызвать его в программе, делают вызов подпрограммы упоминанием в нужном месте имени соответствующего подалгоритма со списком входных и выходных данных. Такое упоминание приводит к выполнению входящих в подпрограмму операторов, работающих с указанными данными. После выполнения подпрограммы работа продолжается с той команды, которая непосредственно следует за вызовом подпрограммы. В языке Паскаль имеется два вида подпрограмм - процедуры и функции. Процедуры и функции помещаются в раздел описаний программы. Для обмена информацией между процедурами и функциями и другими блоками программы существует механизм входных и выходных параметров. Входными параметрами называют величины, передающиеся из вызывающего блока в подпрограмму (исходные данные для подпрограммы), а выходными - передающиеся из подрограммы в вызывающий блок (результаты работы подпрограммы). Одна и та же подпрограмма может вызываться неоднократно, выполняя одни и те же действия с разными наборами входных данных. Параметры, использующиеся при записи текста подпрограммы в разделе описаний, называют формальными, а те, что используются при ее вызове - фактическими. Описание и вызов процедур и функций Структура описания процедур и функций до некоторой степени похожа на структуру Паскаль-программы: у них также имеются заголовок, раздел описаний и исполняемая часть. Раздел описаний содержит те же подразделы, что и раздел описаний программы: описания констант, типов, меток, процедур, функций, перменных. Исполняемая часть содержит собственно операторы процедур. Формат описания процедуры имеет вид: procedure имя процедуры (формальные параметры); раздел описаний процедуры begin исполняемая часть процедуры end; Формат описания функции: function имя функции (формальные параметры):тип результата; раздел описаний функции begin исполняемая часть функции end; Формальные параметры в заголовке процедур и функций записываются в виде: var имя праметра: имя типа и отделяются друг от друга точкой с запятой. Ключевое слово var может отсутствовать (об этом далее). Если параметры однотипны, то их имена можно перечислять через запятую, указывая общее для них имя типа. При описании параметров можно использовать только стандартные имена типов, либо имена типов, определенные с помощью команды type.Список формальных параметров может отсутствовать. Вызов процедуры производится оператором, имеющим следующий формат: имя процедуры(список фактических параметров); Список фактических параметров - это их перечисление через запятую. При вызове фактические параметры как бы подставляются вместо формальных, стоящих на тех же местах в заголовке. Таким образом происходит передача входных параметров, затем выполняются операторы исполняемой части процедуры, после чего происходит возврат в вызывающий блок. Передача выходных параметров происходит непосредственно во время работы исполняемой части. Вызов функции в Турбо Паскаль может производиться аналогичным способом, кроме того имеется возможность осуществить вызов внутри какого-либо выражения. В частности имя функции может стоять в правой части оператора присваивания, в разделе условий оператора if и т.д. Для передачи в вызывающий блок выходного значения функции в исполняемой части функции перед возвратом в вызывающий блок необходимо поместить следующую команду: имя функции := результат; При вызове процедур и функций необходимо соблюдать следущие правила: количество фактических параметров должно совпадать с количеством формальных; соответствующие фактические и формальные параметры должны совпадать по порядку следования и по типу. Заметим, что имена формальных и фактических параметров могут совпадать. Это не приводит к проблемам, так как соответствующие им переменные все равно будут различны из-за того, что хранятся в разных областях памяти. Кроме того, все формальные параметры являются временными переменными - они создаются в момент вызова подпрограммы и уничтожаются в момент выхода из нее. Рассмотрим использование процедуры на примере программы поиска максимума из двух целых чисел. var x,y,m,n: integer; procedure MaxNumber(a,b: integer; var max: integer); begin if a>b then max:=a else max:=b; end; begin write('Введите x,y '); readln(x,y); MaxNumber(x,y,m); MaxNumber(2,x+y,n); writeln('m=',m,'n=',n); end. Аналогичную задачу, но уже с использованием функций, можно решить так: var x,y,m,n: integer; function MaxNumber(a,b: integer): integer; var max: integer; begin if a>b then max:=a else max:=b; MaxNumber := max; end; begin write('Введите x,y '); readln(x,y); m := MaxNumber(x,y); n := MaxNumber(2,x+y); writeln('m=',m,'n=',n); end. Функции. Описание и правила вызова. Функция — это подпрограмма, возвращающая одно значение в вызывающую программу. Функцию можно использовать в качестве операнда в выражениях. Поэтому, если в вызывающую программу необходимо возвратить одно значение, то рекомендуется оформить подпрограмму как функцию. Описание функции Любая используемая в программе функция должна быть предварительно описана в разделе описаний. Функции в разделе описаний, так же как и процедуры, определяют после раздела описания переменных (после раздела Var) и до начала раздела операторов (до слова Begin). Заголовок функции начинается с ключевого слова Function, за которым следует имя функции и необязательный, заключенный в круглые скобки, список формальных параметров с указанием типа каждого параметра. После чего через двоеточие записывается тип возвращаемого значения. Операторы функции внутри операторных скобок begin/end называются телом этой функции. В теле функции обязательно должен быть оператор присвоения, где в левой части стоит имя функции, а в правой — её значение. Иначе, значение функции не будет определено. Таким образом, общий вид функции в языке Паскаль такой: function <имя функции>[<список формальных параметров>]:<тип возвращаемого значения>; <раздел описаний> begin <операторы> <имя функции> := <возвращаемое значение>; еnd; В языке Pascal ABC вместо имени функции для возврата значений в вызывающую программу можно использовать другую специальную переменную с именем Result. Раздел описаний функции устроен так же, как раздел описаний основной программы. Здесь описываются так называемые локальные переменные и константы, типы, а также вложенные процедуры и функции. Все такие локальные объекты доступны лишь внутри данной функции и не видны извне. Вызов функции Вызовом функции является записанное в вызывающей программе имя функции со списком фактических параметров в круглых скобках. В отличие от вызова процедуры вызов функции возвращает одно значение (скалярную величину), следовательно, вызывающая программа должна с ним что-нибудь сделать (сохранить в переменной, вывести на экран и т.д.). Вызов функции с присвоением возвращаемого значения некоторой переменной имеет следующий вид: <имя переменной> := <имя функции> [(<список фактических параметров>)]; Фактические параметры — это значения, передаваемые в функцию при её вызове. Пример 1. Оформить в виде функции алгоритм вычисления степени y = xn с натуральным показателем n. function degree(x,y:integer): longint; var i:integer; begin st :=1; For i:=1 to y do st:= st * x; degree:= st; end; Функция имеет два параметра: первый параметр — основание степени, второй — показатель степени. Вся программа для нашей задачи имеет следующий вид: program primer1; var a, n: integer; s:longint; function degree(x,y:integer): longint; var i:integer; begin st :=1; For i:=1 to y do st:= st * x; degree:= st;end; begin {main} writeln('Введите два числа'); readln(a, n); s := degree(a,n); {Вызов функции} writeln('Результат: ', s); {Вывод результата} end. Функция вызывается по имени в левой части оператора присваивания, вычиcленное значение присваивается переменной s. В нашем примере, фактические параметры а, n передают свои значения соответствующим формальным параметрам x, y. Вы научились определять и вызывать пользовательские функции. Способы передачи данных в подпрограммы. Существует два способа передачи параметров в подпрограммы – передача по значению и передача по наименованию. Способ передачи указывается при объявлении параметра в списке формальных параметров. По умолчанию предполагается, что параметры обычных типов, например, Real, Integer, String, передаются по значению, а параметры таких типов как визуальные компоненты, динамические массивы передаются по наименованию. Если возникает необходимость явно указать, что параметр передается по наименованию, то перед именем параметра, или перечнем имен одного типа, пишется слово var. 3.1.2.1 Передача параметров по значению Передача параметров по значению предполагает, что при вызове подпрограммы в памяти будет выделена специальная область для записи копий значений фактических параметров, с которыми и будет работать подпрограмма. Такой способ передачи защищает переменные, передаваемые в подпрограмму в качестве параметров, от непредусмотренного изменения, так как подпрограмма работает с копиями. Кроме того, такой способ позволяет в качестве фактических параметров задавать выражения. При передаче параметров будет вычислено значение этого выражения и передано в подпрограмму. Недостаток такого способа передачи состоит в том, что при передаче параметров, требующих много памяти, например, большие массивы чисел или длинные строки, копии занимают много места в памяти и требуется много времени для пересылки данных из одного места памяти в другое. 3.1.2.2 Передача параметров по наименованию При передаче параметров по наименованию в подпрограмму передаются адреса фактических параметров. Поэтому такой способ передачи называется еще передачей параметров по адресу или по ссылке. При таком способе передачи в качестве фактических параметров можно передавать только переменные. Выражение и даже отдельное число или символ передать по наименованию нельзя. Передача параметров по наименованию экономит память и сокращает время обращения к подпрограммам. Однако это имеет и побочный эффект. Так как подпрограмма работает непосредственно с фактическими параметрами, то любое изменение формального параметра является изменением фактического параметра. Для исключения такого эффекта нужно в объявлении формальных параметров вместо слова var использовать слово const. Но побочный эффект имеет и положительную сторону. Передачу параметров по наименованию можно использовать для возвращения результатов работы подпрограммы через фактические параметры. Такой способ возвращения особенно эффективен, когда требуется вернуть несколько параметров. Ведь функция возвращает только одно значение. Выше, в пункте 3.1.1 уже рассматривался пример процедуры с передачей параметра по наименованию. Рассмотрим еще один пример использования передачи параметров по наименованию для возвращения результатов работы подпрограммы. В создаваемом ниже приложении для расчетов по формуле используется процедура считывания коэффициентов уравнения. Исходный текст этой процедуры приведен ниже. ProceduregetKoef (var kA, kB, kC:Real); Begin kA:=strToFloat(frmSubroutine.edtA.Text); kB:=strToFloat(frmSubroutine.edtB.Text); kC:=strToFloat(frmSubroutine.edtC.Text); end; В этой процедуре содержимое текстовых полей преобразуется в вещественные числа, и результаты преобразования присваиваются формальным параметрам, которые объявлены как передаваемые по наименованию. На это указывает слово varперед именами параметров. Обращение к этой процедуре происходит в другой процедуре, которая обрабатывает событие onClick кнопки «Расчет по формуле». Фрагмент этой процедуры приведен ниже. До вызова процедуры значения переменных a, b, c были неопределенными (мусор). При вызове процедуры getKoef адреса этих переменных были переданы в качестве фактических параметров. При выполнении процедуры, по этим адресам были записаны результаты преобразования данных. В результате, после окончания работы процедуры getKoef переменные a, b, c приобрели новые значения, которые были вычислены в процедуре procedure TfrmSubroutine.btnCalculateRootsClick(Sender: TObject); var a, b, c :Real; Begin // До вызова процедуры getKoefKvUr // значения переменных a,b,c не определены getKoef(a,b,c); //После вызова процедуры значения переменных // a,b,c соответствуют содержиммому тектовых полей … end; Области видимости переменных. Каждая переменная кроме имени, типа данных и значения имеет ещё одну характеристику – область видимости переменной. Область видимости переменной – это участок кода программы, в котором данная переменная доступна для использования. Рассмотрим пример, написанный ранее. Листинг 1. #include int max_num(int a, int b){ int max = b; if (a > b) max = a; return max; } int main(void) { int x =0, y = 0; int m = 0; scanf("%d %d", &x, &y); m = max_num(x,y); printf("max(%d,%d) = %d\n",x,y,m); return 0; } В этом коде переменные a, b и max доступны для использования только внутри функции max_num. А переменные x,y и m – внутри функции main. Область видимости этих переменных – тело функции, в которой они объявлены. Это означает, к примеру, что мы не можем избавиться от переменной max внутри функции max_num и присваивать значение сразу переменной m. Т.е. вот такой код работать не будет: Листинг 2. #include void max_num(int a, int b){ m = b; if (a > b) m = a; } int main(void) { int x =0, y = 0; int m = 0; scanf("%d %d", &x, &y); max_num(x,y); printf("max(%d,%d) = %d\n",x,y,m); return 0; } Если вы попытаетесь его скомпилировать, то компилятор будет ругаться на несуществующую переменную m внутри функции max_num. Решить эту проблему довольно просто. Достаточно объявить переменную m вне всех функций, сразу после директив препроцессора. Листинг 3. #include int m = 0; void max_num(int a, int b){ m = b; if (a > b) m = a; } int main(void) { int x =0, y = 0; scanf("%d %d", &x, &y); max_num(x,y); printf("max(%d,%d) = %d\n",x,y,m); return 0; } Переменные, объявленные таким образом, называются глобальными, т.к. доступ к ним возможен из любого места в этом файле (доступны глобально). Те переменные, которые мы использовали ранее, называются локальными, т.к. они доступны только в некоторых местах программы (доступны локально). Рис.1 Область видимости переменных (глобальные и локальные) К локальным относятся также переменные, объявленные, например, внутри тела цикла. Возможно, вы замечали, что если в программе два цикла for, то в каждом из них счётчик может иметь имя i и объявляться в заголовке цикла. Листинг 4. #include int main(void) { int x[10] = {1,4,34,53,1,92,4,8,2,44}; int min = 99999; int max = -99999; for(int i = 0; i<10; i++){ if (x[i] < min) min = x[i]; } for(int i = 0; i<10; i++){ if (x[i] > max) max = x[i]; } printf("max: %d\tmin: %d\n",max,min); return 0; } Дело как раз в области видимости и времени жизни локальных переменных. Каждый раз при создании цикла создаётся новая переменная с именем i. На протяжении всего тела цикла данная переменная доступна для использования, т.е. её область видимости – это блок тело цикла. После того как цикл завершается, эта переменная удаляется из памяти. Её время жизни – время работы цикла. Для переменных, объявленных внутри функции, время жизни переменных – время выполнения данной функции. Рис.2 Область видимости переменных объявленных в цикле Если нам не жалко ресурсов памяти, то мы могли бы сделать вот так: Листинг 5. #include int main(void) { int x[10] = {1,4,34,53,1,92,4,8,2,44}; int min = 99999; int max = -99999; int i; for(i = 0; i<10; i++){ if (x[i] < min) min = x[i]; } for(i = 0; i<10; i++){ if (x[i] > max) max = x[i]; } printf("max: %d\tmin: %d\n",max,min); return 0; } В этом случае создаётся одна переменная i, которая в дальнейшем используется во всех циклах. Попробуйте добавить вывод на экран значения переменной i между циклами. В первом случае должна появиться ошибка, т.к. переменная i существует только внутри циклов, а во втором случае всё будет нормально и значение i будет равно 10. Технология оформления алгоритмов в виде подпрограмм. Запись вспомогательных алгоритмов в языках программирования осуществляется с помощью подпрограмм. В языке Pascal различают два вида подпрограмм: процедуры и функции. Процедура — подпрограмма, имеющая произвольное количество входных и выходных данных. Описание процедуры имеет вид: procedure <имя_процедуры>(<описание параметров-значений>; var: <описание параметров-переменных>); begin <операторы> end; В заголовке процедуры после её имени приводится перечень формальных параметров и их типов. Для вызова процедуры достаточно указать её имя со списком фактических параметров. При этом между фактическими и формальными параметрами должно быть полное соответствие по количеству, порядку следования и типу. Пример 6. Запишем на языке Pascal программу нахождения периметра треугольника, заданного координатами его вершин. Вспомогательный алгоритм оформим с помощью процедуры. Выполните программу на компьютере. Подумайте, каким образом можно модифицировать программу, чтобы вычислять с её помощью периметр n-угольника. Каким образом при решении этой задачи можно использовать массивы? Функция — подпрограмма, имеющая единственный результат, записываемый в ячейку памяти, имя которой совпадает с именем функции. Описание функции имеет вид: В заголовке функции после её имени приводится описание входных данных — указывается перечень формальных параметров и их типов. Там же указывается тип самой функции, т. е. тип результата. В блоке функции обязательно должен присутствовать оператор <имя_функции> := <результат>; Для вызова функции достаточно указать её имя со списком фактических параметров в любом выражении, в условиях (после слов if, while, until) или в операторе write главной программы. Пример 7. Запишем на языке Pascal программу нахождения периметра треугольника, заданного координатами его вершин. Вспомогательный алгоритм оформим с помощью функции. Выполните программу на компьютере. На основе этой программы напишите функцию, вычисляющую площадь треугольника по целочисленным координатам его вершин. Используйте эту функцию для вычисления площади n-угольника. САМОЕ ГЛАВНОЕ Структурное программирование — технология разработки программного обеспечения, в основе которой лежит представление программы в виде иерархической структуры логически целостных фрагментов (блоков). Основные принципы структурного программирования заключаются в том, что: 1) любая программа строится из трёх базовых управляющих конструкций: последовательность, ветвление, цикл; 2) в программе базовые управляющие конструкции могут быть вложены друг в друга произвольным образом; 3) повторяющиеся фрагменты программы можно оформить в виде подпрограмм (процедур и функций). В виде подпрограмм можно оформить логически целостные фрагменты программы, даже если они не повторяются; 4) все перечисленные конструкции должны иметь один вход и один выход; 5) разработка программы ведётся пошагово, методом «сверху вниз». Вспомогательный алгоритм — это алгоритм, целиком используемый в составе другого алгоритма. Алгоритм называется рекурсивным, если на каком-либо шаге он прямо или косвенно обращается сам к себе. Запись вспомогательных алгоритмов в языках программирования осуществляется с помощью подпрограмм. В языке Pascal различают два вида подпрограмм: процедуры и функции. Формирование библиотек подпрограмм. Стандартные модули языка Pascal. Стандартный язык Pascal не располагает средствами разработки и поддержки библиотек программиста (в отличие, скажем, от языка Fortran и других языков программирования высокого уровня), которые компилируются отдельно и в дальнейшем могут быть использованы как самим разработчиком, так и другими. Если программист имеет достаточно большие наработки, и те или иные подпрограммы могут быть использованы при написании новых приложений, то приходится эти подпрограммы целиком включать в новый текст. В Turbo Pascal это ограничение преодолевается за счет, во-первых, введения внешних процедур, во-вторых, разработки и использования модулей. В настоящей публикации на примерах рассмотрим работу с теми и другими программными единицами. Начнем с внешних подпрограмм. Такой механизм предусматривает, что исходный текст каждой процедуры или функции хранится в отдельном файле и при необходимости с помощью специальной директивы компилятора включается в текст создаваемой программы. Покажем это на примере задач целочисленной арифметики, где аргументы, результаты и промежуточные величины являются целыми (Integer, Word, LongInt и т.д.). Вот несколько таких задач. 1. Дано натуральное число n. Найти сумму первой и последней цифры этого числа. 2. Дано натуральное число n. Переставить местами первую и последнюю цифры этого числа. 3. Дано натуральное число n. Дописать к нему цифру k в конец и в начало (если это возможно, т.е. результат не выйдет за диапазон допустимых значений), или сообщить о невозможности выполнения операции. 4. Найти наибольшую цифру в записи данного натурального числа. 5. Дано натуральное число n. Переставить его цифры так, чтобы образовалось максимальное число, записанное теми же цифрами. При решении каждой из этих задач может быть использована функция, возвращающая количество цифр в записи натурального числа. Вот возможный вариант такой функции: Function Digits(N : LongInt) : Byte; Var Kol : Byte; Begin Kol := 0; While N <> 0 Do Begin Kol := Kol + 1; N := N Div 10 End; Digits := Kol End; Сохраним этот текст в файле с расширением .inc (это расширение внешних подпрограмм в Turbo Pascal), например, digits.inc. Еще необходима функция возведения натурального числа в натуральную степень. Function Power(A, N : LongInt) : LongInt; {файл power.inc} Var I, St : LongInt; Begin St := 1; For I := 1 To N Do St := St * A; Power := St End; Попробуем использовать функции при решении задачи номер один. Program Example1; Var N, S : LongInt; {$I digits.inc} {подключаем внешнюю функцию digits.inc, возвращающую количество цифр в записи числа} {$I power.inc} {внешняя функция, выполняющая возведение числа A в степень N} Begin Write('Введите натуральное число: '); ReadLn(N); {для определения последней цифры числа N берем остаток от деления этого числа на 10, а для определения первой делим N на 10 в степени на единицу меньшую, чем количество цифр в записи числа (нумерация разрядов начинается с 0)} S := N Mod 10 + N Div Power(10, Digits(N) - 1); WriteLn('Искомая сумма: ', S) End. Внешние процедуры создаются и внедряются в использующие их программы аналогично функциям, и мы не будем подробно на этом останавливаться. Далее речь пойдет о модулях: их структуре, разработке, компиляции и использовании. Модуль — это набор ресурсов (функций, процедур, констант, переменных, типов и т.д.), разрабатываемых и хранимых независимо от использующих их программ. В отличие от внешних подпрограмм модуль может содержать достаточно большой набор процедур и функций, а также других ресурсов для разработки программ. Обычно каждый модуль содержит логически связанные между собой программные ресурсы. В основе идеи модульности лежат принципы структурного программирования. Существуют стандартные модули Turbo Pascal, которые обычно описываются в литературе по данному языку. Модуль имеет следующую структуру: Unit <имя модуля>; {заголовок модуля} Interface {интерфейсная часть} Implementation {раздел реализации} Begin {раздел инициализации модуля} End. После служебного слова Unit записывается имя модуля, которое (для удобства дальнейших действий) должно совпадать с именем файла, содержащего данный модуль. Поэтому (как принято в MS DOS) имя не должно содержать более 8 символов. В разделе Interface объявляются все ресурсы, которые будут в дальнейшем доступны программисту при подключении модуля. Для подпрограмм здесь указывается лишь полный заголовок. В разделе Implementation реализуются все подпрограммы, которые были ранее объявлены. Кроме того, здесь могут содержаться свои константы, переменные, типы, подпрограммы и т.д., которые носят вспомогательный характер и используются для написания основных подпрограмм. В отличие от ресурсов, объявленных в разделе Interface, все, что дополнительно объявляется в Implementation, уже не будет доступно при подключении модуля. При написании основных подпрограмм достаточно указать их имя (т.е. не нужно полностью переписывать весь заголовок), а затем записать тело подпрограммы. Наконец, раздел инициализации (который часто отсутствует) содержит операторы, которые должны быть выполнены сразу же после запуска программы, использующей модуль. Приведем пример разработки и использования модуля. Поскольку рассмотренная ниже задача достаточно элементарна, ограничимся листингом программы с подробными комментариями. |