| Раздел: Turbo Pascal | Автор: fox++ |
| E-mail: |
Www: http://foxweb.net.ru |
| Просмотров: 9068 | Дата: 16.01.2005 |
Почему вдруг я захотел написать эту статью? А потому что 80% всех часто задаваемых вопросов по алгоритмам связано с массивами. Ну например, как вывести на экран все отрицательные числа массива? Или найти третий нулевой элемент массива. А ещё заменить первый чётный элемент последним нечётным. Таких задач бесконечное множество, однако методы их решения стандартны. Программирование давно превратилось из искусства в ремесло. Потому и надо искать знакомые методы, а не изобретать велосипед. Ну вот, вроде с введением всё.
Для начала вспомним, что есть одномерный массив. Массивы представляют собой ограниченную упорядоченную совокупность однотипных величин. Каждая отдельная величина называется элементом массива. Тип элементов может быть любым, принятым в языке ПАСКАЛЬ, кроме файлового типа. Тип элемента называется базовым типом. Вся совокупность элементов определяется одним именем. Для обозначения отдельных элементов используется конструкция, называемая переменной с индексом или с индексами:
A[5] S[k+1] B[3,5]
В качестве индекса может быть использовано выражение. Тип индексов может быть только интервальным или перечисляемым. Действительный и целый типы недопустимы. Индексы интервального типа, для которого базовым является целый тип, могут принимать отрицательные, нулевое и положительные значения.
Ниже я попытаюсь изобразить собственное представление
одномерного массива. Вот он какой. Предположим, что массив уже заполнен
(потом объясню, как это сделать). Проще говоря, это всего лишь набор
ящиков A, в которых хранятся значения.
У каждого ящика есть свой номер (индекс i).
В каждом ящике хранится некоторое значение (элемент A[i]).
Тогда для массива, изображённого на рисунке, справедливо следующее:
A[1]:=4;
A[2]:=5;
A[3]:=6;
A[4]:=3;
A[5]:=0;
Так что одномерный массив - это самый простой тип данных сложной структуры.
Попробуем теперь обратиться к некоторым элементам
массива. Например выведем на экран третий элемент. Его переменная
будет выглядеть A[3].
i:=3;
WriteLn (A[i]);
или
WriteLn (A[3]);
или
z:=A[3];
WriteLn (z);
Первый способ более универсален, поскольку i
- индекс элемента - может изменяться где-то в другом месте программы.
Во втором случае мы печатаем строго третий элемент, что и требовалось.
В третьем случае мы вводим новую переменную z, равную
A[3], чтобы в других местах программы ещё несколько
раз обращаться к A[3] через z.
На этом этапе главное не переборщить с индексом, иначе программа будет выдавать ошибку. Для этого следует проверять по условию номера индексов, введённые пользователем с клавиатуры, чтобы они не оказывались больше определённого значения.
Обычно задачи про одномерные массивы начинаются со слов "заполните массив..." или "дан одномерный массив..." - всё это предполагает то, что массив был ранее создан и заполнен.
Теперь нам ясно, что присвоить элементу массива значение можно следующим образом:
A[i]:=x;
Но если этих элементов десять или десять тысяч?
Тогда на помощь приходит оператор цикла For-to-do.
Приведу такой сэмпл:
For i:=1 to 10000 do
A[i]:=i*2;
Получим в каждом элементе массива число в два
раза большее, чем его индекс. Это значит, что в первым элементом
будет 2, а вторым - 20000. Конечно, вместо выражения i*2
можно использовать любые математические формулы. Тогда каждый раз
массив будет заполняться по функциональной зависимости, где индекс
- это аргумент функции (i), а сам элемент - значение
функции (A[i]). Посмотрим массив значений функции y=x2
на промежутке [1; 20].
For x:=1 to 20 to
y[x]:=sqr(x);
Здесь видно, что в программе y[x]:=sqr(x)
- это тоже самое, что и математическое выражение y(x)=x2.
А задание к этой программке будет звучать примерно так: "Заполнить
массив y квадратами чисел от 1 до 20".
Но если задании сказано, что массив следует заполнить с клавиатуры? В основе заполнения массивов, как мы выяснили, лежит простое присваивание. Ну а там, где присваивание, есть и ввод с клавиатуры. Вспомним как это делается для обычных переменных:
ReadLn (x);
Теперь программа ожидает, пока мы наберём на клаве
число и нажмём Enter. Всё! Наше число хранится в переменной x.
Прикидываем, что элемент массива - это та же переменная, только
с индексом:
ReadLn (A[i]);
В зависимости от индекса i введённое
пользователем число запишется в массиве A по номеру
i. Вспомним, как мы присваивали значения элементов
в цикле:
For i:=1 to 20 do
ReadLn (A[i]);
Программа запрашиват числа одно за другим, пока
мы не введём 20 чисел. И все они по окончании цикла будут находиться
в массиве A по тем номерам и в том порядке, как мы
их вводили. Параллельно с вводом с клавиатуры можно выводить на
экран номер вводимого элемента, чтобы пользователь не запутался:
For i:=1 to 20 do
begin
Write ('A[',i,']=');
ReadLn (A[i]);
end;
Тогда на экране сначала покажется надпись A[1]=
и рядом курсор ввода. Ну вот, теперь мы можем заполнять массивы
с клавиатуры!
Здесь всё остаётся также, как если бы мы заполняли
массив по функции, но в данном примере функция Random()
каждый раз не определена и генерируется случайно.
Randomize; {запуск генератора случайных чисел}
For i:=1 to 20 do
A[i]:=Random(100);
Тогда мы получим массив, заполненный разными числами
от 0 до 99 благодаря функции Random. Если умело использовать
её, то можно заполнить массив не только от 0 до 99, но и от -100
до 100. Для этого сгенерируем случайное число Random(201) (это будет
от 0 до 200) и отнимем 100. Тогда, если получится 0, отнимается
100 и получаем
-100. Если генерируется 200, опять отнимается 100 и получаем 100.
Тут в общем-то всё просто, если в школе учили алгебру и знаете определение
"область принимаемых значений".
Randomize; {запуск генератора случайных чисел}
For i:=1 to 20 do
A[i]:=Random(201)-100;
Теперь мы умеем заполнять массив тремя способами. Этого хватит для решения задач любой сложности. Ведь главное в программе - это исходные данные, полученные извне.
Эту операцию, как и заполнение, тоже можно выполнить
несколькими способами. Это может быть вывод элементов в столбец,
в строку (один за другим) или используя форматный вывод. В задачах
пишут примерно так: "вывести массив на экран", "напечатать
элементы массива в строку", "вывести на экран элементы
массива спосбом форматированного вывода". Как мы знаем, вывод
на экран осуществляется оператором Writeln (). Если
вы об этом слышите впервые, то можете выключить компьютер и идти
спать :).
Итак, вывод на экран значения элемента массива - это очень просто:
WriteLn (A[1]);
WriteLn (A[2]);
- - - - - - - -
Writeln (A[n]);
Главное помнить, что в случае с WriteLn
добавляется перевод строки и следующий вывод печатается на новой
строке. С Write весь вывод идёт в одну строку без
пробелов! Потому-то пробел и добавляют "искуственно"
с помощью Write (' ').
Теперь же рассмотрим, как элементы массива можно
вывести в цикле. Это аналогично алгоритму заполнения с клавиатуры,
только мы не вводим, а выводим значения. Следующий сэмпл демонстрирует
самый простой вывод массива в столбец (обратите внимание на WriteLn,
который переводит строку):
For i:=1 to 20 do
WriteLn (A[i]);
Чуть интереснее выглядит вывод в строку с "искуственным пробелом". После печати элемента сразу же за ним печатается пробел, тогда следующий элемент будет напечатан после пробела.
For i:=1 to 20 do
begin
Write (A[i]);
Write (' ');
end;
Или так, что проще:
For i:=1 to 20 do
begin
Write (A[i],' ');
end;
А теперь самый сложный способ - форматированный вывод. Он используется с многозначными дробными числами и пригоден для вывода больших массивов в виде таблиц.
For i:=1 to 20 do
WriteLn (A[i]:4:2); {4 и 2 - в целой и дробной части числа}
Для начала следует вспомнить, что условие выражается
с помощью оператора If. Потом надо сесть и хорошо подумать
- какое условие следует вычислить? Рассмотрим простейшее условие
вывода на экран.
Допустим задание звучит так: "вывести на экран элементы, равные нулю". Это очень просто. Для каждого элемента массива в цикле вычисляется следующее условие:
If A[i]:=0 then WriteLn (A[i]);
Условие читается так: "Если элемент A[i]
равен нулю, то выводим на экран значение A[i]".
Итак, сэмпл программы, который выводит на экран нулевые элементы,
будет выглядеть так:
For i:=1 to 20 do
If A[i]:=0 then WriteLn (A[i]);
Допустим нам необходимо не только вывести на экран
нулевые элементы, но и подсчитать их количество. Как это сделать?
Это делается с помощью такого же условия, но для подсчёта мы вводим
новую переменную. Пусть это будет переменная целого типа z:integer.
Тогда каждый раз при выполнении условия к ней будет прибавляться
единица. В этом и заключается принцип счётчика.
For i:=1 to 20 do
If A[i]:=0 then
begin
WriteLn (A[i]);
z:=z+1;
end;
Как только очередной элемент равен нулю, он выводится
на экран оператором WriteLn, после чего к счётчику
z прибавляется 1.
Иногда в задании указывается, что из определённых
элементов массива нужно составить новый массив. Пусть это будет
массив B[20].
Прежде, чем приступить к написанию программы,
посмотрим как это можно сделать вручную. Чтобы заполнять поочерёдно
все элементы массива B при перечислении массива A,
необходимо установить счётчик индекса для массива B
(пусть это будет n:=1). Когда будет обнаружен первый
ноль, он будет записан в B[n], после чего n:=n+1.
Следующий ноль будет записан в B[2] и так далее.
n:=1.i:=1 элемент массива A.B[n].n на единицу.Теперь, когда алгоритм ясен, составим сэмпл. Вообще,
в этой программе z и n равны, так как
они обе показывают число нулей.
For i:=1 to 20 do
If A[i]:=0 then
begin
WriteLn (A[i]);
z:=z+1;
B[n]:=A[i];
n:=n+1;
end;
Кстати, вместо конструкции n:=n+1
можно использовать стандартную функцию инкремента (приращения переменной)
inc(n). Вместо кнструкции n:=n+x можно
применить inc(n,x).
От начала до конца я рассматривал такую задачу:
Дан массив целых чисел A,
состоящий из 20 элементов. Определить число нулевых элементов и
записать их в массив B.
Составим на основе предыдущих сэмплов цельную
работающую программу. Вообще, в этой программе z и
n равны, так как они обе показывают число нулей. Потому
оставляю только n.
Program Null;
var
i,n:integer;
A,B:array [1..20] of integer;
begin
For i:=1 to 20 do
begin
Write ('A[',i,']=');
ReadLn (A[i]);
end;
n:=1;
For i:=1 to 20 do
If A[i]:=0 then
begin
WriteLn (A[i]);
n:=n+1;
B[n]:=A[i];
end;
WriteLn ('В массиве найдено ',n,'нулей.');
ReadKey;
end.