Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Самоучитель игры на Паскале. АВС и немного Турбо
.pdf
var
a : array[1..5] of integer;
i : integer;
begin
{ тут вводим}
Writeln(‘Input’);
Writeln;
for i:=1 to 5 do begin
Write(‘a[‘,I,’] = ’);
Readln(a[i]);
end;
Writeln;
{ тут делаем что-нибудь полезное}
{ тут выводим}
Writeln(‘Output’);
Writeln;
for i:=1 to 5 do
Writeln(a[i]);
end.
После запуска получим вот такую картинку:
81

Мешанина кавычек и запятых в строке Write(‘a[‘,I,’] = ’); призвана
обеспечить более приятное и удобное приглашение для ввода элементов
массива.
Если что-то непонятно, придётся просто заучить наизусть. Все наши
ближайшие программы подразумеваются имеющими в точности такой же
объявленный массив и в точности такой же ввод и вывод.
Возвращаемся к проблеме трижды встречающейся в тексте программы
пятерки. Это, безусл
Будем пр
облему решать, раз и навсегда.
овно, нехорошо, по причинам объясненным ранее.
Что такое константа? Да почти то же самое, что и переменная, только в
отличие от переменной получает своё значение раз и навсегда. Ну и по
мелочи:
переменная объявляется в секции var, константа в секции const;
после име
ни переменной следует двоеточие, после имени константы
знак равенства;
после разделителя у пе
82
ременной тип, у константы значение;

в одной строке можно объявить много переменных, а константы
объявляются строго по одной. Ну, можно, конечно, много констант в
одной строке. Имелось с виду, что через запятую нельзя.
Вот так выглядит объявление необходимой нам константы:
const
N = 5;
Секция констант по традиции предшествует секции переменных. Вопервых, по традиции и для единообразия. Во-вторых, как в нашем случае,
ругому нельзя по причине ис
по д
переменных. У нас константа N служит верхней границей в объявлении
массива.
Теперь каждый идентификатор N в нашей программе будет эквивалентен
числу пять, и, в случае, если размер массива изменится, достаточно будет
внести исправление только в одно место нашей программы.
А программа наша тем временем приобрела во
program Arr_2;
uses
Crt;
const
N = 5;
var
a : array[1..N] of integer;
i :
begin
{ тут вводим}
Writeln(‘Input’);
Writeln;
for i:=1 to N do begin
Write(‘a[‘,I,’] = ’);
Readln(a[i]);
end;
Writeln;
{ тут делаем что-нибудь полезное}
integer;
пользования констант в объявлении
т такой вид:
83

{ тут выводим}
Writeln(‘Output’);
Writeln;
for i:=1 to N do
Writeln(a[i]);
end.
А можно вообще без констант? Можно. Почти. Вообще константы можно было бы заменить переменными, присвоить
им один раз значение, а с программиста взять честное слово, что он не будет эти значения менять. К сожалению, на
честное слово программиста надежда небольшая, лучше ограничить программиста компилятором.
В Delphi появились константы, значение которых можно менять. Лично мне каже
случае были неправы.
А почему нельзя совсем без констант? А потому что в Паскале начальный и конечный диапазоны в объявлении
массива не могут быть переменными.
тся, что разработчи
ки языка в данном
И ещё на что нужно обратить внимание – одно имя может быть дано в
программе только один раз. Имя можно дать переменной. Имя можно дать
константе. Можно никому не давать. Но нельзя одним и тем же именем
назвать и константу и переменную.
Опыты
Несколько стандартных задач при работе с массивами. Встречаться они
будут не часто, а очень часто. Ничего изобретать тут не надо, ду
мать тоже
ничего не надо – программист должен это писать, не думая абсолютно и
на полном автопилоте.
У
нас всё тот же массив от одного до N. Все появившееся неупомянутые
ранее переменные – целые.
1. Заполнить массив одним и тем же значением, чаще всего нулем:
for i:=1 to N do
a[i]:=0;
2. Заполнить массив сл
учайными значениями в диапазоне от 0 до 99:
for i:=1 to N do
a[i]:=Random(100);
3. Поместить в каждый элемент массива его индекс:
for i:=1 to N do
a[i]:=i;
4. Увеличить каждый элемент массива на единицу:
for i:=1 to N do
84

