LR4-6

advertisement
ТЕМА: Процедуры и функции
Паскаль позволяет структурировать программу, отделив ее
функционально независимые части. Отдельные, функционально
независимые части программы называют подпрограммами (процедурами и
функциями).
Название «подпрограмма» означает, что она подобна и подчинена
программе.
Подпрограммы решают очень важные задачи, значительно облегчая
программирование:
1) избавляют от необходимости многократно повторять в тексте
программы аналогичные фрагменты;
2) улучшают структуру программы, облегчая ее понимание при разборе;
3) повышают
устойчивость
к
ошибкам
программирования
и
непредвиденным последствиям при модификациях.
Подпрограммы могут быть:
1) стандартными, т.е. определенными системой Паскаль;
2) пользовательскими, т.е. разработанными собственно пользователем.
Существует два способа объединения подпрограмм и программ:
1) текст подпрограмм может быть приведен в разделе описаний
использующей их программы до слова begin, с которого начинается
тело самой программы (это важно!);
2) подпрограммы группируются в отдельных файлах, имеющих
специальную структуру – модулях. Для того чтобы основная программа
могла использовать модуль, он должен быть подключен к основной
программе.
Первый способ используется, когда программа в целом не слишком
велика, а ее подпрограммы, по-видимому, не будут использованы в других
программах.
Второй способ желателен для тех программ, которые составляют Ваш
технологический задел по программированию и могут использоваться в
других программах. Кроме того, оформление отдельных модулей
желательно для больших программ, когда текст становится неудобным для
восприятия.
С одной стороны, вопрос о том, какие частные алгоритмы должны
быть вынесены в подпрограммы, во многом определяется привычками
программиста. С другой стороны, огромное количество разработанных
программ позволяет указать на типичные ситуации и сформулировать
общие принципы выделения подпрограмм:
 Когда Вы несколько раз перепишете в программе одни и те же
последовательности команд, необходимость введения подпрограммы
приобретет характер острой внутренней потребности.
 Иногда слишком много мелочей закрывает главное. Полезно убрать в
подпрограмму подробности, заслоняющие смысл основной программы.
1
 Полезно разбить длинную программу на составные части – просто как
книгу разбивают на главы. При этом основная программа становится
похожа на оглавление.
 Бывают сложные частные алгоритмы. Полезно отладить их отдельно в
небольших тестирующих программах. Включение программ с
отлаженными алгоритмами в основную программу будет легким, если
они оформлены как подпрограммы.
 Все, что Вы сделали хорошо в одной программе, Вам захочется
