Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Программирование. Процедурное программирование. Учебное пособие
.pdf
Основные возможности процедурного программирования по работе с числовыми данными
На основании пузырьковой сортировки разработан один из самых
эффективных алгоритмов сортировки – быстрая сортировка (автор Чарльз
Хоар) с вычислительной сложностью O(N*logN). Основание логарифма
в формуле опущено, так как логарифмы по разным основаниям отличаются
константным множителем, который уже входит в понятие «O» большого.
Этот метод сортировки представлен в рекурсивном виде и подробно рассмотрен в п. 1.4.
Сортировка слиянием: набор разделяется на несколько кратных
частей, каждая сортируется отдельно, затем эти упорядоченные наборы
соединяются в один. Например, в случае двух наборов объединение
происходит следующим образом: выбирается и помещается первым
наименьший элемент из двух наборов (для этого необходимо сравнить
наименьшие элементы из обоих наборов), далее процедура продолжается, пока все элементы не будут объединены. Вычислительная сложность:
O(N*logN).
Числовые наборы, используемые в программе, можно получать раз-
личными способами: генерируя набор с использованием датчика случайных чисел, организуя ввод с клавиатуры либо читая их из другого источника (например, текстового файла).
Пример программы № 3
При помощи датчика случайных чисел создать квадратную мат-
рицу, упорядочить строки матрицы в порядке увеличения суммы элементов в них.
Разработка программы
Для хранения матрицы нам потребуется двумерный массив. Объявим
этот тип данных, назовем его TMatrix, и константу N, содержащую порядок матрицы. Объявим переменную-массив M для хранения матрицы
и индексные переменные I и J для организации обращения к ее элементам,
остальные переменные будем добавлять по мере необходимости.
const
N = 4;
type
TMatrix = array[1..N, 1..N] of Integer;
var
M: TMatrix;
I, J: Integer;
По заданию требуется, чтобы матрица содержала случайные целые
числа. Для того чтобы получить случайные значения, воспользуемся стан-
31

Глава 1
дартным оператором Random и последовательно в двойном цикле заполним массив.
Random(Limit);
Возвращает случайное значение из диапазона [0 ... Limit – 1].
Оператор Random может использовать вспомогательный оператор
Randomize, который инициализирует алгоритм генерации случайных чисел.
Randomize;
for I := 1 to N do
for J := 1 to N do
M[I, J] := Random(100);
Выведем полученную матрицу на экран: для этого организуем циклы
по строкам и столбцам матрицы, считая, что первый индекс массива (переменная I) соответствует номеру строки матрицы, а второй (переменная J) –
номеру столбца. Для обеспечения «красивого» вывода данных можно
форматировать вывод, отводя на каждое число заранее определенное количество позиций, которое указывается через двоеточие после имени переменной. Будем выводить элементы одной строки матрицы последовательно, выделяя по 3 позиции на каждый элемент, а при переходе к новой
строке матрицы будем делать перевод строки.
WriteLn('Матрица');
for I := 1 to N do
begin
for J := 1 to N do
Write(M[I, J]:3);
WriteLn;
end;
Далее по заданию требуется упорядочить строки матрицы по сумме
элементов, содержащихся в них. Воспользуемся сортировкой методом выбора. Общая схема алгоритма, как приведено выше, следующая: нужно по
очереди искать и помещать на свои места сначала первую строку, содержащую минимальную сумму из всех строк, затем вторую, содержащую
минимальную сумму из оставшихся строк, и т. д. Реализуется алгоритм
с использованием вложенных циклов, с внешним циклом по номеру строки, поиск которой производится. Алгоритм несколько осложняется тем,
что сравниваются не пары элементов, а суммы по строкам, которые необходимо предварительно вычислить, а также тем, что для обмена строк мес-
32

