Мы поможем в написании ваших работ!
ЗНАЕТЕ ЛИ ВЫ?
|
Подпрограммы, функции и процедуры
Общие сведения
Структура программы в ТУРБО БЕЙСИКе может быть упрощена использованием подпрограмм, процедур и функций. Примеры программ в предыдущих разделах должны были подготовить вас к восприятию мысли о том, что в каждой задаче полезно вычленять логически завершенные фрагменты и оформлять их как отдельные программные единицы - подпрограммы (процедуры) или функции. Что это дает? Во-первых, упрощается логика программ за счет вынесения многочисленных деталей за рамки основного алгоритма. Появляется возможность конструировать программу "сверху - вниз", составляя ее по началу из пустых блоков (заглушек), о которых известно только их функциональное назначение. Потом каждый из блоков детализируется, разбиваясь на более мелкие программные единицы и т. д. Подпрограммы, текст которых обычно не превышает одну-две страницы, гораздо легче анализировать и отлаживать. Во-вторых, выделение подпрограмм позволяет уменьшить общий объем программы особенно в тех случаях, когда к ним приходится многократно обращаться из разных точек. Наконец, многие подпрограммы могут быть использованы повторно при решении других задач. Цель настоящего раздела - вкратце систематизировать основные сведения, связанные с организацией и использованием подпрограмм (функции можно рассматривать как частный случай подпрограмм, результатом работы которых является единственное значение). Любая программа, готовая к самостоятельному исполнению, состоит из единственной головной (или главной) программы, с которой начинается работа, и некоторого количества подчиненных ей подпрограмм. Головная программа непосредственно или косвенно может обратиться к любой подпрограмме, которые точно таким же образом могут вызвать любую подпрограмму, включая и себя. К головной программе никакая другая программная единица обратиться не может. Подпрограммы, поставляемые в составе системы программирования, обычно называют стандартными или системными. Все остальные подпрограммы, которые мы пишем сами или заимствуем из каких-либо других источников, называют нестандартными или пользовательскими. Текст программы на алгоритмическом языке, оформленный в виде дискового файла с соответствующим расширением (bas, с, срр, pas), принято называть исходным модулем. В решении задачи может принимать участие один или несколько исходных модулей.
Подпрограммы и функции
Подпрограмма - это помеченный набор инструкций, исполняемых при достижении GOSUB. Процедура - это как бы минипрограмма, называемая также подпрограммой, выполняющая некоторые важные части вашей основной программы. Функция - это набор команд, результатом выполнения которых является значение числовой или смвольной (строковой) переменной, зависящее от параметров передаваемых функции. Помещая комплексный и/или часто используемый код в эти структуры можно упростить и сократить ваши программы. Процедуры ТУРБО БЕЙСИКа и определяемые пользователем функции выходят за рамки простого структурирования, предлагаемыми подпрограммами. Хотя миллионы программ в Бейсике были написаны с помощью GOSUB/RETURN как основных организационных приспособлений, мы рекомендуем использовать эти улучшенные структуры. Процедуры и функции ТУРБО БЕЙСИКа обеспечивают истинную рекурсию, передачу параметров и доступ к локальным, статическим и глобальным переменным. Если вы еще не изведали преимуществ передачи параметров, локальных переменных и рекурсии, вам остается только попробовать. У процедур и функций сходства больше, чем различий. Наиболее яркое различие состоит в том, что функции возвращают величину и таким образом, вызываются неявно, появляясь в выражениях (с "FN" присоединенным впереди). Процедуры не возвращают величин и должны появляться явно оператором CALL (ВЫЗОВ). Например, a = b + FNCubeROOT(c) `вызов функции CALL OutChar(a) `вызов процедуры Ниже рассмотрены только внутренние подпрограммы и функции. Подпрограммы - это традиционный метод разбивки программ Бейсик; они состоят из помеченных групп операторов и заканчиваются оператором RETURN (ВОЗВРАТ). Для выполнения подпрограммы можно использовать оператор GOSUB для указания метки, связанной с первым оператором подпрограммы. При встрече с оператором RETURN управление переходит к оператору, непосредственно следующему за вызовом GOSUB.
Внутренние функции
Описанию внутренней функции с именем, обязательно начинающимся с символов "FN", предшествует заголовок вида: DEF FNs1s2...[(аргументы)] Вслед за ним располагаются обычные операторы, участвующие в вычислении значения функции, завершающиеся обязательным присвоением вычисленного результата: FNs1s2... = выражение Признаком конца описания внутренней функции является оператор END DEF. В теле внутренней функции может находиться оператор EXIT DBF, обеспечивающий досрочное завершение вычислений при выполнении определенных условий. Внутренняя функция, алгоритм вычисления которой сводится к единственному выражению, описывается одним оператором, после которого завершение END DEF не требуется: DEF FNs1s2... [(аргументы)]=выражение
Таким образом, DEF FN/END DEF определяет функцию. Синтаксис Единичная строка: DEF FN идентификатор[(список аргументов)]=выражение Многострочная: DEF FN идентификатор[(список аргументов)] [LOCAL список переменных] [STATIC список переменных] [SHARED список переменных] . . . [EXIT DEF] [FN идентификатор=выражение] END DEF Замечания Идентификатор - это уникальное имя, которое должно ассоциироваться с функцией и следовать соглашению об наименовании меток и переменных (т.е. представлять собой букву, за которой следует любое число букв и/или цифр). Список аргументов - это опциональная, разделяемая занятыми последовательность формальных параметров. Параметры, используемые в списке аргументов, служат только для определения функции: они не имеют взаимосвязи с другими переменными программы, имеющими те же имена. Cкобки DEF FN и END DEF и имя подобной субпрограмме группы операторов называется функцией. Функции может опционально подаваться один или более аргументов по назначению. Функции возвращают значение (тип которого управляется соответственно имени функции, как если бы это была переменная) и поэтому могут вызываться из любого оператора, которое способно принимать значение подходящего типа..
Определение функций и программный поток Положение определений функций не имеет значения. Функция может быть определена в строке 1 или строке 1000 программы, вне зависимости от того, где она используется и вам нет необходимости пропускать программный поток непосредственно через функцию в качестве шага возбуждения (что вы обязаны делать с однострочными функциями в Интерпретаторном Бейсике). Компилятор просматривает ваши определения, где бы они ни были.. Также, в отличие от подпрограмм, исполнение не может неожиданно "приняться" за функцию. Для всего, что касается исполнительного прохода программы, определения функций и процедур невидимы. Например:. t=fnВыдатьШтат def fnВыдатьШтат print "Выдаю из fnВыдатьШтат" end def Когда исполняется эта четырехстрочная программа, сообщение появляется только один раз, поскольку ВыдатьШтат вызывается только в первой строке.. Определения функций должны трактоваться как изолированные острова кода; ни переходов в них, ни переходов из них с помощью оператора GOTO, GOSUB или RETURN не существует. Однако в пределах самих определений такие операторы существуют.. Следует заметить, что определения функций и процедур нельзя гнездовать, т.е. незаконно определять процедуру или функцию внутри процедуры или функции (каждое определение процедуры или функции может содержать вызовы других процедур)..
Заявления локальных переменных(только многострочные функции) Чтобы заявить локольные переменные в пределах функции, перед любыми используемыми операторами в определении используйте оператор LOCAL. Например. LOCAL a%,b#,БольшойМассив%() Создает три локальных переменных: a%, b#, (целое и двойной точности соответственно) и массив БольшойМассив%. Затем массив должен быть надлежащим образом образмерен:. DIM DYNAMIC БольшойМассив%(1000)
Синтаксические и разделяемые переменные По умолчанию, переменные которые используются в определении функций, имеют атрибут SHARED (разделяемые); т.е. они являются глобальными для остальной программы. Поскольку это умолчание может измениться, вы обязаны затрачивать- усилия на заявление каждой используемой в функции переменной.. Заявляйте переменные с атрибутом STATIC, если важно чтобы переменная не теряла своего значения прикаждом возбуждении, но еще могла быть изменена только внутри функции.. Определение многострочной функции обычно включает в себя назначение идентификатору функции и должно завершатся END DEF. Если вы делаете выбор не включать назначение идентификатору функции, то значение возвращаемое из функции неопределенно.. Используйте для возвращения из функции где-то в ином месте, чем в конце ее, оператор EXIT DEF.. Пример: DEF FNS=x^3+x^2+cos(x) For x=1 to 10 step 0.5:Y=FNS:? Y:next end Операторы вычисления значения внутренней функции срабатывают только при вызове функции из головной программы. Если Бейсик-интерпретатор попадает на них другим способом, то тело внутренней функции обходится.
Подпрограммы GOSUB - RETURN
Подпрограмма представляет собой встроенную в модуль или автономно оформленную процедуру, к которой можно обратиться из любой точки, приостановив таким образом выполнение основной программы, и после завершения работы процедуры вернуться в точку прерывания для продолжения основной программы. Для организации работы подпрограмм характерны следующие обстоятельства. Во-первых, при каждом очередном обращении подпрограмме должны быть тем или иным способом переданы новые исходные данные. Без этого многократное выполнение подпрограммы потеряло бы свой смысл. Естественно, что результаты работы процедуры тоже каким-то образом должны быть возвращены адресату. Во-вторых, любое обращение к подпрограмме отличается от обычного перехода (GOTO, IF) тем, что координаты точки, из которой производится вызов, необходимо запомнить для организации возврата после завершения работы вызванной процедуры. Это напоминает ситуацию с циклами, когда при обработке заголовка приходится запоминать параметры и адрес точки входа в тело цикла. Они понадобятся в тот момент, когда будет обрабатываться последний оператор цикла. И при реализации вложенных циклов, и в случае последовательных обращений из одной подпрограммы в другую для запоминания очередной точки возврата используется стековый механизм. В момент обращения к подпрограмме адрес возврата заносится в стек и хранится там до тех пор, пока не будет выполнен специальный оператор возврата. При этом сделавший свое дело адрес возврата из стека удаляется. Внутренняя подпрограмма, входящая в текст головной программы, обязательно должна начинаться с метки, на которую передается управление оператором GOSUB. Работа внутренней подпрограммы завершается оператором RETURN, после чего продолжается работа основной программы с оператора, следующего за GOSUB. В отличие от обычных подпрограмм у внутренней подпрограммы отсутствуют параметры, и она может оперировать только с переменными основной программы. Логически внутренние подпрограммы повторяют структуру подпрограмм в машинных кодах. К внутренней подпрограмме может обратиться только ее владелец. GOSUB возбуждает подпрограмму Синтаксис GOSUB метка Замечания Оператор GOSUB вызывает переход Турбо-Бейсика к оператору, имеющему перед собой метку, после предварительного обеспечения хранения текущего адреса в стеке. Использование RETURN возвращает управление к оператору, следущему за GOSUB. Процедуры и функции Турбо-Бейсика могут выполнять работу подпрограмм с добавлением выигрыша в рекурсивности, подачи параметров и локальных и статических переменных. Пример: Ниже приведен листинг программы, в которой вычисление функции S(x) производится в специальной внутренней подпрограмме Sobaka. cls for x=0 to 2.1 step 0.2 gosub Sobaka ? using "x=##.# S=##.#####";x,S next end Sobaka: S=1+x+x^2/2+x^3/3+x^4/4+x^5/5 Return
Маcсивы
Определение и свойства
Что такое массив? Определение: массив — это набор однородных данных (чисел, символов, слов), имеющий имя и последовательную нумерацию его элементов. Например, список фамилий учеников группы — массив, численные данные о среднесуточной температуре за месяц — массив, буквы русского алфавита — массив. ВАЖНО: массив составляют входящие в него элементы, каждый из которых имеет свой собственный порядковый номер. Следовательно, для того чтобы описать массив, нужно а) задать количество входящих в него элементов и б) задать сами элементы. Если мы знаем, что в программе предстоит работать с большим объемом каких-то данных, то мы должны этот массив в программе объявить с помощью специального оператора dim (от англ. "dimension"), после которого указывается имя массива, а потом в скобках следует так называемый размер массива, т. е. количество его элементов. Например, пусть в группе четыре человека. Массив — это фамилии учеников. Мы тогда должны записать так: DIM FAM$ (4) Знак $ добавляется, т. к. в массиве будут храниться строковые переменные. В этом случае компьютер в памяти отводит некую область из четырех ячеек, которую всю и называет fam$. Кроме того, эти ячейки нумеруются натуральными числами, начиная с 1. Подобную процедуру, да и сам массив, можно сравнить с улицей одноэтажных домов в деревне или маленьком городке. Построили на улице четыре дома, назвали улицу fam$ (имя массива дается по тем же правилам, что и имя переменной), пронумеровали дома и заселили туда жильцов. FAM$ из четырех элементов
Из этого следует, что:
- у массива есть имя, которое дает ему программист;
- у массива есть тип, который определяется именем — числовой (имя без $) и текстовый (или символьный, или строковый — имя с символом $);
- у массива есть размер, т. е. количество составляющих его элементов;
- у массива есть сквозная последовательная индексация составляющих его элементов;
- у каждого элемента массива есть значение (в нашем случае это фамилия).
Предупреждение Оператор dim для каждого конкретного массива должен задаваться только один раз в программе до первого к нему обращения. Продолжая аналогию с улицей одноэтажных домов, что надо сделать, чтобы обратиться к какому-либо конкретному жильцу? Знать его адрес! Предположим, мы хотим потревожить господина Муна — указываем его адрес — fam$(2), т. е. название улицы и дом. Зачастую начинающие программисты путают индекс элемента массива (его номер) и значение элемента массива, т. е. "кто-кто в тереме живет". Итак, еще раз: индекс или номер элемента массива — величина постоянная, а значение (как и жильцы в доме) с легкостью может меняться. В начале мы рассмотрим одномерные массивы — такие, в которых адрес элемента массива определяется только одним индексом (номером "дома"). Предупреждение На самом деле, нумерация ячеек-"домиков" в Бейсике начинается с нуля, но с единицы нам привычнее и удобнее, поэтому нулевой "домик" мы пропускаем. Возможен более законный вариант — обязать Бейсик нумеровать "домики" с единицы оператором OPTION BASE 1. Массивы представляют собой организованный набор однотипных переменных, компактно расположенных в оперативной памяти. Все элементы одного массива снабжаются общим идентификатором, вслед за которым в круглых скобках записываются один или несколько индексов, определяющих местоположение элемента в массиве.
Использование массивов позволяет заменить большое количество индивидуальных имен каждого объекта одним групповым именем набора данных, вслед за которым в круглых (QBasic) или квадратных (Си, Паскаль) скобках задаются один или несколько индексов, определяющих местоположение требуемого значения. Естественно, что такая возможность упрощает и массовую обработку данных в соответствующих циклах программы. Кстати, маленькое лирическое отступление (из Учебник по языку Basic в задачах и примерах). Откуда пошла традиция указывать на билетах ряд и место? Оказывается из Франции. Когда тамошние дворяне при шпагах и гордом характере приходили в театр, имея просто билет без указания места, то нередко возникали смертоубийственные стычки из-за этих самых мест. Королю это надоело, и он обратился за помощью к ученому Декарту, который и предложил систему — "ряд—место". Эта система в дальнейшем трансформировалась в привычную нам декартову систему координат — ось X, ось Y.
Векторы и матрциы
Векторы Наиболее просто организованы одномерные массивы, являющиеся эквивалентами векторов. Все их элементы пронумерованы последовательными натуральными числами, которые и выполняют роль индексов. Минимальное значение индекса устанавливается либо по умолчанию, либо задается явным или неявным образом. Максимальное значение индекса обычно указывается при объявлении массива. Для необъявленных массивов максимальный индекс принимается равным 10.
Матрицы Представьте себе таблицу, состоящую из нескольких строк. Каждая строка состоит из нескольких ячеек. Тогда для точного определения положения ячейки нам потребуется знать не одно число (как в случае таблицы линейной), а два: номер строки и номер столбца. Структура данных для хранения такой таблицы называется двумерным массивом. Описать такой массив можно следующим образом: DIM a(20,30). Описан двумерный массив, соответствующий таблице, состоящей из 20 строк и 30 столбцов.
Отдельный элемент двумерного массива адресуется, естественно, двумя индексами. Сначала указывается номер строки, а затем - номер столбца. Например, ячейка, находящаяся в 5-й строке и 6-м столбце будет называться A[5,6]. Двумерные массивы являются аналогами матриц. Первый индекс элемента двумерного массива определяет номер строки, а второй - номер столбца, на пересечении которых расположен элемент. Строки и столбцы нумеруются либо от единого, установленного заранее минимального значения индекса, либо от граничного значения, заданного одновременно с объявлением массива.
В системе программирования TurboBasic максимальное количество индексов органичено 8, а максимальный индекс 32767.
9.6. Одномерные массивы − векторы
9.6.1. Ввод-вывод элементов линейного массива:
Первая задача, встающая перед программистом прежде чем, обработать массив, — заполнить его "жильцами". Для этого в Бейсике существует несколько способов, которые мы и рассмотрим. Кроме того, для контроля правильности заполнения, лучше бы сразу выводить массив на экран, чтобы потом можно было проверить правильность решения поставленной задачи. Ввод с клавиатуры массива из N=10 элементов
| cls for i=1 to 10 input A[i] next i end
| В данном примере размер массива известен заранее: N=10. А если этот размер заранее неизвестен? Тогда с клавитауры можно ввести размер N и после этого объявить массив: cls INPUT "Введите размер массива N"N DIM A(N) for i=1 to 10 input A[i] next i end Операторы READ - DATA Часто встречаются задачи, когда данные для обработки уже известны и содержатся в операторе data. (Однако, если их много, тяжелый труд — их туда заносить. Обычно — работа для молодых программистов.) DATA 23, 13, 98, 77, 45, 56, 32,' 10, 90, 55 CLS INPUT "Введите количество элементов массива"; N DIM MASS(N) FOR 1=1 ТО N READ MASS(I) ? MASS(I); NEXT I Программа стала несколько короче, т. к. в этом случае можно совместить чтение данных из data и одновременный вывод их на экран — ведь пользователь освобожден от необходимости вводить данные с клавиатуры. Мы сразу увидим массив на экране. Этот способ экономичней первого, и, кроме того, при отладке программы нет нужды всякий раз заново вводить данные. Ввод из файла При выполнении ЛР№2 необходимо ввести три числа, an, da, ak, из текстового файла. Аналогичным образом может быть организован ввод массива из файла CLS N=10 open "Ivanov3.txt" for input as#1 FOR 1=1 ТО N INPUT #1, A(I) ? A(I): NEXT I
|