перенести в новые. Для повторного использования частей программы
лучше сразу выделять полезные алгоритмы в подпрограммы.
Структура текста подпрограммы соответствует структуре текста
основной программы:
<заголовок подпрограммы>;
<раздел описаний>;
begin
<тело подпрограммы>
end;
Следует обратить внимание на два отличия в описании основной
программы и подпрограммы:
1) подпрограмма начинается с заголовка, содержащего имя
подпрограммы, передаваемые в нее и возвращаемые от нее
параметры. Заголовок подпрограммы отличается от заголовка
основной программы;
2) подпрограмма заканчивается точкой с запятой, а не точкой.
Чем отличаются процедуры и функции?
И процедура, и функция – подпрограмма, которая создается для
выделения в отдельный завершенный логический блок некоторого
вспомогательного алгоритма. Обычно функция используется в том случае,
когда результатом подпрограммы должна быть единственная скалярная
(простая) величина. Отличие между процедурой и функцией проявляется
также при вызове их из основной программы.
Заголовки процедуры и функции имеют вид:
Procedure <имя_процедуры> (<список формальных параметров>);
Function <имя_функции> (<список формальных параметров>): <тип
результата>;
Список формальных параметров – это имена переменных с указанием
их типов, над которыми подпрограмма осуществляет действия.
Пример заголовков процедуры и функции:
Procedure primer1 (x, y: real; z: integer);
Function primer2 (n, m: byte): integer;
Вызов подпрограммы происходит при каждом употреблении ее имени
в основной программе. При вызове подпрограммы начинают выполняться
2
ее операторы до завершающего слова end или специального выхода из
подпрограммы – exit. После выхода из подпрограммы управление
передается команде, следующей за обращением к подпрограмме.
Отличия процедуры от функции связаны со способом вызова.
Для вызова процедуры приводится ее имя и в скобках приводится
список передаваемых и получаемых параметров. Вызов процедуры –
оператор (это важно!).
Вызов функции производится по ее имени и списку параметров, но, в
отличие от процедуры, результат функции имеет определенное значение,
поэтому функции используются не как операторы, а как выражения или
операнды в выражениях (это важно!). Для того чтобы функция получила
численное значение, в теле функции необходимо присвоить ей это
значение.
Пример обращения к процедуре и функции:
Primer1 (sin(2), k, 3); {обращение к процедуре, используется как
оператор}
F:= primer2 (i, 2*j); {обращение к функции, используется как
операнд выражения}
При вызове подпрограммы (процедуры или функции) после ее имени
в скобках указываются фактические параметры. Фактическими
параметрами могут быть как конкретные значения, так и переменные или
даже результат выражения. Последовательность фактических параметров,
их количество и их тип должны точно совпадать с формальными
параметрами подпрограммы. Значения фактических параметров на момент
обращения к подпрограмме должны быть определены.
Передача параметров по ссылке и по значению
При передаче параметров по значению в подпрограмме создаются
переменные, в соответствии с объявлениями в заголовке. Эти переменные
существуют только на время работы подпрограммы.
При вызове процедуры фактические параметры, передаваемые по
значению, могут быть записаны как константы, переменные или
выражения.
В начале выполнения подпрограммы копии значений этих констант,
переменных и выражений присваиваются временным переменным
подпрограммы. Когда подпрограмма завершается, используемые в ней
переменные не сохраняются. Это значит, что передача параметров по
значению имеет смысл для передачи данных в подпрограмму, но не для
передачи полученных результатов из нее.
Пример описания формальных параметров, передаваемых по
значению:
Procedure primer (x, y: integer; z: real);
При передаче параметров по ссылке основная программа передает в
подпрограмму не значение переменной, а ссылку на нее, следовательно,
память под передаваемую по ссылке переменную не отводится.
3
Подпрограмма, производя некоторые действия с переменной, принявшей
ссылку на место памяти основной программы, где расположена
переменная, в действительности производит действия с переменной
основной программы. Поэтому после завершения процедуры изменения,
совершенные с переменной основной программы, сохраняются. Этот
механизм используется для получения результатов от подпрограммы.
При вызове процедуры параметры, передаваемые по ссылке, не могут
быть заданы ни константой, ни выражением, т.к. они не имеют адреса для
передачи. Параметры, передаваемые по ссылке, при вызове процедуры
задаются переменной.
В заголовке процедуры список параметров, принимающих значения
по ссылке, начинается служебным словом var.
Пример описания формальных параметров, передаваемых по ссылке:
Procedure primer1 (var k,l: byte; var d: integer);
Решение задачи с использованием подпрограмм
Задача: треугольник задан координатами своих вершин. Составить
программу вычисления его площади.
Решение этой задачи удобно представить в виде следующих этапов:
1. Ввод последовательно координат трех вершин: x1, y1, x2, y2, x3, y3.
2. Вычисление длины первой стороны
3. Вычисление длины второй стороны
4. Вычисление длины третьей стороны
5. Вычисление площади по формуле Герона
6. Вывод на экран полученного значения площади.
Из приведенного выше плана решения задачи видно, что в пунктах 2-4
будут выполняться одни и те же действия только с разными координатами
вершин. Удобно оформить эти вычисления в виде подпрограммы. Так как
длина стороны – это вещественное число, то ее можно вычислять с
помощью подпрограммы-функции. При этом для начала можно продумать
лишь название функции, ее параметры и тип результата, а детали
реализации записать чуть позже. Иначе говоря, следует пока написать
«пустую» функцию, чтобы понять для начала ход решения основной
задачи.
Итак, пусть наша функция называется storona. Для вычисления
стороны треугольника нужно передать в подпрограмму координаты двух
вершин. Пусть формальные параметры называются a1, b1, a2, b2 и имеют
вещественный тип (real). Тип результата функции также будет
вещественным.
Тогда начальный вариант программы будет выглядеть следующим
образом:
Program treugolnik;
Var
S, a, b, c, p: real; {описываем переменные для вычисления площади
(S), сторон (a, b, c), периметра (p)}
4
X1, y1, x2, y2, x3, y3: real; {описываем переменные – координаты
вершин}
Function storona (a1, b1, a2, b2: real): real;
{заголовок функции, в
которой будет вычисляться длина стороны треугольника}
Begin
End; {конец функции. Пока тело функции пусто, детали вычислений
запишем чуть позже. Зато к этой функции уже можно
обращаться из основной программы}
Begin {начало основной программы}
Writeln (‘Введите координаты первой вершины’);
Readln (x1, y1);
Writeln (‘Введите координаты второй вершины’);
Readln (x2, y2);
Writeln (‘Введите координаты третьей вершины’);
Readln (x3, y3);
A:= storona (x1, y1, x2, y2); {вычисляем длину первой стороны}
B:= storona (x2, y2, x3, y3); {вычисляем длину второй стороны}
C:= storona (x3, y3, x1, y1); {вычисляем длину третьей стороны}
P:= a+ b+ c; {вычисляем периметр}
S:= sqrt(p/2*(p/2-a)*(p/2-b)*(p/2-c));
Writeln (‘площадь треугольника равна:’, s);
End.
После того, как в основной программе выделены подзадачи, продуман
план решения, решен основной вопрос, какие данные передаются в
подпрограмму и что должно быть получено в результате ее работы, можно
детально продумать алгоритм работы подпрограммы.
Для вычисления длины стороны в функции можно описать локальную
(определенную только внутри функции) переменную вещественного типа,
пусть она называется d.
Function storona (a1, b1, a2, b2: real): real;
Var d: real; {описание переменной, которая будет использоваться
исключительно внутри функции}
Begin
D:= sqrt(sqr(a1- a2) +sqr(b1-b2));
Storona:= d; {обязательный в теле функции оператор присваивания,
когда с именем функции связывается вычисленное значение}
End;
Вот теперь наша задача полностью решена.
Эту же задачу можно решить с использованием подпрограммыпроцедуры. Начинать решение задачи рекомендуется так же, как и в
предыдущем случае. Сначала определить название процедуры,
передаваемые в нее параметры, способ получения результата из
процедуры. Тело процедуры пока можно сделать пустым. Затем написать
5
основную программу, в которой определить точки обращения к процедуре
и значения фактических параметров.
Пусть наша процедура называется dlina. Для вычисления длины
стороны треугольника в процедуру необходимо передать значения
координат двух вершин, поэтому в списке формальных параметров в
заголовке процедуры нужно описать 4 параметра-значения вещественного
типа: a1, b1, a2, b2. Для передачи полученного значения в основную
программу нужно описать в заголовке параметр-переменную,
принимающий ссылку, назовем этот параметр d (необходимо помнить, что
в заголовке процедуры перед этим параметром ставится служебное слово
var).
Тогда начальный вариант программы будет выглядеть следующим
образом:
Program treugolnik;
Var
S, a, b, c, p: real; {описываем переменные для вычисления площади
(S), сторон (a, b, c), периметра (p)}
X1, y1, x2, y2, x3, y3: real; {описываем переменные – координаты
вершин}
Procedure dlina (a1, b1, a2, b2: real; var d: real); {заголовок процедуры,
в которой будет вычисляться длина стороны треугольника}
Begin
End; {конец процедуры. Пока тело процедуры пусто, детали
вычислений запишем чуть позже. Зато к этой процедуре уже
можно обращаться из основной программы}
Begin {начало основной программы}
Writeln (‘Введите координаты первой вершины’);
Readln (x1, y1);
Writeln (‘Введите координаты второй вершины’);
Readln (x2, y2);
Writeln (‘Введите координаты третьей вершины’);
Readln (x3, y3);
dlina (x1, y1, x2, y2, a); {вычисляем длину первой стороны, при этом
x1, y1, x2, y2 будут передавать копии своих
значений в процедуру, а переменная a будет
принимать полученный результат}
dlina (x2, y2, x3, y3, b); {вычисляем длину второй стороны, при этом
x2, y2, x3, y3 будут передавать копии своих
значений в процедуру, а переменная b будет
принимать полученный результат }
dlina (x3, y3, x1, y1, c); {вычисляем длину третьей стороны, при этом
x3, y3, x1, y1 будут передавать копии своих
значений в процедуру, а переменная c будет
принимать полученный результат}
6
P:= a+ b+ c; {вычисляем периметр}
S:= sqrt(p/2*(p/2-a)*(p/2-b)*(p/2-c));
Writeln (‘площадь треугольника равна:’, s);
End.
Обратите еще раз внимание на различие в вызове подпрограммыфункции и подпрограммы-процедуры. Обращение к функции
использовалось в операторе присваивания как выражение, а обращение к
процедуре – это оператор.
Теперь можно наполнить содержанием саму процедуру:
Procedure dlina (a1, b1, a2, b2: real; var d: real);
Begin
D:= sqrt(sqr(a1- a2) +sqr(b1-b2));
End;
Область действия переменных, взаимодействие блоков
В программе может быть описано сколько угодно блоков
(подпрограмм). Внутри этих блоков могут быть описания других блоков.
Важно знать, откуда и какие блоки могут быть вызваны.
«Блок – это дом с зеркальными стенами. Изнутри видно все, что
делается снаружи. Внутрь заглянуть нельзя».
Рассмотрим программу с процедурами различного уровня
вложенности. Мы получим иерархию описаний:
Program osnovn;
Procedure A;
Основная программа
Procedure A1;
Подпрограмма А
……….
Begin…… end; {A1}
Подпрограмма А1
Procedure A2;
………..
Подпрограмма А2
begin ……end; {A2}
begin
Подпрограмма В
………
end; {A}
Подпрограмма В1
procedure B;
procedure B1;
Подпрограмма В2
………
Подпрограмма В21
begin ……. end; {B1}
procedure B2;
procedure B21;
………..
begin ..end; {B21}
begin …….. end; {B2}
begin …………end; {B}
begin {начало основной программы}
………end. {конец основной программы}
7
Подпрограмма любого уровня имеет обычно описание множества
констант, переменных, типов и вложенных подпрограмм низшего уровня.
Считается, что все имена, описанные внутри подпрограммы,
локализуются в ней, т.е. они как бы «невидимы» снаружи подпрограммы.
Таким образом, со стороны операторов, использующих обращение к
подпрограмме, она (подпрограмма) трактуется как «черный ящик», в
котором реализуется тот или иной алгоритм. Все детали этой реализации
скрыты от глаз пользователя и поэтому недоступны ему.
В рассмотренном выше примере из основной программы можно
обратиться к подпрограммам А и В, но нельзя вызвать ни одну из
вложенных в них процедур А1, А2, В1, В2 и В21.
При входе в подпрограмму низшего уровня становятся доступными не
только описанные в ней имена, но и сохраняется доступ ко всем именам
верхнего уровня. Так, например, из подпрограммы В21 мы можем вызвать
подпрограмму А, использовать имена, объявленные в основной программе,
в подпрограмме В, и обратиться к ним.
При взаимодействии подпрограмм одного уровня вступает в действие
основное правило Паскаля: любая подпрограмма перед использованием
должна быть описана. Поэтому из процедуры В можно вызвать процедуру
А. Из процедуры А вызвать В невозможно (точнее такая возможность
появляется только с использованием опережающего описания).
Продолжая образное сравнение, подпрограмму можно уподобить
ящику с непрозрачными стенками и дном, но с полупрозрачной крышей:
из подпрограммы можно «смотреть» только вверх и нельзя вниз; т.е.
подпрограмме доступны только те объекты верхнего уровня, которые
описаны до описания данной подпрограммы. Эти объекты называются
глобальными по отношению к подпрограмме.
Имена локальных переменных могут совпадать с именами глобальных
переменных. Если в подпрограмме описана (локализована) переменная с
тем же именем, что и глобальная, то в этом случае на время действия
подпрограммы локальная переменная «закрывает» глобальную и делает ее
недоступной, т.е. значение глобальной переменной на время действия
подпрограммы «замораживается».
Память для локальных, т.е. описанных в подпрограмме, переменных
выделяется на время действия подпрограммы в специальной области,
называемой
стеком.
При
завершении
подпрограммы
память
освобождается, поэтому все внутренние результаты работы подпрограммы
не сохраняются от одного обращения к другому.
8
Рекурсия
Подпрограммы в Паскале могут обращаться сами к себе. Такое
обращение называется рекурсией.
Для того чтобы такое обращение не было бесконечным, в тексте
подпрограммы должно быть условие, по достижению которого
дальнейшее обращение к подпрограмме не происходит.
Пример.
Рассмотрим математическую головоломку из книги Ж. Арсака
«Программирование игр и головоломок».
Построим последовательность чисел следующим образом: возьмем
целое число i>1. Следующий член последовательности равен i/2, если i
четное, и 3i+1, если i нечетное. Если i=1, то последовательность
останавливается.
Математически конечность последовательности независимо от
начального i не доказана, но на практике последовательность
останавливается всегда.
Применение рекурсии позволило решить задачу без использования
циклов, как в основной программе, так и в процедуре.
Program Arsac;
Var first: word;
Procedure posledov (i: word);
Begin
Writeln (i);
If i=1 then exit;
If odd(i) then posledov (3*i+1) else posledov (i div 2);
End;
Begin
Write (‘введите первое значение’); readln (first);
Posledov (first);
Readln;
End.
Программист разрабатывает программу, сводя исходную задачу к
более простым. Среди этих задач может оказаться и первоначальная, но в
упрощенной форме. Например, для вычисления F(N) может понадобиться
вычислить F(N-1). Иными словами, частью алгоритма вычисления
функции будет вычисление этой же функции.
Алгоритм, который является своей собственной частью, называется
рекурсивным. Часто в основе такого алгоритма лежит рекурсивное
определение.
Пример.
N! = (N-1)!*N, если N=0, то N!= 1
Любое рекурсивное определение состоит из двух частей. Одна часть
определяет понятие через него же, другая часть – через иные понятия.
Пример.
9
2n= 2n-1*2, если n=0, то 2n= 1
Процедура является рекурсивной, если она обращается сама к себе
прямо или косвенно (через другие процедуры).
А
А
В
С
Заметим, что при косвенном обращении все процедуры в цепочке –
рекурсивные.
Все сказанное о процедурах целиком относится и к функциям.
Пример рекурсивной функции вычисления факториала:
Function factorial(N: integer) : longint;
Begin
If N= 0 then
Factorial := 1
Else
Factorial := factorial(N-1) * N
End;
Рекурсия изнутри
Это может показаться удивительным, но самовызов процедуры ничем
не отличается от вызова другой процедуры. Что происходит, если одна
процедура вызывает другую? В общих чертах следующее:
1) в памяти размещаются параметры, передаваемые процедуре (но не
параметры-переменные!);
2) в другом месте памяти сохраняются значения внутренних
переменных вызывающей процедуры;
3) запоминается адрес возврата в вызывающую процедуру;
4) управление передается вызванной процедуре.
Если процедуру вызвать повторно из другой процедуры или из нее
самой, будет выполняться тот же код, но работать он будет с другими
значениями параметров и внутренних переменных. Это и дает
возможность рекурсии.
Пусть рекурсивная процедура Power(X,N,Y) возводит число X в
степень N и возвращает результат Y .
Procedure Power (X: real; N: integer; var Y: real);
Begin
If N=0 then
Y := 1
Else Begin Power(X, N-1,Y);
Y:= Y*X;
End;
End;
10
Проследим за состоянием памяти в процессе выполнения вызова
данной процедуры Power(5,3,Y). Стрелка «» означает вход в процедуру,
стрелка «» означает выход из нее.
X N
Y
Power(5,3,y)
5
3
?
Power(5,2,y)
5
3
X’ N’
5
2
?
X” N”
5
3
5
2
5
1
5
3
5
2
5
1
Power(5,0,y)
5
3
5
2
5
1
Power(5,1,y)
5
3
5
2
Power(5,2,y)
5
3
Power(5,1,y)
Power(5,0,y)
X”’ N”’
5
0
?
?
1
5
25
125
Power(5,3,y)
Число копий переменных, одновременно находящихся в памяти,
называется глубиной рекурсии. Как видно из примера, сначала она растет,
а затем сокращается.
Лабораторная работа №4
Тема: Процедуры и функции
Приступая к решению задач, следует вспомнить, что:
 Для передачи данных в подпрограмму следует использовать