Основные возможности процедурного программирования по работе с числовыми данными
тами необходимо попарно обменять местами все элементы этих строк, находящиеся на соответствующих местах.
После упорядочения повторно выведем матрицу на экран.
Текст программы полностью приведен в листинге 3.
Листинг 3. Пример программы № 3
program Example3;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
const
N = 4;
type
TMatrix = array[1..N, 1..N] of Integer;
var
M: TMatrix;
I, J, K, Min, Min_Sum, Sum, T: Integer;
begin
SetConsoleOutputCP(1251);
{Заполняем матрицу случайными числами.}
Randomize;
for I := 1 to N do
for J := 1 to N do
M[I, J] := Random(100);
WriteLn('Матрица');
{Выводим матрицу на экран.}
for I := 1 to N do
begin
for J := 1 to N do
Write(M[I, J]:3);
WriteLn;
end;
{Упорядочиваем строки матрицы методом выбора.}
for I := 1 to N - 1 do
begin
Min := I;
{Вычисляем сумму I-й строки и принимаем ее
за первоначальный минимум.}
Min_Sum := 0;
for J := 1 to N do
Min_Sum := Min_Sum + M[I, J];
{Просматривая строки с номерами большими I, отыскиваем
минимум.}
for J := I + 1 to N do
begin
Sum := 0;
for K := 1 to N do
Sum := Sum + M[J, K];
33

Глава 1
if Min_Sum > Sum then
begin
Min_Sum := Sum;
Min := J;
end;
end;
{Если найденная строка отлична от I-й, меняем их местами.}
if Min <> I then
begin
for J := 1 to N do
begin
T := M[I, J];
M[I, J] := M[Min, J];
M[Min, J] := T;
end;
end;
end;
{ Выводим результирующую матрицу на экран. }
WriteLn('Упорядоченная матрица');
for I := 1 to N do
begin
for J := 1 to N do
Write(M[I, J]:3);
WriteLn;
end;
ReadLn;
end.
Результат работы программы
Матрица
63 38 46 55
56 15 4 84
35 20 6 77
9 12 19 24
Упорядоченная матрица
9 12 19 24
35 20 6 77
56 15 4 84
63 38 46 55
Контрольные вопросы и задания
1. Назовите операторы для генерации случайных чисел.
2. Каким образом сгенерировать набор случайных значений так, что-
бы среди них были как положительные, так и отрицательные величины?
Как целые, так и вещественные?
34

Основные возможности процедурного программирования по работе с числовыми данными
3. Приведите несколько простейших алгоритмов сортировки. Укажи-
те их вычислительную сложность.
4. Напишите код, заполняющий матрицу таким образом, чтобы на
элементы главной диагонали принимали значения 2, на двух соседних диагоналях – 1, а остальные элементы матрицы были равны 0.
5. Как объявить трехмерный массив и работать с ним?
1.4. Основные инструменты структурного программирования.
Процедурные типы. Рекуррентность и рекурсия.
Реализация в языке
Процедуры и функции
При конструировании достаточно сложного алгоритма логично раз-
бить его на ряд более простых задач. В этом случае в основном алгоритме
предполагается обращение к вспомогательным алгоритмам, позволяющим решать более простые подзадачи. При реализации таких вспомогательных алгоритмов на языке Delphi их оформляют в виде подпрограмм,
которые в Delphi представлены в виде процедур и функций. Подпрограммы, в свою очередь, могут разбиваться на более мелкие подпрограммы
нижнего уровня.
Подпрограмма представляет собой относительно самостоятельный
фрагмент программы, оформленный особым образом и снабженный именем. По структуре (используемым разделам) подпрограмма может напоминать программу. В ней могут быть собственные переменные, собственные описания типов и даже собственные функции и процедуры.
Процедуры и функции в программе оформляют в виде отдельных
блоков, каждый из которых начинается ключевым словом (procedure или
function). Эти блоки располагаются в программе перед оператором begin,
начинающим основное тело программы.
Описать подпрограмму – это значит указать ее заголовок и тело.
В заголовке объявляются имя подпрограммы и формальные параметры,
если они есть. Формальными параметры называются потому, что они
служат для представления логики подпрограммы и не несут конкретных
значений. Для функции, кроме того, указывается тип возвращаемого ею
результата.
Отличие функции от процедуры обычно заключается в том, что ре-
зультатом исполнения операторов, образующих тело функции, всегда является некоторое единственное значение, поэтому вызов функции можно
использовать в выражениях наряду с переменными и константами.
35