a[i]:=a[i] + 1;
5. Определить сумму элементов массива:
sum:=0;
for i:=1 to N do
sum:=sum + a[i];
6. Определить среднее элементов массива (результат - дробный)
sum:=0;
for i:=1 to N do
sum:=sum + a[i];
result:=sum/N;
7. Найти минимальный элемент массива и его индекс:
min:=a[1];
index:=1;
for i:=2 to N do begin
if a[i] < min then begin
min:=a[i];
index:=I;
end;
end;
8. Определить количество отрицательных и неотрицательных
элементов массива:
numNeg:=0;
numNonNeg:=0;
for i:= 1 to N do begin
if a[i]
then numNeg:=numNeg + 1
else numNonNeg:=numNonNeg + 1;
end;
9. Вставить нулевой элемен
количество элементов массива не меньше пяти). При этом все
элементы, начиная с бывшего пятого должны сдвинуться на одну
позицию вправо:
for i:=N downto 6 do
a[i]:=a[i-1];
a[5]:=0;
10. Сдвинуть все элементы, начиная с четвертого налево на три.
Хвост заполнить нулями.
< 0
т в пятую позицию (доверчиво считаем, что
85

for i:=1 to N-3 do
a[i]:=a[i+3];
for i:=N-2 to N do
a[i]:=0;
Вариант альтернативный, но допустимый:
for i:=1 to N do
if i <= N-3
then a[i]:=a[i+3]
else a[i]:=0;
11. Определить индекс первого чётного элемента массива:
indexEven:=0;
for i:=1 to N do begin
if ((a[i] mod 2) = 0) and (indexEven=0)
then indexEven:=i;
end;
Здесь вторая проверка добавлена, чтобы вернуть номер только и только
первого чётного элемента. Если этой проверки не будет, вс
случиться совсем по-друго
му. В случае нечётности всех элементов
ё может
массива мы должны вернуть в качестве ответа ноль. Это
общепринятая практика – если ответа нет, возвращать некоторое
невозможное значение. Если ноль является допустимым ответом,
обычно возвращают минус единицу.
Скобки вокруг a[i] mod 2 поставлены исключительно для наглядности и
выразительности – по синтаксису они не нужны.
По хорошему, вторая проверка вообще не нужна – Вам поможет волшебное слово Break – и на гигантском массиве
программа заработает чуть-чуть быстрее (тот, кого это волнует – не очень хороший программист). Поскольку оно
(Break) противоречит принципам структурного программирования, о Break, возможно вспомним потом. О
структурном программировании, тоже, возможно, потом – или в совсем другой книге. Впрочем, все приведённые
рограммы
п
от заветов структурного программирования пока не отступили ни на шаг.
Ещё опыты
То, что мы делали в предыдущем разделе, мы делали с одним массивом.
Несколько типовых задач, в которых участвуют два массива сразу.
Первый массив зовут A, второй массив B. Оба массива содержат
одинаковое число элементов – N.
1. Проще не бывает. Присвоить все элементы одного массива
другому.
86

Вопрос на самом деле не такой уж простой. Потому что можно и так: b:=a; Но только при условии, что массивы
объявлены где-то так a,b : array[1..N] of integer; А если вот так a : array[1..N] of integer; b : array[1..N] of integer; то
уже ничего не выйдет. Точнее, ничего не выйдет в Turbo Pascal, что неважно. Но ничего не выйдет и в Delp
очень важно. Дальше нам надо плавно перейти к
будем.
обсуждению определенных пользователем типов. Но мы пока не
hi, что
for i:=1 to N do
b[i]:=a[i];
2. Посчитать поэлементно сумму массивов и отправить в первый
массив:
for i:=1 to N do
a[i]:=a[i] + b[i];
3. Положительные элементы из первого массива отправить во
второй, но чтобы во втором они шли без пропусков в начале
массива. То есть, было в первом массиве [1,2,3,-5,1,-7,2]. Во
втором должно образоваться [1,2,3,1,2]
ind:=0;
for i:=1 to N do begin
if a[i]
>0 then begin
ind:=ind + 1;
b[ind]:=a[i];
end;
end;
4. В первом массиве для нас представляют интерес только первые
N1 эл
ементов, во втором массиве, соответственно, N2.
Объединить N1 и N2 первых элементов их двух массивов, записав
их в первый массив. Искренне верим, что N1+N2 <= N.
for i:=1 to N2 do
a[N1+i]:=b[i];
N1:=N1 + N2;
5. Переписать элементы первого массива во второй, но в обратном
порядке
for i:=1 to N do
b[N-i+1]:=a[i]
87

А теперь как будто мы вернулись в предыдущий раздел. Перепишите
элементы массива в обратном порядке, не используя второго
массива. То есть, внутри него самого.
Как поменять два элемента местами? Обычно делают так (wrk –
целая переменная, исключительно для вспомогательных целей):
wrk:=a[i];
a[i]:=a[i+1]
a[i+1]:=wrk;
Самый главный опыт
Из всех упражнений, которые приходится проделывать над мас
наиважнейшим для нас является, бесспорно, сортировка. Что делает
сортировка? Сортировка, ну,
На входе:
[10, 22, 11, 50, 30]
На выходе
[10, 11, 22, 30, 50]
Методов сортировки огромное количество. Главный критерий их оценки –
быстродействие. Математическую сторону, как и везде в этой книге, мы
беспощадно упрощаем, уплощаем и опошляем.
Одни методы сортируют быстрее, другие ещё быстрее, а совсем другие –
сем наоборот.
сов
Большинство программистов используют самы
методов – пузырьковую сортировку. Такова традиция. Программист,
который не может её запрограммировать за пять минут – неполноценен во
всех отношениях. Даже если освоил все остальные методы. Мы в
неполноценные не хотим, поэтому сейчас будем программировать
пузырьковую сортировку. Почему она пузырьковая? Запрограммируйте,
включите воображение и поймёте.
В чём идея? Сравниваем первый и второй элем
второго (или равен второму), то всё хорошо и ничего делать не надо. Если
первый больше второго, то это пло
в общем, сортирует…
й худший из худших
енты. Если первый меньше
хо, поэтому меняем первый элемент со
сивами,
88

вторым местами. Потом сравниваем второй элемент с третьим, реагируем
аналогично. И так доходим до сравнения предпоследнего элемента с
последним.
А затем начинаем всё сначала. Если за время всего прохода по массиву
мы никого не поменяли местами, то всё хорошо и можно заканчивать.
Что видно сразу? Внешний, главный цикл прямо-таки напрашивается
быть запрограммированным как repeat-until – повторять до тех пор, по
не станет всё хорошо. Внутренний цикл обычный, и повторяться он будет
очевидн
Ну и конечно, объявим специальную переменную по имени Ok. Как
только она – да, то мы – всё. Получаем вот такой эскиз программы:
const
N = 5;
var
a
Ok : integer;
i : integer;
……………………………………………
repeat
for i:=1 to N-1 do begin
if a[i] > a[i+1] then begin
{поменять местами}
end;
end;
until ok=1;
Мы просто записали на Паскале то, что раньше сказали словами. Что
осталось неясным?
Судьба переменной Ok. Договоримся, что если Ok=1, то всё хорошо, то
есть о’кей, а если ok=0, то, наоборот, всё плохо, не о’кей, в смы
уже решили, что основной цикл выполняет
записали это. Очевидно, перед началом сортировки у нас не всё Ok – а
иначе, зачем сортировать? Значит, перед циклом переменная
устанавливается в ноль. Опять-таки, если пришлось поменять элементы
местами, значит у нас опять всё плохо – и опять переменной присваиваем
ноль. Но когда-то же должна она стать единицей, цикл ведь должен
о N-1 раз. N – как всегда, количество элементов в массиве.
: array[1..N] of integer;
ся до тех пор, пока не Ok – и
ка
сле. Мы
89

закончиться? Стандартная технология для таких случаев – перед циклом
предполагаем, что всё хорошо. Если внутри цикла хоть раз что-то
оказалось не так – переменная получает значение ноль.
Вторая, даже не проблема, а так. Поменять элементы местами. Вводим
вспомогательную переменную того же (целого) типа и меняем через неё.
Затем думаем, как это можно сделать без использ
переменной. Подсказка – это можно сделать для числен
ования вспомогательной
ных переменных,
для строковых номер не пройдёт.
Примечание. Тот, кто попробует сделать это для real, немедленно будет лишён премии.
Маньяки могут поменять и для строковых переменных. Но таких премией не возьмёшь.
И, наконец, наша программа приобретает законченный вид:
const
N = 5;
var
a : array[1..N] of integer;
Ok : integer;
wrk : integer;
i : integer;
……………………………………………
Ok:=0;
repeat
ok:=1;
for i:=1 to N-1 do begin
if a[i] > a[i+1] then begin
Ok:=0;
{поменять местами}
wrk:=a[i];
a[i]:=a[i+1];
a[i+1]:=a[i];
end;
end;
until Ok=1;
Прикрутите заполнение массива случайными числами, вывод до и вывод
после и любуйтесь результатом.
90
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