параметры. Глобальные переменные применять не рекомендуется;
 При написании подпрограммы-функции среди ее инструкций
должен быть хотя бы один оператор присваивания вида
<имя_функции>:= выражение;
 Тип каждого фактического параметра (константы, выражения или
переменной) при вызове подпрограммы должен совпадать с типом
формального параметра, указанного в заголовке подпрограммы;
11
 Если в заголовке подпрограммы перед именем формального
параметра не стоит слово var, то при вызове подпрограммы в
качестве фактического параметра можно использовать константу,
переменную или выражение соответствующего типа;
 Если параметр подпрограммы используется для возврата результата
в основную программу, то в заголовке перед ним ставится слово var;
 Если в заголовке подпрограммы перед именем формального
параметра стоит слово var, то при вызове подпрограммы в качестве
фактического параметра можно использовать только переменную
соответствующего типа;
Задание 1
Указание к выполнению: задание выполняется в тетради и
предназначено для отработки навыков правильного описания процедур и
функций и алгоритмов, реализованных в них. Вы можете для выполнения
задания №1 написать программу на компьютере и проверить правильность
работы Вашей процедуры/функции, в этом случае в основной программе
должны быть реализованы ввод исходных данных и вызов
процедуры/функции.
Вариант 1. Написать подпрограмму, которая вычисляет объем цилиндра.
Параметрами функции должны быть радиус и высота цилиндра.
Вариант 2. Написать подпрограмму, которая возвращает максимальную из
двух обыкновенных дробей вида
a
c
и .
b
d
Вариант 3. Написать подпрограмму, которая сравнивает два числа и
возвращает результат сравнения в виде одного из знаков: < , > или =.
Вариант 4. Написать подпрограмму, вычисляющую натуральную степень
числа.
Вариант 5. Написать подпрограмму, вычисляющую целую отрицательную
степень числа.
Вариант 6. Написать подпрограмму, вычисляющую наибольший общий
делитель двух натуральных чисел.
Вариант 7. Написать подпрограмму, вычисляющую проценты от числа.
Вариант 8. Написать подпрограмму, выводящую на экран строку,
состоящую из звездочек. Количество звездочек является параметром
подпрограммы.
Вариант 9. Написать подпрограмму, вычисляющую наименьшее общее
кратное двух натуральных чисел.
Вариант 10. Написать подпрограмму, выводящую на экран строку из
одинаковых символов. Количество символов в строке и выводимый
символ – параметры подпрограммы.
Вариант 11. Написать подпрограмму, вычисляющую значение выражения
q
x p , где x, p, q – параметры подпрограммы.
12
Вариант 12. Написать подпрограмму, вычисляющую минимальную из
двух обыкновенных дробей вида
a
c
и .
b
d
Вариант 13. Написать подпрограмму, вычисляющую сумму делителей
данного натурального числа.
Вариант 14. Написать подпрограмму, вычисляющую площадь кольца.
Радиус внешней и внутренней окружностей – параметры подпрограммы.
Вариант 15. Написать подпрограмму, вычисляющую функцию sign(x):
 1, при_ x  0

sign ( x)  0, при _ x  0
1, при _ x  0

Задание 2
Указание к выполнению: составить программу решения задачи с
использованием подпрограмм.
Вариант 1. Определить, в каком из данных двух целых чисел больше
цифр.
Вариант 2. Два натуральных числа называются «дружественными», если
каждое из них равно сумме всех делителей (кроме самого числа) другого
(например, числа 220 и 284). Найти все пары дружественных чисел,
которые не больше заданного числа N.
Вариант 3. Два простых числа называются «близнецами», если они
отличаются друг от друга на 2 (например, 41 и 43). Напечатать все пары
«близнецов» из отрезка [n, 2n], где n – заданное натуральное число
большее 2.
Вариант 4.
Написать
p
1 1
(1)
 1  
q
2 3
n
n 1
для
программу
заданного
вычисления
n.
Дробь
p
q
должна
суммы
быть
несократимой (p, q – натуральные).
Вариант 5. Натуральное число, в записи которого n цифр, называется
числом Армстронга. Если сумма его цифр, возведенная в степень n, равна
самому числу. Найти все такие числа от 1 до k.
Вариант 6. Найти все натуральные числа, не превосходящие заданного n,
которые делятся на каждую из своих цифр.
Вариант 7. Составить программу для нахождения числа из интервала [M,
N], имеющего наибольшее количество делителей.
13
Вариант 8. Для последовательности
программу,
вычисляющую
k-й
a1  1 ,
член
1
1  an
a n 1  a n 
составить
последовательности
в
виде
3
19
обыкновенной несократимой дроби. Например, a2  , a3  .
2
10
Вариант 9. Написать программу, которая находит и выводит на печать все
четырехзначные числа вида abcd , для которых выполняется условие
ab  cd  a  b  c  d .
Вариант 10. На части катушки с автобусными билетами номера
шестизначные. Составить программу, определяющую количество
счастливых билетов на катушке, если меньший номер билета – N, больший
– M (билет является счастливым, если сумма первых трех его цифр равна
сумме последних трех цифр).
Вариант 11. Написать программу, определяющую сумму n-значных чисел,
содержащих только нечетные цифры.
Вариант 12. Составить программу разложения числа на простые
множители. Например, 200=23 52.
Вариант 13. Из заданного числа вычли сумму его цифр. Из результата
вновь вычли сумму его цифр и т.д. Через сколько таких действий
получится ноль?
Вариант 14. Дано четное число n>2. Проверить для него гипотезу
Гольдбаха: каждое четное n представляется в виде суммы двух простых
чисел.
Вариант 15. Написать программу вычисления суммы
для заданного n. Дробь
p
1 1
1
 1  
q
2 3
n
p
должна быть несократимой (p, q – натуральные).
q
Задание 3
Указания к выполнению: составить программу решения задачи с
использованием функций нахождения факториала и числа сочетаний из n
по m Cnm 
n!
.
m!(n  m)!
n
Вариант 1. Вычислить выражение для заданных n, x: y   Cni * xi
i 1
Вариант 2. Вычислить выражение для заданных n, m, p, k: y 
k
Вариант 3. Вычислить выражение для заданных n, k: y   Cnm
m 1
2k
Вариант 4. Вычислить выражение для заданного k: y   Cnk
nk
14
Cmp * Cnkmp
.
Cnk
n
Вариант 5. Вычислить выражение для заданных n, x, y: z   Cnk * x k * y n  k
k 0
n
1
k
k 1 Cn
Вариант 6. Вычислить выражение для заданного n: y  
xk
Вариант 7. Вычислить выражение для заданных n, x: y   k
k 1 Cn
2k
1
Вариант 8. Вычислить выражение для заданного k: y   k
n  k Cn
n
Вариант 9. Вычислить выражение для заданных n, x, a: y 
ndiv2
C
k 1
Вариант 10. Вычислить выражение для заданных n, x: y 
k
n
( x  a) k
xk
 k
k  ndiv2 Cn
n
C2kn
k
k 1 Cn
n
Вариант 11. Вычислить выражение для заданного n: y  
xk
k
k 1 C2 n
n
Вариант 12. Вычислить выражение для заданных x, n: y  
(1) k
k
k 1 Cn
n
Вариант 13. Вычислить выражение для заданного n: y  
(1) k x k
Cnk
k 1
n
Вариант 14. Вычислить выражение для заданных n, x: y  
Вариант 15. Вычислить выражение для заданных n, x, a: y 
( x  a) k