Глава 1
Общая форма записи заголовка подпрограммы:
function <имя> [(<список формальных параметров>)]: <тип
результата>;
procedure <имя> [(список формальных параметров)];
<Имя> – правильный идентификатор.
<Список формальных параметров> включает в себя параметры дан-
ной подпрограммы, и если в списке формальных параметров нет необходимости, то он может отсутствовать. Если же он есть, то в нем должны
быть перечислены имена формальных параметров и их типы.
<Тип результата> – тип значения, получаемого после выполнения
функции.
Примеры заголовков подпрограмм
function ArcTan(Phi : Real) : Real;
procedure Output;
За заголовком следует тело подпрограммы, которое, подобно про-
грамме, состоит из раздела описаний и раздела исполняемых операторов.
В разделе описания подпрограммы могут встретиться описания подпрограмм низшего уровня, в которых могут быть описания других подпрограмм, и т. д.
Все объекты, объявленные внутри подпрограммы (типы, константы,
переменные, процедуры и функции), являются локальными по отношению
к подпрограмме и невидимы снаружи подпрограммы. При входе в подпрограмму становятся доступными объявленные в ней имена, но при этом сохраняется доступ ко всем именам, описанным выше по тексту программы
до описания данной подпрограммы. Эти объекты называются глобальными
по отношению к подпрограмме. Имена локальных объектов могут совпадать с именами глобальных объектов, в этом случае локальное имя «закрывает» глобальное.
Любой из формальных параметров подпрограммы может быть одним
из нескольких видов: параметром-значением, параметром-переменной,
параметром-константой, выходным параметром, параметром процедурного типа. В данном учебном пособии будут использоваться только пер-
вые два вида параметров.
Если параметр определен как параметр-значение, то перед вызовом
подпрограммы его фактическое значение копируется во временную память
и передается подпрограмме. Поэтому любые возможные изменения в подпрограмме параметра-значения никак не отразятся на значении фактиче-
36

Основные возможности процедурного программирования по работе с числовыми данными
ского параметра. При вызове подпрограммы параметру-значению могут
соответствовать как переменная, так и произвольное выражение и даже
константа.
Если параметр определен как параметр-переменная, то при вызове
подпрограмме передается сама переменная, а не ее копия (фактически
в этом случае подпрограмме передается адрес переменной). Изменение параметра-переменной приводит к изменению самого фактического параметра в вызывающей программе. При описании перед формальным параметром-переменной необходимо ставить зарезервированное слово var. При
вызове подпрограммы параметру-переменной должен соответствовать
фактический параметр в виде переменной нужного типа.
Упоминание имени подпрограммы в тексте программы называется
вызовом этой подпрограммы. Необходимо помнить, что при вызове подпрограммы имена фактических параметров (которые замещают формальные параметры) могут как отличаться от имен соответствующих формальных параметров, так и совпадать с ними, но при этом их количество, взаимный порядок и тип должны быть четко соблюдены.
В отличие от процедуры, где выходное значение присваивается вы-
ходному параметру, в функции выходное значение должно быть присвоено
имени функции или обобщенной переменной Result.
Компиляцией подпрограмм можно управлять с помощью специаль-
ных директив, которые указываются либо после заголовка подпрограммы
(локальный вариант, действует только для указанной подпрограммы), либо в специальном оформлении директивы (в фигурных скобках, в которых первым стоит символ доллара ($)). В этом случае директива действует на все подпрограммы в программе, пока не будет отменена другой директивой (блоковый вариант). Одним из примером такого управления
является построение косвенной рекурсии с использованием директивы
forward.
Пример программы № 4
С клавиатуры вводятся координаты вершин двух треугольников.
Необходимо сравнить площади введенных треугольников.
Приведем три варианта решения.
Вариант № 1. Процедура без параметров
В листинге 4.1 приведен пример процедуры Square1, использующей
для вычисления глобальные переменные: A, B, C – длины сторон треугольника и S – вычисленная площадь. Переменная P является локальной.
В этом примере все взаимодействие процедуры осуществляется че-
рез глобальные переменные: перед вызовом Square1 необходимо присво-
37

