Будь умным!


У вас вопросы?
У нас ответы:) SamZan.net

Тульский государственный университет Политехнический институт Кафедра

Работа добавлена на сайт samzan.net: 2016-03-13

Поможем написать учебную работу

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

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 23.5.2024

11

PAGE  3

Министерство образования и науки РФ

Федеральное бюджетное государственное
образовательное учреждение

высшего профессионального образования

«Тульский государственный университет»

Политехнический институт

Кафедра "Автоматизированные станочные системы"

Троицкий Д.И.
доцент, к.т.н.

МЕТОДИЧЕСКИЕ УКАЗАНИЯ

ПО ВЫПОЛНЕНИЮ ЛАБОРАТОРНОЙ РАБОТЫ №7

по дисциплине

ИНФОРМАТИКА

Направление подготовки:

230100 Информатика и вычислительная техника

Профиль подготовки:

Системы автоматизированного проектирования

Форма обучения – очная, очно-заочная, заочная

Тула 2011 г.


Рассмотрено на заседании кафедры "Автоматизированные станочные системы"

протокол №1 от "31" августа 2011 г.

Зав. кафедрой________________А.Н. Иноземцев


Содержание

[1]
Динамические массивы

[1.1] Создание динамических массивов

[1.2]  Многомерные динамические массивы

[2] Процедуры и функции

[3] Что такое функция?

[4] Функция: туда и обратно

[5] Процедуры

[6] Передача данных в процедуры

[7] Вложенные процедуры и функции

  1.  
     Динамические массивы

Если у начальника довольное лицо,

значит, вы сделали что-то не так!

Из законов Мэрфи

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

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

  1.  Создание динамических массивов

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

TYPE TA=ARRAY OF INTEGER;

VAR a:TA;

Для динамических массивов размерность вообще не указывается.

Первоначальное задание или изменение размеров динамического массива выполняется функцией  SetLength(массив, число_элементов). Функция Length(массив) (та же, что работает с текстовыми строками) возвращает текущее количество элементов в массиве, функции Low(массив) и High(массив) – нижнее и верхнее значения индекса массивов соответственно. Нумерация индексов всегда  начинается с нуля. Процедура Finalize(массив) удаляет массив целиком из памяти и делает его длину нулевой.

Пусть нам надо прочесть из файла неизвестное заранее количество текстовых строк и занести их в массив. Делается это так:

TYPE TA=ARRAY OF STRING;

VAR a:TA; f:TEXTFILE; i:byte;

BEGIN

ASSIGNFILE(f,'1.TXT');

RESET(f);

// цикл до конца файла

 WHILE NOT(EOF(f)) DO

 BEGIN

   // увеличиваем длину массива на единицу

  SetLength(a,Length(a)+1);

  // считываем строку в последний элемент массива

  READLN(f,a[Length(a)-1])

 END;

 CLOSEFILE(f)

Обратите внимание на строку READLN(f,a[Length(a)-1]). Функция Length(a) возвращает число элементов в массиве. Оно на единицу больше индекса последнего элемента. Так, при длине массива в три элемента индексы имеют вид 0,1,2. Поэтому необходимо вычитать единицу для получения индекса последнего элемента.

Теперь выведем содержимое динамического массива в компонент Memo1:

Memo1.Lines.Clear;

FOR i:=Low(a) TO High(a) DO

 Memo1.Lines.Add(a[i]);

  1.   Многомерные динамические массивы

 

Создадим динамический массив в виде матрицы 53 вещественных числа:

TYPE TA=ARRAY OF ARRAY OF REAL;

VAR a:TA;

SetLength(a,5,3);

a[0,0]:=10.0;

Многомерный динамический массив описывается аналогично статическому с той лишь разницей, что индексы по размерностям (число строк и столбцов) в операторе TYPE не указываются. Соответственно в процедуре SetLength задаются два размера: число строк и столбцов.

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

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

Из законов Мэрфи

При написании сколько-нибудь сложных программ они в обязательном порядке разделяются на отдельные "кирпичики" – процедуры и функции. Процедура или функция – это маленькая программа со своими переменными, в которую можно передавать информацию и из которой можно получать результаты. Чем больше таких кирпичиков, тем легче создавать и отлаживать программу. Рекомендуется, чтобы каждая процедура целиком умещалась на экране, т.е. не превышала 20..25 строк текста.

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