Cnk
k 1
ndiv2
Контрольные вопросы по данной теме
1. Преимущества процедурного программирования
2. Подпрограммы и пошаговая детализация
3. Структура подпрограмм на Паскале. Подпрограммы-процедуры и
подпрограммы-функции
4. Формальные и фактические параметры. Передача параметров по
значению и по ссылке
5. Область действия переменных, локальные и глобальные переменные.
Взаимодействие блоков
6. Рекурсивные подпрограммы
7. *Внешние подпрограммы
8. *Размещение параметров в стеке. Активная точка программы
15
Тема: Массивы
Понятие структуры
До сих пор мы работали с простыми типами данных – логический
(boolean), целый (integer, word, byte, longint), вещественный (real),
символьный (char). Любой алгоритм можно запрограммировать с помощью
этих четырех базовых типов. Но для обработки информации о
многообразном реальном мире требуются данные, имеющие более
сложное строение. Такие сложные конструкции, основанные на
простейших скалярных типах, называются структурами. Структура –
некоторый составной тип данных, составленный из базовых
скалярных. Если структура не изменяет своего строения на протяжении
всего выполнения программы, в которой она описана, то такую структуру
называют статической.
Массив – однородная совокупность элементов
Самой распространенной структурой, реализованной практически во
всех языках программирования, является массив.
Массивы состоят из ограниченного числа компонент, причем все
компоненты массива имеют один и тот же тип, называемый базовым.
Структура массива всегда однородна. Массив может состоять из элементов
типа integer, real или char, либо других однотипных элементов. Из этого,
правда, не следует делать вывод, что компоненты массива могут иметь
только скалярный тип.
Другая особенность массива состоит в том, что к любой его
компоненте можно обращаться произвольным образом. Что это значит?
Программа может сразу получить нужный ей элемент по его порядковому
номеру (индексу).
Индекс массива
Номер элемента массива называется индексом. Индекс – это
значение порядкового типа, определенного, как тип индекса данного
массива. Очень часто это целочисленный тип (integer, word или byte), но
может быть и логический и символьный.
Описание массива в Паскале. В языке Паскаль тип массива задается
с использованием специального слова array (англ. – массив), и его
объявление в программе выглядит следующим образом:
Type <имя_типа>= array [ I ] of T;
где I – тип индекса массива, T – тип его элементов.
Можно описывать сразу переменные типа массив, т.е. в разделе
описания переменных:
Var a,b: array [ I ] of T;
16
Обычно тип индекса характеризуется некоторым диапазоном
значений любого порядкового типа : I1 ..In. Например, индексы могут
изменяться в диапазоне 1..20 или ‘a’..’n’.
При
этом
длину
массива
характеризует
выражение:
ord(In)-ord(I1)+1.
Вот, например, объявление двух типов: vector в виде массива из 10
целых чисел и stroka в виде массива из 256 символов:
Type
Vector=array [1..10] of integer;
Stroka=array [0..255] of char;
С помощью индекса массива можно обращаться к отдельным
элементам любого массива, как к обычной переменной: можно получать
значение этого элемента, отдельно присваивать ему значение,
использовать его в выражениях.
Опишем переменные типа vector и stroka:
Var a: vector;
c: stroka;
далее в программе мы можем обращаться к отдельным элементам массива
a или c. Например, a[5]:=23; c[1]:=’w’; a[7]:=a[5]*2; writeln(c[1], c[3]).
Вычисление индекса массива
Индекс массива не обязательно задавать в явном виде. В качестве
индекса массива можно использовать переменную или выражение,
соответствующее
индексному типу. Иначе говоря, индексы можно
вычислять.
Этот механизм – весьма мощное средство программирования. Но он
порождает распространенную ошибку: результат вычислений может
оказаться за пределами интервала допустимых значений индекса, то есть
будет произведена попытка обратиться к элементу, которого не
существует. Эта типичная ошибка называется «выход за пределы
массива».
Например:
Program primer_error;
Type
vector=array [1..80] of word;
var
n: integer;
a: vector;
begin
n:=45; a[n*2]:=25;
end.
Хотя данная программа полностью соответствует синтаксису языка,
и транслятор «пропустит» ее, на стадии выполнения произойдет ошибка
17
выхода за пределы массива. При n=45 выражение n*2=90, компьютер
сделает попытку обратиться к элементу массива a[90], но такого элемента
нет, поскольку описан массив размерностью 80.
Будем считать, что хорошая программа должна выдавать
предупреждающее сообщение в случае попытки обращения к
несуществующим элементам массива. Не лишним будет проверять
возможный выход как за правую, так и за левую границы массива, ведь не
исключено, что в результате вычисления значения выражения получится
число, находящееся левее границы массива.
Из всего этого следует сделать вывод: программисту надо быть
очень аккуратным при работе с индексами массива.
Основные действия с массивами
Как известно, определение типа данных означает ограничение области
допустимых значений, внутреннее представление в ЭВМ, а также набор
допустимых операций над данными этого типа. Мы определили тип
данных массив. Какие же операции определены над этим типом данных?
Единственное действие, которое можно выполнять над
массивами
целиком, причем только при условии, что массивы однотипны, – это
присваивание. Если в программе описаны две переменные одного типа,
например,
Var
a,b: array [1..10] of real;
то можно переменной a присвоить значение переменной b (a:= b). При
этом каждому элементу массива a будет присвоено соответствующее
значение из массива b. Все остальные действия над массивами
производятся поэлементно (это важно!).
Ввод массива
Для того чтобы ввести значения элементов массива, необходимо
последовательно изменять значение индекса, начиная с первого до
последнего, и вводить соответствующий элемент. Для реализации этих
действий удобно использовать цикл с заданным числом повторений, т.е.
простой арифметический цикл, где параметром цикла будет выступать
переменная – индекс массива. Значения элементов могут быть введены с
клавиатуры или определены с помощью оператора присваивания.
Например (рассмотрим фрагмент программы),
Var
A: array [1..10] of integer;
I : byte; {переменная I вводится как индекс массива}
Begin
For i:=1 to 10 do
Readln (a[i]); {ввод i-го элемента производится с клавиатуры}
18
Рассмотрим теперь случай, когда массив заполняется автоматически
случайными числами, для этого будем использовать функцию random(N).
Var
A: array [1..10] of integer;
I: byte; {переменная I вводится как индекс массива}
Begin
For i:=1 to 10 do
A[i]:= random(10); {i-му элементу массива присваивается
«случайное» целое число в диапазоне от 0 до 10}
Вывод массива
Вывод массива осуществляется также поэлементно, в цикле, где
параметром выступает индекс массива, принимая последовательно все
значения от первого до последнего.
Например,
Var
A: array [1..10] of integer;
I: byte; {переменная I вводится как индекс массива}
Begin
.............
For i:=1 to 10 do
Wtite (a[i],’ ‘); {вывод массива осуществляется в строку, после
каждого элемента печатается пробел}
Вывод можно осуществить и в столбик с указанием
соответствующего индекса. Но в таком случае нужно учитывать, что при
большой размерности массива все элементы могут не поместиться на
экране и будет происходить скроллинг, т.е. при заполнении всех строк
экрана будет печататься очередной элемент, а верхний смещаться за
пределы экрана.
Например,
Var
A: array [1..10] of integer;
I: byte; {переменная I вводится как индекс массива}
Begin
...................
For i:=1 to 10 do
Writeln (‘a[‘, i,’]=’, a[i]); {вывод элементов массива в столбик}
На экране мы увидим, к примеру, следующие значения:
a[1]=2
a[2]=4
a[3]=1 и т.д.
Пример решения задачи с использованием массивов
19
Задача: даны два n-мерных вектора. Найти сумму этих векторов.
Решение задачи:
1. Входными данными в этой задаче будут являться два одномерных
массива. Размер этих массивов может быть произвольным, но
определенным. Т.е. мы можем описать заведомо большой массив, а в
программе определить, сколько элементов реально будет
использоваться.
Элементы
этих
массивов
могут
быть
целочисленными.
Тогда
описание
будет
выглядеть следующим образом:
var a,b: array [1..100] of integer;
2. Выходными данными будут элементы результирующего массива,
назовем его c. Тип результирующего массива также должен быть
целочисленным.
3. Кроме трех массивов нам потребуется переменная – параметр цикла
и индекс массива, назовем ее i, а также переменная n для
определения количества элементов в каждом массиве.
4. Ход решения задачи:
- определим количество элементов (размерность) массивов, введем
значение n;
- введем массив a;
- введем массив b;
- в цикле, перебирая значения индекса i от 1 до n, вычислим
последовательно значения элементов массива c по формуле:
c[i]=a[i]+b[i];
- выведем на экран полученный массив.
Текст программы:
Program summa;
Var a, b, c: array [1..100] of integer; I, n: byte;
Begin
Write(‘введите размерность массивов:’);
Readln(n);
For i:=1 to n do
Readln (a[i]); {ввод массива a}
For i:=1 to n do
Readln (b[i]); {ввод массива b}
For i:=1 to n do
C[i]:=a[i]+b[i]; {вычисление суммы массивов}
For i:=1 to n do
write (c[i],’ ‘); {вывод массива с}
end.
20
Вопросы для повторения
1. В чем отличие простых и структурированных типов данных? К
каким типам данных относится массив?
2. Что называется массивом?
3. Как в Паскале описываются переменные типа массив?
4. Может ли массив содержать один элемент? А ни одного?
5. Можно ли во время выполнения программы изменить размер
массива (количество элементов, определенное во время описания)?
6. Верно ли, что тип элементов массива может быть любым?
7. Могут ли в одном массиве храниться элементы:
1, 2.3, ‘а’, -5.23, 0, ‘слово’, -2 ?
8. Может ли типом индекса быть тип integer или real?
9. Какие из приведенных описаний являются неправильными и
почему?
 var a: array [1..20] of integer;
 type myarray=array [1..20];
var b: myarray;
 var sd: array [1..n] of integer;
 var dd: array[1] of integer;