Глава 1
ить переменным A, B и C необходимые значения, а после работы процедуры площадь вычисленного треугольника оказывается в переменной S.
Листинг 4.1. Первый вариант программы сравнения
площадей треугольников
program Example4_1;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
var
AB1, AC1, BC1, AB2, AC2, BC2 : Real;
S1, S2 : Real;
A, B, C, S: Real;
// Процедура Square без параметров
procedure Square1;
var
P: Real;
begin
// Для вычисления используются глобальные переменные:
P := (A + B + C)/2;
S := Sqrt(P*(P-A)*(P-B)*(P-C));
end;
begin
SetConsoleOutputCP(1251);
WriteLn('Введите стороны треугольника №1: ');
ReadLn(AB1, AC1, BC1);
WriteLn('Введите стороны треугольника №2: ');
ReadLn(AB2, AC2, BC2);
// Присваивание значений глобальных переменных:
A := AB1; B:= BC1; C := AC1;
Square1; // Вызов процедуры для треугольника №1
S1:= S; // Сохранение площади треугольника №1
// Присваивание значений глобальных переменных:
A := AB2; B:= BC2; C := AC2;
Square1; // Вызов процедуры для треугольника №2
S2:= S; // Сохранение площади треугольника №2
if S1 > S2 then
WriteLn('Площадь треугольника №1 больше')
else
WriteLn('Площадь треугольника №2 больше');
ReadLn;
end.
Этот способ использования процедур не только неудобен из-за
большого числа операторов присваивания, которые до обращения к процедуре определяют значения переменных A, B и C, но и не поощряется, так
38

Основные возможности процедурного программирования по работе с числовыми данными
как работает с глобальными переменными и не способствует коллективной
разработке программ. Излишняя зависимость кода подпрограмм от глобальных объектов может привести к появлению трудновыявляемых ошибок времени выполнения программы.
Вариант № 2. Процедура с параметрами
В листинге 4.2 приведен второй вариант программы, использующей
для вычисления площади процедуру Square2, имеющую формальные параметры. Это позволяет избавиться в программе от лишних переменных
и лишних операторов присваивания.
Переменные, указанные в скобках (A, B, C, S), – это формальные па-
раметры. При выполнении программы в момент обращения к процедуре
они заменяются фактическими параметрами: первый формальный параметр заменяется первым фактическим параметром, второй формальный
параметр – вторым фактическим и т. д.
В примере A, B, C – это формальные параметры-значения, а S – это
формальный параметр-переменная.
Листинг 4.2. Второй вариант программы сравнения
площадей треугольников
program Example4_2;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
var
AB1, AC1, BC1, AB2, AC2, BC2 : Real;
S1, S2 : Real;
// Процедура Square2 с параметрами
procedure Square2(A, B, C: Real; var S: Real);
var
P: Real;
begin
// Для вычисления используются глобальные переменные:
P := (A + B + C)/2;
S := Sqrt(P*(P-A)*(P-B)*(P-C));
end;
begin
SetConsoleOutputCP(1251);
WriteLn('Введите стороны треугольника №1: ');
ReadLn(AB1, AC1, BC1);
WriteLn('Введите стороны треугольника №2: ');
ReadLn(AB2, AC2, BC2);
// Вызов процедуры для треугольника №1:
Square2(AB1, AC1, BC1, S1);
// Вызов процедуры для треугольника №2
39

Глава 1
Square2(AB2, AC2, BC2, S2);
if S1 > S2 then
WriteLn('Площадь треугольника №1 больше')
else
WriteLn('Площадь треугольника №2 больше');
WriteLn(S1, ' ', S2);
ReadLn;
end.
Вариант № 3. Использование функции
В листинге 4.3 приведен пример программы, использующей функ-
цию Square3 для вычисления площади треугольника. Функция возвращает
значение в точку вызова, поэтому вызов функции возможен непосредственно в условном операторе. Каждая функция имеет зарезервированную
переменную Result, которой присваивается результат функции.
Листинг 4.3. Третий вариант программы сравнения площадей
треугольников
program Example4_3;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
var
AB1, AC1, BC1, AB2, AC2, BC2 : Real;
function Square3(A, B, C: Real) : Real;
var
P: Real;
begin
P := (A + B + C)/2;
Result := Sqrt(P*(P-A)*(P-B)*(P-C));
end;
begin
SetConsoleOutputCP(1251);
WriteLn('Введите стороны треугольника №1: ');
ReadLn(AB1, AC1, BC1);
WriteLn('Введите стороны треугольника №2: ');
ReadLn(AB2, AC2, BC2);
if Square3(AB1, AC1, BC1) > Square3(AB2, AC2, BC2) then
WriteLn('Площадь треугольника №1 больше')
else
WriteLn('Площадь треугольника №2 больше');
WriteLn(S1, ' ', S2);
ReadLn;
end.
40
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