ЕСЛИ В ТЕКСТЕ ПРОГРАММЫ ЧТО-ТО ПОВТОРЯЕТСЯ –

ВЫ ЧТО-ТО НЕПРАВИЛЬНО ДЕЛАЕТЕ!

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

  1.  Что такое функция?

Ошибка? Это не ошибка, это системная функция!

Из законов Мэрфи

Сначала рассмотрим функции, поскольку с ними вам уже приходилось сталкиваться. В Delphi предусмотрено много встроенных функций, таких, как SQR(), SQRT(), SIN(), COS() и др. Давайте создадим пользовательскую функцию, которая будет вычислять тангенс угла. Мы хотим, чтобы в любом месте программы в формуле можно было написать TAN(x), а не делить синус на косинус.

Запись TAN(x) является вызовом функции с именем TAN. Сама же функция должна быть где-то описана. По правилам Delphi все объекты в программе описываются до их первого использования. Поэтому глобальные (доступные во всей программе) процедуры и функции описываются в разделе реализации после оператора IMPLEMENTATION.

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

Общий вид описания функции следующий:

FUNCTION имя_функции(арг1:тип; … аргn : тип): тип_возвр_знач;

раздел локальных описаний

BEGIN

 Result := значение

END;

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

  1.  Функция: туда и обратно

Две интересные передачи всегда идут в одно и то же время.

Из законов Мэрфи.

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

a:=StrToFloat(Edit2.Text);

b := Tan(a);

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

FUNCTION Tan(x: REAL):REAL;

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

Все переменные, описанные внутри функции или процедуры, являются ЛОКАЛЬНЫМИ. Это значит, что они никак не связаны с одноименными переменными, описанными в других частях программы. Например:

IMPLEMENTATION 

VAR a: REAL; { глобальная переменная а }

FUNCTION abc(a:REAL):REAL; { локальная переменная а }

BEGIN

END;

В примере в начале всей программы выделяется память под ГЛОБАЛЬНУЮ переменную с именем a. Глобальные переменные можно использовать в любом месте в тексте программы. Они постоянно занимают память. Большое количество глобальных переменных – признак низкой квалификации программиста.

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

В момент вызова функции Tan значение, записанное в скобках после ее имени, будет занесено в локальную переменную a. Например:

x := Tan(2*b+pi);

Сначала вычисляется выражение 2*b+pi, а затем начинает выполняться функция и полученное при вычислении значение заносится в ее локальную переменную а.

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

FUNCTION abc(a:REAL):REAL;

TYPE TA=ARRAY[1..10] OF REAL;

VAR x:REAL;

BEGIN

END;

В приведенном примере в переменную a заносится значение при вызове функции, а переменная x является просто ячейкой памяти. Она никак не связана с другими переменными с именем x, описанными в других местах программы. Аналогично тип данных TA в примере действует (обычно говорят "виден") только до конца текста функции, т.е. до слова END.

После того, как в функции вычислено возвращаемое значение, самое главное – не забыть на самом деле вернуть его. Для возврата значения внутри функции всегда существует переменная с именем Result, а также с именем, совпадающем с именем самой функции. Например, внутри функции Tan живет переменная с именем Tan и типом REAL и переменная Result тоже типа Real (напомним, что тип возвращаемого значения указывается после заголовка функции). Этой-то переменной и нужно присвоить результат вычислений:

FUNCTION Tan(a:REAL):REAL;

BEGIN

Result:=SIN(a)/COS(a)

END;

Очень часто встречается следующая ошибка:

FUNCTION Tan(a:REAL):REAL;

VAR t:REAL;

BEGIN

 t:=SIN(a)/COS(a)

END;

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

ВНУТРИ ФУНКЦИИ ОБЯЗАТЕЛЬНО ДОЛЖНО

ПРИСВАИВАТЬСЯ ЗНАЧЕНИЕ ПЕРЕМЕННОЙ Result

  1.  Процедуры

Если уж вы открыли банку с червями, то единственный способ

снова их запечатать - это воспользоваться банкой большего размера.

Из законов Мэрфи.

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

PROCEDURE имя_процедуры (арг1:тип; … аргn : тип);

раздел локальных описаний

BEGIN

операторы

END;

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

PROCEDURE Stop;

BEGIN

Form1.Close

END;

Вот как выглядит ее вызов:

BEGIN

. . .

 Stop;

. . .

END;