10.Сколько элементов в каждом из следующих массивов:
 var mb: array [2..20] of integer;
 type myarray1= array [0..8] of integer;
myarray2= array [-5..5] of integer;
var aa: myarray1;
bb: myarray2;
11.Используя описание массивов из предыдущего пункта, определить,
какие
из
приведенных
обращений
к
элементам
массивов неправильные и почему?
 mb[3];
 aa[0];
 myarray1[2];
 bb[0];
 aa[6];
 bb[-3];
 bb[6];
 aa[-3]
21
Лабораторная работа №5
Тема: Одномерные массивы
Задание 1
Задание: составить программу решения задачи.
Указание к выполнению: выполнить основные этапы решения
задачи самостоятельно, ввод и вывод массива желательно оформить в виде
процедур.
Вариант 1. Дан массив натуральных чисел. Найти сумму элементов,
кратных данному числу K.
Вариант 2. В целочисленной последовательности есть нулевые элементы.
Создать массив из номеров этих элементов.
Вариант 3. Дан массив действительных чисел, размерность которого N.
Посчитать, сколько в нем отрицательных, положительных и нулевых
элементов.
Вариант 4. Дана последовательность действительных чисел a1, a2, ..an.
Выяснить, будет ли она возрастающей.
Вариант 5. Дана последовательность натуральных чисел a1, a2, ..an.
Составить массив из четных чисел этой последовательности. Если таких
чисел нет, то вывести сообщение об этом.
Вариант 6. Задана последовательность из N вещественных чисел.
Определить, сколько среди них чисел меньших К, равных К и больших К.
Вариант 7. Дана последовательность чисел, среди которых имеется один
нуль. Вывести на печать все числа до нуля включительно.
Вариант 8. Даны целые числа a1, a2, ..an. Указать те из них, для которых ai
 i.
Вариант 9. При поступлении в вуз абитуриенты, получившие двойку на
первом экзамене, ко второму не допускаются. В массиве A[n] записаны
оценки, полученные на первом экзамене. Посчитать, сколько человек не
допущено ко второму экзамену.
Вариант 10. Задана последовательность N вещественных чисел.
Вычислить сколько раз меняется знак в данной последовательности.
Вариант 11. Задана последовательность N вещественных чисел.
Вычислить n | x1  x2   xn | (среднее геометрическое).
Вариант 12. Задана последовательность N целых чисел. Вычислить сумму
элементов, порядковые номера которых совпадают со значением этого
элемента.
Вариант 13. Определить количество элементов последовательности
натуральных чисел, кратных числу M, заключенных в промежутке от L до
N.
22
Вариант 14. Определить, сколько процентов от всего количества
элементов последовательности целых чисел составляют нечетные
элементы.
Вариант 15. Даны натуральные числа a1, a2, ..an. Указать те из них, у
которых остаток от деления на M равен L (0 L M-1).
Задание 2
Задание: составить программу решения задачи.
Указание к выполнению: выполнить все этапы решения задачи
самостоятельно, использовать процедуры ввода и вывода массивов,
выделить в задаче вспомогательные алгоритмы и оформить их в виде
подпрограмм.
Рекомендации к решению задач
Удаление элемента из массива. Удалить из массива максимальный
элемент, если все элементы различные.
Решение: Приведем общие рассуждения.
Для того чтобы решить данную задачу, необходимо:
 найти номер максимального элемента k;
 сдвинуть все элементы, начиная с k-го, на один элемент влево;
 последнему элементу присвоить значение 0.
Рассмотрим на конкретном примере. Пусть дан одномерный массив из
целых чисел, состоящий из 10 элементов:
6, 3, 4, 7, 11, 2, 13, 8, 1, 5.
Номер максимального элемента равен 7 (k=7), то есть, начиная с 7-го
элемента, будем сдвигать элементы на один влево: 7-му элементу
присвоим значение 8-го, 8-му присвоим значение 9-го, а
9-му присвоим значение 10-го, на этом сдвиг заканчивается. Таким
образом, сдвиг начинается с k-го элемента и идет до (n-1)-го (где n – это
количество элементов в массиве). После этого последнему элементу
присвоим значение 0, тогда массив будет следующим:
6, 3, 4, 7, 11, 2, 8, 1, 5, 0.
Замечание: при удалении элемента из массива размерность массива не
меняется, чтобы последний элемент не выводился, необходимо выводить
уже не n элементов, а на 1 меньше.
Удаление нескольких элементов из массива. Удалить из массива все
элементы, значение которых равно максимальному.
Решение:
Когда необходимо удалять несколько элементов, то лучше всего это
делать с конца массива, так как иначе нужно будет снова возвращаться к
23
элементу с номером, который только что удаляли (это случается тогда,
когда подряд стоят два максимальных элемента, если первый удалим, то на
его место встанет снова максимальный элемент).
Для решения этой задачи нам не нужен номер максимального
элемента, а нужно знать значение. После того, как значение
максимального элемента определено, просмотрим массив с конца и, если
элемент имеет максимальное значение, то удалим его, при этом значение
счетчика k будем увеличивать на 1.
После выполнения программы k будет равно количеству удаленных
элементов, поэтому на экран будем выводить n-k элементов, где n – это
количество элементов в исходном массиве.
Рассмотрим удаление нескольких максимальных элементов из
массива целых чисел для n=10.
Пусть массив содержит следующие элементы:
6, 3, 4, 7, 11, 2, 13, 8, 13, 5.
Значение максимального элемента равно max=13. Будем
просматривать массив с конца, изменяя индекс массива i от n до 1. На
каждом шаге будем проверять условие: если i-й элемент равен max, то
сдвинем все элементы, начиная с i до (n-1)-го на одну позицию влево,
последнему элементу присвоим значение 0 и увеличим счетчик на 1
(k:=k+1).
После выполнения программы, мы получим массив вида:
6, 3, 4, 7, 11, 2, 8, 5, 0, 0.
Значение счетчика будет равно k=2. Остается вывести на экран n-k
элементов (в нашем случае 8-2): 6, 3, 4, 7, 11, 2, 8, 5.
Вставка элемента в массив. Вставлять элемент можно до или после
данного элемента, номер которого можно задать с клавиатуры или искать
при определенных условиях.
1) Рассмотрим вставку элемента в массив после элемента с
заданным номером, номер этого элемента введем с клавиатуры.
Решение:
Пусть k – это номер элемента, после которого мы должны вставить
элемент x (k и x будем вводить с клавиатуры). Тогда вставка
осуществляется следующим образом:
 первые k элементов массива остаются без изменений;
 все элементы, начиная с (k+1)-го, необходимо сдвинуть на
одну позицию вправо;
 на место (k+1)-го элемента записываем значение x, т.е. после
k-го элемента массива;
 при выводе массива необходимо учесть, что печатать придется
уже не n (где n – количество элементов в исходном массиве), а
n+1 элемент. Этот факт необходимо учесть еще при описании
массива, чтобы не выйти за границы размерности.
24
2) Рассмотрим теперь вставку элемента в массив перед элементом с
заданным номером.
Решение:
Эта вставка немногим отличается от предыдущей: в первой сдвигали все
элементы, стоящие после k-го, то есть с (k+1)-го, а на его место ставили
новый элемент. В этой – сдвигаем все элементы с k-го, а затем на его место
ставим новый элемент.
Вставка нескольких элементов. Предположим, что надо вставлять не
один элемент в массив, а по одному элементу после всех элементов с
заданным свойством.
Пусть нужно вставить число после всех элементов массива кратных 3.
Решение: Приведем лишь общие рекомендации.
Первое, на что необходимо обратить внимание – это описание
массива: на сколько элементов может увеличиваться массив? В нашем
примере может оказаться, что все элементы исходного массива кратны 3,
т.е. удовлетворяют заданному свойству. Значит, после каждого элемента
нужно вставить число, т.е. количество элементов может увеличиться
вдвое.
Второе. Если мы будем просматривать массив с начала и вставлять
новый элемент после элемента с заданным свойством, то номер последнего
элемента будет меняться, кроме того, будет просматриваться и новый
(вставленный) элемент и его необходимо будет пропускать, поэтому
решение будет не очень эффективным.
Лучше всего просматривать массив, начиная с конца, тогда
вставляемый элемент мешать не будет. Кроме того, номер последнего
элемента можно будет знать (если знать, сколько элементов вставлено на
данный момент), при этом просмотр будет последовательным от N-го до
1-го.
Вариант 1. Дан целочисленный массив с количеством элементов n. Сжать
массив, выбросив из него каждый второй элемент.
Вариант 2. Вставить по одному элементу перед всеми отрицательными
элементами массива.
Вариант 3. Вставить два элемента: первый – после максимального
элемента, второй – перед ним.
Вариант 4. Удалить из массива все отрицательные элементы.
Вариант 5. Преобразовать исходный массив, поменяв порядок элементов
на обратный, не используя вспомогательный массив.
Вариант 6. Удалить все элементы массива, кратные 3 или 5.
Вариант 7. Вставить элемент перед последним отрицательным элементом
массива.
Вариант 8. Дана упорядоченная последовательность. Вставить заданное
число так, чтобы последовательность осталась упорядоченной.
25
Вариант 9. Преобразовать исходный массив, поменяв местами все пары
соседних элементов.
Вариант 10. Преобразовать исходный массив, поменяв местами первый
элемент с максимальным, а последний – с минимальным.
Вариант 11. Дан одномерный массив. Переставить в обратном порядке
элементы массива, расположенные между максимальным и минимальным
элементами.
Вариант 12. Дан одномерный массив. Удалить элемент, стоящий перед
максимальным, а после максимального элемента вставить заданное число.
Вариант 13. Задан массив, содержащий несколько нулевых элементов.
Сжать его, выбросив эти элементы.
Вариант 14. Массив заполнен нулями и единицами. Преобразовать этот
массив так, чтобы вначале стояли нули, а затем единицы.
Вариант 15. Дан массив, состоящий из четного числа элементов. Поменять
местами первую и вторую его половины, сохраняя порядок следования
элементов в каждой половине.
Задание 3
Задание: отсортировать массив указанным способом.
Указание к выполнению: выполнить все этапы решения задачи
самостоятельно, использовать процедуры ввода и вывода массивов,
выделить в задаче вспомогательные алгоритмы и оформить их в виде
подпрограмм.
Виды сортировок
Сортировка выбором. Дана последовательность чисел a1, a2, ..an.
Требуется переставить элементы так, чтобы они были расположены по
убыванию. Для этого в массиве, начиная с k-го, выбирается наибольший
элемент и меняется местами с k-м. Эта процедура выполняется для
k= 1, 2, 3... n-1. При k=1 из всех элементов массива выбирается
наибольший и меняется местами с k-м, т.е. с 1-м, таким образом, он
занимает свое место. При k=2 из оставшихся (всех, кроме первого)
выбирается максимальный элемент и меняется местами с k-м, т.е. со 2-м.
Процедура эта повторяется, пока k не станет равно n-1. Тогда на последнем
шаге из двух последних элементов выбирается максимальный, меняется
местами с k-м, т.е. с (n-1)-м. После этого массив является
отсортированным.
Сортировка методом «пузырька». Дана последовательность чисел a1, a2,
..an. Требуется переставить элементы так, чтобы они были расположены по
возрастанию. Для этого из k элементов массива сравнивают каждую пару
соседних элементов ai и ai+1. Если ai>ai+1, то их меняют местами. При
первом прохождении массива самый большой элемент, как «пузырек»,
26
займет последнее место. Эта процедура выполняется для всех
k=n, n-1, n-2, ...2.
Шейкер-сортировка. Эта сортировка является усовершенствованной
сортировкой методом «пузырька» (внимательно прочитайте предыдущее
описание). Просмотр массива осуществляется последовательно в двух
направлениях. Сначала массив проходят в «прямом» направлении,
сравнивают каждую пару соседних элементов и, если ai>ai+1, то их меняют
местами. При этом элемент с самым большим значением перемещается
вверх и занимает последнее место. Затем массив просматривается в
обратном направлении, начиная уже с (n-1)-го элемента. Сравнивают
каждую пару соседних элементов и, если ai<ai-1, то их меняют местами.
При этом элемент с самым маленьким значением перемещается вниз и
занимает первое место. Затем этот процесс повторяется, начиная со
второго элемента и т.д.
Сортировка вставками. Дана последовательность чисел a1, a2, ..an.
Требуется переставить элементы так, чтобы массив стал упорядоченным.
Пусть k элементов массива уже являются упорядоченными. Берется
следующее число ak+1 и вставляется в последовательность так, чтобы
оказались упорядоченными уже k+1 элемент. Выполняем эту процедуру
для k=1, 2, 3, ..., n-1. Иными словами, при k=1 считаем, что первый элемент
стоит на своем месте. Берем (k+1)-й, т.е. 2-й элемент, и переставляем его
так, чтобы по порядку стояли уже первые два элемента. При k=2 считаем,
что два элемента стоят на своем месте. Берем (k+1)-й, т.е. 3-й элемент, и
переставляем его так, чтобы первые три элемента были упорядочены.
Повторяем эту процедуру, пока k не станет равно n-1. Тогда берем (k+1)-й,
т.е. последний элемент, и переставляем его так, чтобы он занял свое место
среди предыдущих уже упорядоченных элементов. После этого массив
отсортирован.
Сортировка Шелла. Дана последовательность чисел a1, a2, ..an. Требуется
переставить элементы так, чтобы они были расположены по неубыванию.
Делается это следующим образом: сравниваются два соседних элемента ai
и ai+1. Если aiai+1, то продвигаются на один элемент вперед, а если ai>ai+1,
то их меняют местами и сдвигаются на один элемент назад.
Сортировка подсчетом. Дана последовательность чисел a1, a2, ..an.
Требуется переставить элементы так, чтобы они были расположены по
возрастанию. Выходной массив заполняется фиксированными значениями,
заведомо отличными от элементов исходного массива, например, равными
–1. Затем для каждого элемента исходного массива определяется его место
в выходном массиве путем подсчета количества элементов строго
меньших данного. Естественно, что все равные элементы попадают на
одну позицию в выходном массиве, за которой будет следовать ряд
значений –1. После того, как позиции всех элементов исходного массива
определены, и они размещены в выходном массиве, все оставшиеся в
27
выходном массиве элементы равные –1 заполняются копией предыдущего
значения.
Вариант 1. Упорядочить массив по неубыванию Шейкер-сортировкой.
Вариант 2. Упорядочить массив по возрастанию методом выбора.
Вариант 3. Упорядочить массив по убыванию методом вставки.
Вариант 4. Упорядочить массив по невозрастанию методом «пузырька».
Вариант 5. Упорядочить массив по убыванию методом выбора.
Вариант 6. Упорядочить массив по возрастанию методом подсчета.
Вариант 7. Упорядочить массив по возрастанию методом Шелла.
Вариант 8. Упорядочить массив по неубыванию методом вставки.
Вариант 9. Упорядочить массив по неубыванию методом подсчета.
Вариант 10. Упорядочить массив по неубыванию методом «пузырька».
Вариант 11. Упорядочить массив по невозрастанию методом выбора.
Вариант 12. Упорядочить массив по возрастанию методом вставки.
Вариант 13. Упорядочить массив по убыванию Шейкер-сортировкой.
Вариант 14. Упорядочить массив по невозрастанию методом Шелла.
Вариант 15. Упорядочить массив по невозрастанию методом подсчета.
Двумерные массивы – матрицы
Двумерный массив в Паскале трактуется как одномерный массив, тип
элементов которого также является массивом (массив массивов).
Положение элементов в двумерных массивах описывается двумя
индексами. Их можно представить в виде прямоугольной таблицы или
матрицы.
Рассмотрим матрицу размерностью 3*3, то есть в ней будет три
строки, а в каждой строке по три элемента:
 a11 a12

A   a21 a22
a
 31 a32
a13 