Фактически в язык Delphi мы добавили новый оператор и назвали его Stop.

  1.  Передача данных в процедуры

Две интересные передачи всегда идут в одно и то же время.

Из законов Мэрфи.

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

PROCEDURE ShowMax(a, b : REAL);

VAR r:REAL;

BEGIN

r:=a-b;

 IF r>0 THEN

 Form1.Label1.Caption:= FloatToStr(r)

END;

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

Здесь r – локальная переменная процедуры, она существует только внутри нее. При вызове такой процедуры ей на вход надо подать два числа, например:

ShowMax(10, 2*a-45);

Обратите внимание, что здесь a – совсем другая переменная, не имеющая отношения к переменной a в заголовке процедуры. Значение 10 будет занесено в локальную переменную a,  а вычисленное значение 2*a-45 – в локальную переменную b.

Такой способ передачи данных называется "по значению" (by value). У него есть два недостатка. Во-первых, он позволяет передавать информацию только в одну сторону – из вызывающей программы в процедуру. Во-вторых, при передаче больших объемов данных, скажем, больших массивов, они каждый раз полностью копируются из одной области памяти в другую, на что уходит много ресурсов компьютера.

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

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

PROCEDURE Hypot (a,b:REAL; VAR c:REAL);

VAR h:REAL;

BEGIN

h:= SQR(a)+SQR(b);

c:=SQRT(h)

END;

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

При обращении к процедуре Hypot третьим ее параметром обязательно должно идти имя переменной. Следующая запись правильна:

VAR h:REAL;

. . .

BEGIN

. . .

 Hypot(a+b, 45, h)

Величина гипотенузы будет записана в переменную h.

А так делать нельзя:

Hypot(a+b, 45, h*4)

Выражение h*4 не является именем переменной и в него нельзя записать значение.

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

CONST Nmax=20;

TYPE TA=ARRAY[1..Nmax] OF REAL;

VAR a:TA; i:BYTE; min:REAL;

PROCEDURE FindMin(ar:TA; n:BYTE; VAR min:REAL); 

VAR i:BYTE;

BEGIN

min:=ar[1];

FOR i:=2 TO n DO

IF ar[i]<min THEN

min := ar[i]

END;

BEGIN

FOR i:=1 TO Nmax DO

a[i]:=RANDOM;

FindMin(a,Nmax,min);

Label1.Caption:=FloatToStrF(min,ffFixed,10,4)

END.

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

FUNCTION FindMax(a:ARRAY OF REAL):REAL;

VAR i:WORD;

BEGIN

Result:=a[Low(a)];

FOR i:=Low(a)+1 TO High(a) DO

  IF a[i]>Result THEN

   Result:=a[i]

END;

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

  1.  Вложенные процедуры и функции

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

Правило мытья стеклянной посуды.

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

PROCEDURE abc;

FUNCTION cde:STRING;

BEGIN

END;

BEGIN

END;

Здесь cde – локальная функция внутри процедуры abc.

1 Подобное "двойное назначение" слова VAR в Delphi представляется неудачным и вносит ненужную путаницу.

функцию cde можно вызывать

только здесь!

возможность изменения

параметра c внутри процедуры

выделение памяти под локальную переменную

переменные a, b, r существуют
только здесь!




1. Москвоведение 2007 Рецензенты- Бенку И
2. реферат Основные положения факторного кластерного и дискриминантного анализа
3. Виды речевой деятельности
4. Реферат- Новый канцлер Гельмут Шмидт
5. Развитие внимания младших школьников с нарушением интеллекта на уроках изобразительной деятельности
6. . Задачи учета затрат на производство
7. рока Vn der Grf Genertor
8. Исходные данные Uг
9. ССейфуллина УТВЕРЖДА
10. Общее понятие человека 2
11. Жеребцово ВА
12. реферат дисертації на здобуття наукового ступеня доктора технічних наук Дніпропет
13. Прогнозирование рисков Методы социальноэкономического прогнозирования
14. Тема- Основы уголовного права План- Понятие предмет и метод уголовного права.
15. методичному семінарі з болгарської мови літератури культури та історії який відбудеться 15 16 травня 2014
16. Информатика часть 1 История появления и развития вычислительной техники
17. Реферат- Телекоммуникация.html
18. тема сегодняшнего урока utoCD
19. Роль государства в регулировании ВЭД и перемещении товаров
20. Динамические структуры данных