a23 
a33 
Каждый элемент имеет свой номер, как у одномерных массивов, но
сейчас номер уже состоит из двух чисел – номера строки, в которой
находится элемент, и номера столбца. Таким образом, номер элемента
определяется пересечением строки и столбца. Например, a21 – это элемент,
стоящий во второй строке и в первом столбце.
Описание двумерного массива. Существует несколько способов
объявления двумерного массива.
Мы уже умеем описывать одномерные массивы, элементы которых
могут иметь любой тип, а, следовательно, и сами элементы могут быть
массивами. Рассмотрим следующее описание типов и переменных:
Type
Vector= array [1..5] of <тип_элементов>;
28
Matrix= array [1..10] of vector;
Var m: matrix;
Мы объявили матрицу m, состоящую из 10 строк, в каждой из
которых 5 столбцов. При этом к каждой i-й строке можно обращаться m[i],
а каждому j-му элементу внутри i-й строки – m[i,j].
Определение типов для двумерных массивов можно задавать и в
одной строке:
Type
Matrix= array [1..5] of array [1..10] of <тип элементов>;
или еще проще:
type
matrix= array [1..5, 1..10] of <тип элементов>;
Обращение к элементам двумерного массива имеет вид: M[i, j]. Это
означает, что мы хотим получить элемент, расположенный в i-й строке и
j-м столбце. Тут главное не перепутать строки со столбцами, а то мы
можем снова получить обращение к несуществующему элементу.
Например, обращение к элементу M[10, 5] имеет правильную форму
записи, но может вызвать ошибку в работе программы.
Основные действия с матрицами
Все, что было сказано об основных действиях с одномерными
массивами, справедливо и для матриц. Единственное действие, которое
можно осуществить над однотипными матрицами целиком – это
присваивание. Т.е., если в программе у нас описаны две матрицы одного
типа, например,
type
matrix= array [1..5, 1..10] of integer;
var
a, b: matrix;
то в ходе выполнения программы можно присвоить матрице a значение
матрицы b (a:=b). Все остальные действия выполняются поэлементно,
при этом над элементами можно выполнять все допустимые
операции, которые определены для типа данных элементов массива.
Это означает, что если массив состоит из целых чисел, то над его
элементами можно выполнять операции, определенные для целых чисел,
если же массив состоит из символов, то к ним применимы операции,
определенные для работы с символами.
Ввод матрицы. Для последовательного ввода элементов
одномерного массива мы использовали цикл for, в котором изменяли
значение индекса с 1-го до последнего. Но положение элемента в
двумерном массиве определяется двумя индексами: номером строки и
номером столбца. Это значит, что нам нужно будет последовательно
изменять номер строки с 1-й до последней и в каждой строке перебирать
29
элементы столбцов с 1-го до последнего. Значит, нам потребуется два
цикла for, причем один из них будет вложен в другой.
Рассмотрим пример ввода матрицы с клавиатуры:
type
matrix= array [1..5, 1..10] of integer;
var
a, : matrix;
i, j: integer; {индексы массива}
begin
for i:=1 to 5 do {цикл для перебора всех строк}
for j:=1 to 10 do {перебор всех элементов строки по столбцам}
readln(a[i,j]); {ввод с клавиатуры элемента, стоящего в i-й строке
и j-м столбце}
Матрицу можно заполнить случайным образом, т.е. использовать
функцию random(N), а также присвоить каждому элементу матрицы
значение некоторого выражения. Способ заполнения матрицы выбирается
в зависимости от поставленной задачи, но в любом случае должен быть
определен каждый элемент в каждой строке и каждом столбце.
Вывод матрицы на экран. Вывод элементов матрицы также
осуществляется последовательно, необходимо напечатать элементы
каждой строки и каждого столбца. При этом хотелось бы, чтобы элементы,
стоящие в одной строке, печатались рядом, т.е. в строку, а элементы
столбца располагались один под другим. Для этого необходимо выполнить
следующую последовательность действий (рассмотрим фрагмент
программы для массива, описанного в предыдущем примере):
for i:=1 to 5 do {цикл для перебора всех строк}
begin
for j:=1 to 10 do {перебор всех элементов строки по столбцам}
write (a[i,j]:4); {печать элементов, стоящих в i-й строке матрицы в
одной экранной строке, при этом для вывода
каждого элемента отводится 4 позиции}
writeln;
{прежде, чем сменить номер строки в матрице, нужно
перевести курсор на начало новой экранной строки}
end;
Замечание (это важно!): очень часто в программах студентов
встречается ошибка, когда ввод с клавиатуры или вывод на экран массива
пытаются осуществить следующим образом: readln(a), writeln(a), где а –
это переменная типа массив. При этом их удивляет сообщение
компилятора, что переменную этого типа невозможно считать или
напечатать. Может быть, вы поймете, почему этого сделать нельзя, если
представите N кружек, стоящих в ряд, а у вас в руках, например, чайник с
водой. Можете вы по команде «налей воду» наполнить сразу все кружки?
Как бы вы ни старались, но в каждую кружку придется наливать отдельно.
30
Заполнение и вывод на экран элементов массива также должно
осуществляться последовательно и поэлементно, т.к. в памяти ЭВМ
элементы массива располагаются в последовательных ячейках.
Представление массива в памяти
Нижние адреса памяти
M32
Элемент
M31
Элемент
M22
Элемент
M21
Элемент
M12
Элемент
M11
Элемент
Элементы абстрактного массива в памяти машины физически
располагаются последовательно, согласно описанию. При этом каждый
элемент занимает в памяти количество байт, соответствующее его размеру.
Например, если массив состоит из элементов типа integer, то каждый
элемент будет занимать по два байта. А весь массив займет S2 байта, где
S – количество элементов в массиве.
А сколько места займет массив, состоящий из массивов, т.е.
матрица? Очевидно: SiSj, где Si - количество строк, а Sj – количество
элементов в каждой строке. Например, для массива типа
Matrix= array [1..3, 1..2] of integer;
потребуется 12 байт памяти.
Как будут располагаться в памяти элементы этого массива?
Рассмотрим схему размещения массива M типа matrix в памяти.
Верхние адреса памяти
Под каждый элемент M[i, j] типа integer выделяется две ячейки
памяти. Размещение в памяти осуществляется «снизу вверх». Элементы
размещаются в порядке изменения индекса, что соответствует схеме
вложенных циклов: сначала размещается первая строка, затем вторая,
третья... Внутри строки по порядку идут элементы: первый, второй и т.д.
Как мы знаем, доступ к любой переменной возможен, только если
известен адрес ячейки памяти, в которой хранится переменная. Конкретная
память выделяется для переменной при загрузке программы, то есть
устанавливается взаимное соответствие между переменной и адресом
ячейки. Но если мы объявили переменную как массив, то программа
«знает» адрес начала массива, то есть первого его элемента. Как же
происходит доступ ко всем другим элементам массива? При реальном
доступе к ячейке памяти, в которой хранится элемент двумерного массива,
система вычисляет ее адрес по формуле:
Addr+SizeElem*Cols*(I-1)+SizeElem*(J-1),
где Addr – фактический начальный адрес, по которому массив
располагается в памяти; I, J – индексы элемента в двумерном массиве;
SizeElem – размер элемента массива (например, два байта для элементов
типа integer); Cols – количество элементов в строке.
31
Выражение
SizeElem*Cols*(I-1)+SizeElem*(J-1)
смещением относительно начала массива.
называют
Сколько памяти выделяется для массива?
Рассмотрим не столько вопрос о том, сколько памяти выделяется под
массив (это мы разобрали в предыдущем разделе), а о том, каков
максимально допустимый размер массива, учитывая ограниченный объем
памяти.
Для работы программы память выделяется сегментами по 64 Кбайт
каждый, причем как минимум один из них определяется как сегмент
данных. Вот в этом-то сегменте и располагаются те данные, которые будет
обрабатывать программа. Ни одна переменная программы не может
располагаться более чем в одном сегменте. Поэтому, даже если в сегменте
находится только одна переменная, описанная как массив, то она не
сможет получить более чем 65536 байт. Но почти наверняка, кроме
массива в сегменте данных будут описаны еще некоторые переменные,
поэтому реальный объем памяти, который может быть выделен под
массив, находится по формуле: 65536-S, где S – объем памяти, уже
выделенный под другие переменные.
Зачем нам это знать? Для того чтобы не удивляться, если при
компиляции транслятор выдаст сообщение об ошибке объявления
слишком длинного массива, когда в программе встретит описание
(правильное с точки зрения синтаксиса):
Type myArray= array [1..50000] of integer;
Вы уже знаете, что, учитывая двухбайтовое представление целых
чисел, реально можно объявить массив с количеством элементов равным
65536/2 –1=32767. И то лишь в том случае, если других переменных не
будет. Двумерные массивы должны иметь еще меньшие границы
индексов.
Примеры решения задач
Задача: Найти произведение ненулевых элементов матрицы.
Решение:
1. Для решения данной задачи нам потребуются переменные: матрица,
состоящая, например, из целочисленных элементов; P –
произведение элементов, отличных от 0; I, J – индексы массива; N, M
– количество строк и столбцов в матрице.
2. Входными данными являются N, M – их значения введем с
клавиатуры; матрица – ввод матрицы оформим в виде процедуры,
заполнение матрицы осуществим случайным образом, т.е. с
помощью функции random().
32
3. Выходными данными будет являться значение переменной P
(произведение).
4. Чтобы проверить правильность выполнения программы, необходимо
вывести матрицу на экран, для этого оформим процедуру вывода
матрицы.
5. Ход решения задачи:
обсудим сначала выполнение основной программы, реализацию
процедур обговорим чуть позже:
 введем значения N и M;
 Введем матрицу, для этого обращаемся к процедуре vvod(a),
где а – матрица;
 Напечатаем полученную матрицу, для этого обращаемся к
процедуре print(a);
 Присвоим начальное значение переменной P=1;
 Будем последовательно перебирать все строки I от 1-й до N-й,
в каждой строке будем перебирать все столбцы J от 1-го до
M-го, для каждого элемента матрицы будем проверять
условие: если aij0, то произведение P будем домножать на
элемент aij (P=P*aij);
 Выведем на экран значение произведения ненулевых
элементов матрицы – P;
А теперь поговорим о процедурах.
Замечание (это важно!) Параметром процедуры может быть любая
переменная предопределенного типа, это означает, что для передачи в
процедуру массива в качестве параметра, тип его должен быть описан
заранее. Например:
Type
Matrix=array [1..10, 1..10] of integer;
..............................
procedure primer (a: matrix);
..............................
Вернемся теперь к нашим процедурам.
Процедура ввода матрицы называется vvod, параметром процедуры
является матрица, причем она должна быть, как результат, передана в
основную программу, следовательно, параметр должен передаваться по
ссылке. Тогда заголовок нашей процедуры будет выглядеть так:
Procedure vvod(var m: matrix);
Для реализации вложенных циклов в процедуре нам потребуются
локальные переменные-счетчики, например, k и h. Алгоритм заполнения
матрицы уже обсуждался, поэтому не будем его повторять.
Процедура вывода матрицы на экран называется print, параметром
процедуры является матрица, но в этом случае она является входным
параметром, следовательно, передается по значению. Заголовок этой
процедуры будет выглядеть следующим образом:
33
Procedure print (m: matrix);
И вновь для реализации вложенных циклов внутри процедуры нам
потребуются счетчики, пусть они называются так же – k и h. Алгоритм
вывода матрицы на экран был описан выше, воспользуемся этим
описанием.
Текст программы
Program proizvedenie;
Type
Matrix=array [1..10, 1..10] of integer;
Var
A: matrix;
N, m, i, j: byte;
P: integer;
Procedure vvod (var m: matrix);
Var k, h: byte;
Begin
For i:=1 to n do {переменная n для процедуры является глобальной, а
значит «известной»}
For j:=1 to m do {переменная m для процедуры является глобальной, а
значит «известной»}
M[i,j]:= random(10);
End;
Procedure print (m: matrix);
Var k, h: byte;
Begin
For i:=1 to n do
begin
For j:=1 to m do
Write (M[i, j]: 4);
Writeln;
end;
End;
Begin {начало основной программы}
Writeln(‘Введите размерность матрицы:’);
Readln(N, M);
Vvod(a);
Print(a);
P:=1;
For i:=1 to N do
For j:=1 to M do
If a[i, j]<>0 then p:=p*a[i, j];
Writeln(p);
End.
34
Задача: даны две матрицы. Найти их сумму.
Решение задачи:
1. Для решения данной задачи нам потребуются переменные: a, b, c –
матрицы одной размерности; i, j – индексы матриц; n, m –
размерность матриц.
2. Входными данными являются переменные n и m, они могут
принимать натуральные значения, их введем с клавиатуры; a, b –
матрицы, ввод матриц оформим в виде процедуры.
3. Выходными данными в этой задаче является матрица c – сумма двух
данных матриц. Вывод матриц на экран оформим в виде процедуры.
4. Ход решения задачи:
 введем размерность матриц n, m;
 введем матрицу a, для этого обратимся к процедуре vvod(a);
 напечатаем полученную матрицу, для этого обратимся к
процедуре print(a);
 введем матрицу b, для этого обратимся к процедуре vvod(b);
 напечатаем полученную матрицу, для этого обратимся к
процедуре print(b);
 Будем последовательно перебирать все строки I от 1-й до N-й,
в каждой строке будем перебирать все столбцы J от 1-го до
M-го, каждый элемент матрицы cij будет равен сумме
соответствующих элементов данных матриц, т.е. cij= aij + bij;
 напечатаем полученную матрицу, для этого обратимся к
процедуре print(c);
Текст программы
Program summa;
Type
Matrix=array [1..10, 1..10] of integer;
Var
A, b, c: matrix;
N, m, i, j: byte;
Procedure vvod (var m: matrix);
Var k, h: byte;
Begin
For i:=1 to n do {переменная n для процедуры является глобальной, а
значит «известной»}
For j:=1 to m do {переменная m для процедуры является глобальной, а
значит «известной»}
M[i,j]:= random(10);
End;
Procedure print (m: matrix);
Var k, h: byte;
35
Begin
For i:=1 to n do
begin
For j:=1 to m do
Write (M[i, j]: 4);
Writeln;
End;
End;
Begin {начало основной программы}
Writeln(‘Введите размерность матрицы:’);
Readln(N, M);
Vvod(a); Print(a);
Writeln; {вставим пустую строку чтобы разделить вывод матриц}
Vvod(b); Print(b);
Writeln; {вставим пустую строку чтобы разделить вывод матриц}
For i:=1 to N do
For j:=1 to M do
C[i, j]:= a[i, j]+b[i, j];
Print(c);
End.
Вопросы для повторения
1. Что представляет собой двумерный массив?
2. Как в Паскале описывается двумерный массив?
3. Как осуществляется доступ к элементам двумерного массива?
4. Как осуществить ввод матрицы?
5. Как осуществить вывод матрицы на экран?
6. Есть следующее описание переменных:
var a,b: array [1..15, 0..8] of real; t: boolean;
Какие из указанных операций допустимы в Паскале?
 a:= b;
 t:=a<>b;
 a[1]:=a[8];
 a:=a+b;
 read(a);
 a[2,3]:=b[4,8]+b[1,1].
7. Какое из описаний вызовет ошибку "Structure too large" (структура
превышает максимально допустимый объём статической памяти) :
 Type Vector = Array[Byte] Of Integer; Var C : Array[1..10] Of Vector;
 Var K : Array [Byte, Byte] Of real;
 Var S : Array[–10000..10000] Of integer.
8. Можно ли в Паскале описать трехмерный массив? А n-мерный? Как
это сделать? Как осуществляется доступ к элементам n-мерного
массива?
36
Лабораторная работа №6
Тема: Двумерные массивы
Задание 1
Задание: Сформировать квадратную матрицу порядка n по заданному
образцу:
Указания к выполнению: выполнить все этапы решения задачи
самостоятельно. Вывод матрицы на экран оформить в виде процедуры.
Вариант 1.
Вариант 5.
1
2
3
... n-1 N
1
1
1
...
1
1
N n-1 n-2 ...
2
1
0
1
1
...
1
0
1
2
3
... n-1 N
0
0
1
...
0
0
N n-1 n-2 ...
2
1
...
...
... ...
...
...
...
...
...
...
...
0
1
1
...
1
0
N n-1 n-2 ...
2
1
1
1
1
...
1
1
Вариант 2.
0
0
0
0
0
0
...
...
...
0
0 n-2
0 n-1 0
n
0
0
...
...
...
...
...
...
0
2
...
0
0
0
Вариант 3.
n
0
0
0 n-1 0
0
0 n-2
...
...
...
0
0
0
0
0
0
...
...
...
...
...
...
0
0
0
...
2
0
Вариант 4.
1
n
1
n
2 n-1 2 n-1
3 n-2 3 n-2
...
...
...
...
n-1 2 n-1 2
n
1
n
1
...
...
...
...
...
...
1
0
...
0
0
0
Вариант 6.
1
1
1
2
2
2
3
3
3
...
...
...
n-1 n-1 0
n
0
0
...
...
...
...
...
...
1
2
0
...
0
0
1
0
0
...
0
0
0
0
0
...
0
1
Вариант 7.
1
2
3
2
3
4
3
4
5
...
...
...
n-1 N
0
n
0
0
...
...
...
...
...
...
n-1
n
0
...
0
0
N
0
0
...
0
0
N
n-1
n-2
...
2
1
Вариант 8.
1
0
0
0
2
0
0
0
3
...
...
...
0
2
0
1
0
0
...
...
...
...
...
...
0
n-1
0
...
n-1
0
N
0
0
...
0
N
37
Задание: вычислить сумму элементов матрицы в заштрихованной
области.
Указание к выполнению: выполнить все этапы решения задачи
самостоятельно. Ввод и вывод матрицы оформить в виде процедур.
Вариант 12.
K строка
Вариант 10.
Вариант 13.
Вариант 11.
Вариант 14.
38
H столбец
Вариант 9.
K строка
H столбец
Вариант 15.
Задание 2
Задание: составить программу решения задачи.
Указания к выполнению: самостоятельно выполнить все этапы
решения задачи. Ввод и вывод матрицы оформить в виде процедур. При
необходимости выделить в задаче вспомогательные алгоритмы и
оформить их в виде подпрограмм.
Вариант 1.
Квадратная матрица, симметричная относительно главной диагонали,
задана верхним треугольником в виде одномерного массива.
Восстановить исходную матрицу и напечатать ее по строкам.
Вариант 2.
Элемент матрицы назовем седловой точкой, если он является
наибольшим в строке и одновременно наименьшим в столбце. Для
заданной матрицы напечатать индексы ее седловых точек.
Вариант 3.
Дана матрица, переставляя ее строки и столбцы. Добиться того, чтобы
наибольший элемент оказался в левом верхнем углу.
Вариант 4.
Дана матрица, определить количество «особых» элементов. Элемент
считается «особым», если он больше суммы остальных элементов
строки.
Вариант 5.
Упорядочить по возрастанию элементы каждой строки матрицы.
Вариант 6.
Расположить столбцы матрицы в порядке возрастания элементов k-ой
строки.
Вариант 7.
Упорядочить по убыванию элементы каждого столбца матрицы.
39
Вариант 8.
Элемент матрицы назовем седловой точкой, если он является
наибольшим в столбце и одновременно наименьшим в строке. Найти
все седловые точки матрицы.
Вариант 9.
Дана матрица, вывести все «особые» элементы. Элемент считается
«особым», если он больше суммы остальных элементов столбца.
Вариант 10.
Расположить строки матрицы в порядке возрастания элементов первого
столбца.
Вариант 11.
Расположить столбцы матрицы в порядке убывания элементов
последней строки.
Вариант 12.
В квадратной матрице поменять местами строку с наибольшим
элементом матрицы и столбец, содержащий наименьший элемент.
Вариант 13.
Дана квадратная матрица. Преобразовать ее, повернув на 90 против
часовой стрелки относительно центра.
Вариант 14.
Определить, является ли заданная квадратная матрица симметричной
относительно побочной диагонали.
Вариант 15.
Определить, является ли квадратная матрица магическим квадратом,
т.е. суммы элементов в каждой строке и каждом столбце равны.
Литература
1. Грызлов В.И., Грызлова Т.П. Турбо Паскаль 7.0. – М.: ДМК, 1998.
2. Фаронов В.В. Турбо Паскаль 7.0. Начальный курс/ Учебное пособие. – М.:
«Нолидж», 1997.
3. Марченко А.И., Марченко Л.А. Программирование в среде Turbo Pascal 7.0/
Под ред. Тарасенко В.П. – 5-е изд., доп. и перераб. – К.: ВЕК+, 1999.
4. Пильщиков В.Н. Сборник упражнений по языку Паскаль: учеб. пособие для
вузов. – М.: Наука, 1989.
5. Информатика. Задачник-практикум в 2т./ Под ред. И.Г. Семакина, Е.К.
Хеннера: Том 1. – М.: Лаборатория Базовых Знаний, 1999.
6. Бабушкина И.А., Бушмелева Н.А., Окулов С.М., Черных С.Ю. Практикум по
Турбо Паскалю. Учебное пособие по курсам «Информатика и вычислительная
техника», «Основы программирования». – Москва, АБФ, 1998.
7. Румянцев Дмитрий, Монастырский Леонид. Путь программиста: Опыт
созидания личности программиста. – М.: «Издательский Дом ИНФРА-М», 2000
8. Семакин И.Г., Шестаков А.П. Основы программирования: Учебник. – М.:
Мастерство; НМЦ СПО; Высшая школа, 2001.
9. Звягина А.С. Языки и методы программирования: средства описания данных,
средства описания действий. Учебный курс. – Хабаровск: Изд-во ХГПУ, 2000.
10. Звягина А.С. Языки и методы программирования: процедурное, модульное,
объектно-ориентированное программирование. Учебный курс. – Хабаровск:
Изд-во ХГПУ, 2000.
40
Download