Basic - вводный курс

         

Описание массива

Если мы знаем, что в программе предстоит работать с большим объемом каких-то данных, то мы должны этот массив в программе объявить с помощью специального оператора dim (от англ. "dimension"), после которого указывается имя массива, а потом в скобках следует так называемый размер массива, т. е. количество его элементов. Например, пусть в группе четыре человека. Массив — это фамилии учеников. Мы тогда должны записать так:

DIM FAM$ (4)

Знак $ добавляется, т. к. в массиве будут храниться строковые переменные. В этом случае компьютер в памяти отводит некую область из четырех ячеек, которую всю и называет fam$. Кроме того, эти ячейки нумеруются натуральными числами, начиная с 1. Я всегда подобную процедуру, да и сам массив, сравниваю с улицей одноэтажных домов в деревне или маленьком городке. Построили на улице четыре дома, назвали улицу fam$ (имя массива дается по тем же правилам, что и имя переменной), пронумеровали дома и заселили туда жильцов (рис. 1.66).

Рис.1.66. Массив

FAM$ из четырех элементов
Из этого следует, что:

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

Предупреждение
Оператор dim для каждого конкретного массива должен задаваться только один раз в программе до первого к нему обращения.

Продолжая аналогию с улицей одноэтажных домов, что надо сделать, чтобы обратиться к како'му-либо конкретному жильцу? Знать его адрес!


Предположим, мы хотим потревожить господина Муна — указываем его адрес — fam$(2), т. е. название улицы и дом. Зачастую начинающие программисты путают индекс элемента массива (его номер) и значение элемента массива, т. е. "кто-кто в тереме живет". Итак, еще раз: индекс или номер элемента массива — величина постоянная, а значение (как и жильцы в доме) с легкостью может меняться.
В начале мы рассмотрим одномерные массивы — такие, в которых адрес элемента массива определяется только одним индексом (номером "дома").

Предупреждение
На самом деле, нумерация ячеек-"домиков" в Бейсике начинается с нуля, но с единицы нам привычнее и удобнее, поэтому нулевой "домик" мы пропускаем. Возможен более законный вариант — обязать Бейсик нумеровать "домики" с единицы оператором OPTION BASE 1.


Заполнение одномерных массивов и вывод их на экран

Первая задача, встающая перед программистом прежде чем, обработать массив, — заполнить его "жильцами". Для этого в Бейсике существует несколько способов, которые мы и рассмотрим. Кроме того, для контроля правильности заполнения, лучше бы сразу выводить массив на экран, чтобы потом можно было проверить правильность решения поставленной задачи.
Для всех случаев мы рассмотрим один и тот же пример — заполнить массив N целыми числами, каждое из которых не более 100. Мы не берем конкретное значение N, чтобы вы понимали: программа не должна зависеть от исходных данных. Сейчас мы хотим создать массив из 10 чисел, а в следующий раз — из 1000. Программа останется той же.

Заполнение одномерного массива с клавиатуры

Рассмотрим следующий пример:

CLS
INPUT "Введите количество элементов массива"; N
DIM MASS(N)
FOR 1=1 ТО N
? "Введите"; N; "элемент массива"
INPUT MASS(I) NEXT I
7
FOR 1=1 TO N ? MASS(I); NEXT I

Программа требует некоторых пояснений. Первая команда тра-диционна — очистка экрана. Далее идет запрос с клавиатуры количества элементов массива. Потом цикл, в котором от 1 до N программа последовательно запрашивает у пользователя ввод очередного элемента массива и записывает его значение по указанному адресу mass(i) . После первого цикла выполняется оператор print без параметров. Он отображает пустую строку между вводом значений и их выводом. Последний оператор цикла выводит значения массива на экран в строчку, что обеспечивается
добавлением к оператору print точки с запятой. Результаты работы программы для трех элементов будут выглядеть так:

Введите 1 элемент массива
? 23
Введите 2 элемент массива
? 13
Введите 3 элемент массива
? 98
23 13 98

Заполнение одномерного массива заранее известными значениями из оператора DATA

Часто встречаются задачи, когда данные для обработки уже известны и содержатся в операторе data. (Однако, если их много, тяжелый труд — их туда заносить. Обычно — работа для молодых программистов.)

DATA 23, 13, 98, 77, 45, 56, 32,' 10, 90, 55
CLS
INPUT "Введите количество элементов массива"; N
DIM MASS(N)
FOR 1=1 ТО N
READ MASS(I)
? MASS(I); NEXT I

Программа стала несколько короче, т. к. в этом случае можно совместить чтение данных из data и одновременный вывод их на экран — ведь пользователь освобожден от необходимости вводить данные с клавиатуры. Мы сразу увидим массив на экране.
Этот способ экономичней первого, и, кроме того, при отладке программы нет нужды всякий раз заново вводить данные.

Заполнение массива при помощи стандартных функций

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

CLS
RANOMIZE TIMER
INPUT "Введите количество элементов массива"; N
DIM MASS(N)
FOR 1=1 ТО N
MASS(I)=INT(RND(l)*100)
? MASS(I); NEXT I

Мы вычисляем какую-либо функцию, например синус, и значения этой функции заносим в массив. Пусть дана функция y-sinx , где х меняется от 1 до 10 с шагом 0,5. Здесь мы должны сначала решить для себя, а сколько будет значений вычислено. Мы это уже делали, но, повторение — мать учения.

N=(Хнач. — Хкон.)/шаг+1

В нашем случае:

N=(10-1)/0.5 +1=19

Тогда программа будет выглядеть так:

CLS
INPUT "Введите начальное, конечное значения аргумента
и шаг приращения"; XN, XK, DX
N=INT((XK - XN)/DX)+1
DIM MASS(N)
1=1
FOR X=XN TO XK STEP DX
MASS(I)=SIN(X)
? MASS(I);
1=1+1 NEXT X

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

MASS(1!=13
MASS(3)=12
MASS(3)=SQR(MASS(1)+MASS(3))
? MASS(3)

Вопрос. Какое значение будет выведено на экран? Чему равны значения mass ( i ) и mass (3) ?
Задания. Прежде всего попрактикуемся в заполнении массивов и выводе на экран не только численных значений элементов массива, но и графической их интерпретации.
236. Заполните массив десятью случайными целыми числами, каждое их которых лежит в пределах от 50 до 200, и выведите на экран их численные значения, а также графическое представление в виде вертикальных закрашенных прямоугольников шириной 30, и высотой, соответствующей их значению. Нижние стороны прямоугольников лежат на линии с координатой Y=300, левой стороне первого прямоугольника соответствует координата Х=100 (рис. 1.67).
237. Заполните массив десятью случайными целыми числами, каждое их которых лежит в пределах от 5 до 30, и выведите на экран их численные значения, а также графическое представление в виде закрашенных соприкасающихся кругов, радиусы которых равны значениям элементов массива (рис. 1.68).

Рис.1.67. Столбиковая интерпретация одномерного массива

Рис.1.68. Круговая интерпретация одномерного массива

238. Напишите программу вычисления среднего арифметического содержащихся в операторе data следующих десяти чисел: 31, 19, 52, 65, 6, 8, 13, 16, 97, 33.
239. Напишите программу вычисления выражения:

где х, — числа из оператора data предыдущего задания;
N— их количество; S — среднее арифметическое элементов массива х.
240. Найти сумму 1-го, 4-го, 9-го, 16-го и 81-го элементов массива, состоящего из 100 целых случайных чисел, каждое из которых лежит в пределах от 2 до 22.
241. Замените в массиве из 10 случайных целых чисел, каждое из которых лежит в пределах от 1 до 10, все четные элементы нулями и выведите полученный массив на экран.
242. Массив состоит из 60 случайных двузначных целых чисел. Выведите их на экран в обратном порядке по 6 чисел в строке.
243. В массиве содержатся 10 букв — С, Ф, О, И, К, Л, О, И, Л, Н. Выведите на экран слово, образованное буквами с четными индексами, и слово, образованное буквами с нечетными индексами.
244. Массив состоит из 20 целых положительных и отрицательных чисел, модуль каждого из которых в пределах от 2 до 12. Выведите на экран сначала отрицательные, а затем положительные числа. Определите, модуль суммы каких чисел больше — положительных или отрицательных.
245. Найдите максимальный и минимальный элементы массива из 10 случайных целых двузначных чисел и разность между ними. Представьте графическую столбиковую интерпретацию этого массива, выделив максимальный элемент красным, а минимальный — зеленым цветом. Остальные прямоугольники должны быть желтого цвета.
Если в программе используется несколько массивов, то они могут быть описаны через запятую, например:

DIM Х(10) , Y(10) , W$ (20)

Теперь задания с несколькими массивами.
246. Даны два массива, заполненные каждый десятью случайными целыми числами, каждое из которых от 1 до 9 включительно. Сложите массивы поэлементно, результаты запишите в третий массив. На экран вывести все три массива.
247. Даны три массива с одинаковым количеством элементов 5, в которых содержатся стороны треугольников Aj, Bj и Q. Определите периметр Pj и площадь S; каждого треугольника по формуле Герона. (Так как для того, чтобы треугольник существовал, необходимо определенное соотношение его сторон, то лучше элементы массивов задать в операторе
DATA.)
248. Найдите скалярное произведение двух массивов А и В, состоящих из 5 элементов каждый, которые содержат случайные числа от 2 до 9 включительно. Воспользуйтесь формулой:

где n — размер массива.
249. Найдите соотношение sx/sy, где sx и sy — средние арифметические значения массивов X и Y. соответственно. (Массивы из 10 элементов содержат случайные двузначные целые числа.)
250. Определите объем каждого из 10 цилиндров, для которых заданы радиусы оснований Rj (случайные целые числа от 5 до 25 см) и высоты Hj (случайные целые числа от 10 до 30 см).
251. Заданы 10 пар координат Xj, Yj одних точек на плоскости и 10 пар координат Aj, Bj других точек на плоскости. Вычислите попарно расстояния между точками по формуле:
Занесите эти расстояния в массив S. Проиллюстрируйте задачу графически (соответствующими отрезками на экране). Выделите разными цветами наибольшую и наименьшую длину.
252. Дан одномерный массив W из 10 случайных целых чисел, каждое из которых лежит в пределах от 1 до 100. Получите новый массив R, где каждый элемент создается из массива W делением соответствующего элемента на его индекс.
253. Вычислите и представьте в виде массива последовательность первых 20 чисел Фибоначчи, если Xi~l, X2=2, а каждый последующий элемент равен сумме двух предыдущих.
254. В операторе data содержатся данные о среднесуточной температуре в течение февраля 2000 г. по Санкт-Петербургу. Вычислите среднюю температуру февраля, наибольшую и наименьшую температуры. Постройте линейный график изменения среднесуточной температуры.
255. Школьники неохотно носят одежду, отличающуюся по цвету от одежды одноклассников. Напишите программу, выбирающую 2 цвета (для мальчиков и для девочек) из 12 возможных цветов, которые сегодня будут носить все. Выбор производится случайным образом и сопровождается выводом на экран прямоугольников соответствующих цветов, внутри одного из которых написано "Сегодня этот цвет для мальчиков", а внутри другого "Сегодня этот цвет для девочек".
256. В фирме "Green Beavis Ltd" работают семь сборщиков компьютеров. Для того чтобы повысить производительность их труда, в конце недели обрабатывают сведения о количестве компьютеров, собранных каждым из них ежедневно. Напишите программу, которая выдаст на экран следующие данные:

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

257. Дан массив X, состоящий из 100 целых случайных чисел, каждое из которых лежит в пределах от 3 до 13. С клавиатуры вводится целое число N, также лежащее в этих пределах. Определите количество элементов массива, равных числу N.
258. Даны два числовых массива X и Y с количеством элементов 10 и-20, соответственно. Получите массив Z из 30 элементов, составленный добавлением массива X в коней массива Y.
259. Дан массив из 20 случайных целых чисел, каждое из которых лежит в пределах от 10 до 50. Найдите максимальное число и его номер, а если таких чисел несколько, то подсчитайте, сколько их.
260. Дан массив из 20 случайных целых чисел, каждое из которых лежит в пределах от 10 до 50. Определите среднее арифметическое элементов массива, а также значение элемента, ближайшего к среднему, и его номер.
261. Дан массив среднемесячных температур за год. Определите, в каком месяце была самая высокая температура, а в каком самая низкая, а также среднесезонные температуры.
262. У автора этой книги была копилка, в которой было 100 советских монеток достоинством в 1, 2, 3, 5, 10, 15, 20 и 50 копеек. Задайте массив М(100) случайным образом из этого набора, а затем подсчитайте, сколько в копилке было пятачков и полтинников, и какова общая сумма накопленного.
263. Дан массив из десяти целых двузначных случайных чисел. Найдите сумму трех максимальных из них.
264. Заполните массив R(25) случайными целыми двузначными числами так, чтобы числа не повторялись.
265. Программа "Пожиратель звезд". Когда мы говорили о циклах и построении графиков функций, то писали программу о движении "звездолета", который, пролетая по траектории заданной тригонометрической функции, уничтожал планету, находящуюся от него в опасной близости. Теперь, со знанием массивов, мы можем написать более красивую и более сложную программу. Сначала заполним экран тысячью разноцветных звезд, изображенных либо точками, либо окружностями радиусом 1. Координаты всех звезд запоминаются в массивах Х( 1000) и Y(1000). Затем по траектории


начинает двигаться кавалькада. Впереди сторожевой звездолет (закрашенный круг радиусом 2), проверяющий, не находится ли какая-нибудь звезда в опасной близости от армады (S<=30), и уничтожающий ее в таком случае (звезда заменяется точно такой же, но цветом фона). Позади движутся три крейсерских звездолета (закрашенные круги радиусом 4). В результате выполнения программы на экране должен быть проложен коридор по траектории функции с шириной 60 экранных точек (рис. 1.69).

Рис.1.69. "Пожиратель звезд"

266. Напишите программу "Сторож", которая бы заставила змейку (рис. 1.70) оббегать стороны экрана по часовой стрелке (это можно написать и без массива). Усложните программу, взяв на службу еще одну "змейку". Теперь они ползают друг за другом (рис. 1.71). Еще сложнее — программа для движения змейки, управляемой стрелками или буквенными клавишами и совершающей повороты под прямым углом. А если и это все по плечу, то заставьте змейку поворачивать еще и под углом 45°.

Рис.1.70. "Сторож-змейка"

Рис.1.71. "Пожиратель звезд"


Простейшие сортировки

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

Сортировка выбором

Допустим, дан числовой массив из N элементов. Надо отсортировать его по возрастанию.
Суть способа в следующем. Находим наибольший элемент в массиве и меняем его местами с последним. Уменьшаем количество рассматриваемых элементов на 1 (т. к. последний элемент уже на своем месте). Повторяем о'перацию для уменьшенного на единицу массива. И так — N—1 раз.
Пусть дан массив из пяти элементов:

8 4 9 6 7

Рассмотрим процесс упорядочивания по шагам.

На этом шаге третий элемент поменялся сам с собой.

267. Напишите программу для упорядочивания массива по возрастанию методом выбора. Измените программу так, чтобы она упорядочивала массив по убыванию.
268. Дан массив из 13 чисел. Расположите числа по возрастанию. Введите с клавиатуры число М так, чтобы оно вошло в массив и получившийся массив также был бы упорядочен по возрастанию.

Метод обмена или "пузырька"

Название данного метода часто вызывает нездоровый смех у молодежи, хотя никакого тайного смысла у этого метода нет. Просто он выполняется таким образом, что максимальное число после каждого шага сортировки как бы всплывает в конец массива, на свое заслуженное место. Заключается метод в следующем. Программа, начиная с первых элементов массивов, сравнивает эти элементы попарно, и, в случае, если они расположены не по возрастанию, меняет их местами. В результате (N -I)2 перестановок (в случае самого плохого расположения элементов массива — все элементы по убыванию) массив окажется упорядочен по возрастанию. Например, есть массив из четырех элементов:

4 3 2 1

Рассмотрим по шагам метод "пузырька" для этого массива.

269. Напишите программу, реализующую метод "пузырька". Для уменьшения количества ненужных сравнений может служить счетчик, подсчитывающий количество обменов за один полный пробег вдоль всего массива. Как только его значение станет равно нулю (т. е. ни одного нового обмена не будет произведено), это будет означать, что массив упорядочен. Для наглядности оформите исходный и получившийся массив в виде столбиковых интерпретаций друг под другом.
270. Дан массив букв, составляющих английский алфавит, но размешенных не по порядку. Напишите программу, преобразующую этот массив в алфавит английского языка.
271. Дан массив из 13 четырехбуквенных русских слов (существительных и нарицательных), в единственном числе, в именительном падеже. Упорядочить их по алфавиту.


Двумерные массивы

Что такое двумерный массив? Это такой набор однотипных данных, местоположение каждого элемента которого определяется не одним индексом, а двумя. Например, для тех, кто с детства играл в "морской бой", не будет открытием, что каждая клеточка игрового поля обозначается двумя символами — буквой и цифрой, например, А5 — "мимо", И10— "попал", Ж7 — "убит". Только в Бейсике принято в качестве индексов использовать все же целые числа. Жизненный пример применения двумерных массивов — билеты в кино или театр, имеющие для каждого зрителя две координаты — ряд и место'.
Описываются подобные массивы в Бейсике тем же оператором dim, после которого в скобках указываются две размерности массива — количество строк и количество столбцов. Например, массив 5x3 объявим так:

DIM X(5, 3)
X (If 1) X [1, 2) X (1, 3) X (1. 4) X (1, 5)
X (2, 1) X (2, 2) X (2, 3) X (2, 4) X (2, 5)
X (3, 1) X (3, 2) X (3, 3) X (3, 4) X (1, 5)

' Кстати, маленькое лирическое отступление. Откуда пошла традиция указывать на билетах ряд и место? Оказывается из Франции. Когда тамошние дворяне при шпагах и гордом характере приходили в театр, имея просто билет без указания места, то нередко возникали смертоубийственные стычки из-за этих самых мест. Королю это надоело, и он обратился за помощью к ученому Декарту, который и предложил систему — "ряд—место". Эта система в дальнейшем трансформировалась в привычную нам декартову систему координат — ось X, ось Y.

Заполнение двумерных массивов и вывод их на экран

В обработке двумерных массивов есть своя специфика — использование вложенных циклов.
Заполним двумерный массив Х(3, 5) целыми случайными числами, лежащими в интервале от 1 до 20 и выведем массив на экран в виде таблицы.

CLS : RANDOMIZE TIMER DIM X(3, 5) FOR I =1 ТО 3 FOR J=l TO 5
X(I, J)=INT(RND(l)*20)+l ? X(I, J); NEXT J
NEXT I

На что надо обратить внимание. Для начала, при выводе массива во внутреннем цикле после оператора print стоит точка с запятой. Это дает возможность отображать массив построчно. А оператор print без параметров, указанный после внутреннего цикла, позволяет после вывода каждой строки элементов массива, переводить курсор на новую строчку.
272. Найдите в массиве из приведенного выше примера максимальный и минимальный элемент, и, при выводе массива на экран, выделите их красным цветом.
273. Дан двумерный массив 5x5. Определите сумму элементов каждой строки и ту строку, в которой сумма элементов максимальна.
274. Дан массив А(2, 10). В первом столбце содержатся координаты X точек плоскости экрана, а во втором столбце — координаты Y тех же точек. Определите количество точек, попадающих в нижнюю правую четверть экрана, выведите их на экран, а искомые точки выделите другим цветом.
275. Определите наименьший элемент в массиве Х(10, 10). Выделите его другим цветом.
276. Дан массив W$(5, 4), в котором каждая строка состоит из четырех символов, составляющих английское слово. Отсор-
тируйте массив таким образом, чтобы слова были расположены по алфавиту.
277. В массиве R (5x5) поменяйте местами первую и последнюю строки.
278. В массиве R (5x5) замените элементы, стоящие ниже главной диагонали, нулями.
279. В массиве R (5x5) замените элементы главной диагонали нулями.
280. В массиве R (5x5) вычислите сумму элементов главной диагонали.
281. В массиве R (5x5) упорядочьте строки по возрастанию элементов главной диагонали.
282. Определите, является ли заданный массив 3x3 магическим квадратом, т. е. таким, суммы элементов которого в строках, столбцах и главных диагоналях равны между собой.
283. Выведите на экран номера строк массива 5x5, сумма элементов которых четна.
284. Выведите на экран изображение Андреевского флага, если у данного массива 5x5 суммы элементов диагоналей равны, и флаг Японии — в обратном случае (рис. 1.72, 1.73).

Рис.1.72. Андреевский флаг (суммы элементов диагоналей равны)

Рис.1.73. Флаг Японии (суммы элементов диагоналей не равны)

285. Одномерный массив из N элементов свернуть по спирали в квадратную матрицу размерностью корень квадратный из N по следующему образцу.
286. Исходный массив Sl(16) состоит из следующих элементов: 3, 5, 9, 7, 12, 34, 21, 13. 6, 89, 54, 66, 2, 10, 99, 55.
Создайте массив S2(4, 4), вид которого представлен на рис. 1.74.

Рис.1.74. Преобразованный в спираль одномерный массив


Подпрограммы

Иногда в определенных местах программы приходится выполнять практически одни и те же последовательности действий с разными исходными данными. Такие последовательности действий можно оформить в виде так называемых подпрограмм (от англ. "subroutine"). Подпрограммы сокращают текст программы, существенно уменьшают время их исполнения, облегчают жизнь программистам, которые могут создавать программы модульно, т. е. собирая сложную программу из законченных кусочков более простых составляющих. Это позволяет создавать большие программы группой программистов, разрабатывать и реализовать группе школьников какие-либо глобальные проекты.
Для примера использования процедуры приведем программу вычисления следующего выражения:

Z=N!/M!*(N-M)!

Переменные N и М, а также выражение (N—М) снабжены восклицательным знаком, который в математике означает не что иное, как факториал (например, N-факториал). Факториал — это произведение натуральных чисел от 1 до N включительно. Например, 3!=1х2хЗ=6, а, например, 6! — это уже 1x2x3x4x5x6=720.
В выражении нам три раза придется вычислять факториал, производя при этом одни и те же действия с разными числами. Нам облегчит работу подпрофамма, которую мы разместим в конце основной профаммы и назовем, например, fact. В подпрофам-ме мы опишем, как вычислить факториал вообще, а затем из основной программы обратимся к подпрофамме три раза с различными параметрами. Вот как будет выглядеть проuhамма:

CLS
1 : INPUT "Введите значения N и М"; N, М
K=N
GOSUB FACT
Х1=Р
К=М
GOSUB FACT
Х2=Р
K=(N-M)
GOSUB FACT
Z=X1/(X2*P)
PRINT "Искомое выражение равно"; Z
PRINT "Еще одно выражение?(Y/N): INPUT а$
IF UCASE$(a$)="Y" THEN 1 ELSE PRINT "До новых встреч
у монитора..." END
' Описание подпрограммы FACT для вычисления факториала
FACT:
Р=1
FOR i=l TO К
P=P*i NEXT i RETURN

Рассмотрим работу программы. Начало стандартное: очистка экрана, запрос с клавиатуры исходных данных. Самое интересное начинается потом. Подпрограмма fact описана после слова end основной профаммы, что обусловлено простым желанием, чтобы профамма все же не зациклилась, а когда-нибудь все-
таки завершилась. Параметром подпрограммы является переменная к, для которой и вычисляется факториал.
В основной программе мы присваиваем переменной к значение переменной n, для которой мы хотим вычислить первый факториал из трех. После чего необходимо обратиться к подпрограмме. Для этого существует специальное слово gosub, после которого указывается имя подпрограммы (в нашем случае fact). Управление переходит на первый оператор, содержащийся в подпрограмме, затем выполняются все операторы подпрограммы, вплоть до ключевого слова return. Это означает, что подпрограмма закончилась, и управление передается в основную программу.

Предупреждение
Ключевое слово RETURN передает управление в основную программу на оператор, следующий за обращением к подпрограмме GOSUB.

Результатом выполнения подпрограммы в нашем случае является переменная р, в которой сохраняется значение факториала. Запомним первое полученное значение (фактически N-факто-риал) в переменной xi. Это необходимо сделать, т. к. подпрограмма будет выполняться несколько раз, и значение переменной р будет меняться.
Затем мы повторяем действия для переменных м и (n-m) , соответственно. Причем, в последнем случае уже не надо запоминать полученное значение факториала в новой переменной, т. к. больше обращений к подпрограмме не будет. Осталось вывести на экран полученное значение и запросить пользователя, будет ли он работать с программой еще.
Если непонятно, запустите пошаговый режим исполнения этой программы, разберитесь, как она работает (клавиша <F8>).

Предупреждение
Привыкайте оформлять самостоятельные куски программ в виде подпрограмм. Это способствует четкой структуризации, описанию внутренних логических связей и пониманию со стороны коллег-программистов, что не маловажно. Программирование с использованием подпрограмм — это хороший стиль!

Итак, если все ясно, то надо бы выполнить ряд упражнений с использованием подпрограмм.
287. Для каждого двумерного массива Х(3, 4), Y(5, 3), Z(4. 6) определите номер строки с максимальной суммой положительных элементов.
288. Напишите программу, предлагающую пользователю меню из десяти функций, и строящую по ним графики этих функций в зависимости от выбора пользователя.
289. Напишите программу для младших школьников, проверяющую знание ими таблицы умножения от 2 до 12. Учащемуся задаются 5 примеров перемножения случайных чисел в заданном интервале. Оценкой является количество правильных ответов. Используйте подпрограмму для печати замечаний в ответ на каждый результат, вводимый пользователем. За правильный ответ— замечание должно быть поощрительным, за неправильный — сожалеющим. Чтобы сделать опрос более интересным, необходимо заготовить по десять замечаний для правильных и неправильных ответов и выбирать их случайным образом, обращаясь при этом к пользователю по имени, запрошенному в начале программы. Сделайте красочную заставку, легкое музыкальное сопровождение тоже не будет лишним.
290. Напишите программу, отображающую цветное кольцо. Используя ее в качестве подпрограммы, нарисуйте олимпийский флаг.
291. Напишите программы, находящие минимальное и максимальное значения из трех чисел X, Y и Z, введенных с клавиатуры. Используя их в качестве подпрограмм, напишите программу, вычисляющую значение следующей функции:

292. Даны два одномерных массива из 20 элементов каждый. Элементом является случайное целое двузначное число. Напишите программу с использованием подпрограммы, которая изменяет исходный массив путем деления четных чи сел на их индексы. Используя эту подпрограмму, определите, в каком из массивов было произведено больше замен.
В заключение несколько слов о подпрограммах в Russian Quick Basic. Мы привели самый простой способ написания и использования подпрограмм. Но если вы чувствуете в себе силы, то попробуйте самостоятельно разобраться с такими мощными инструментами Бейсика по написанию подпрограмм, как declare sub и call sub. He пожалеете!


Работа с файлами

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


Файловая система

Информация, вводимая с клавиатуры или обрабатываемая с помощью программных средств Бейсика размещается в оперативной памяти компьютера, которая является энергозависимой, и, как только мы выключим питание, вся наша информация погибнет. Чтобы избежать это и донести наши гениальные программы по крайней мере до преподавателя (чтобы он их достойно оценил), а лучше до далеких потомков, необходимо сохранять наши работы на диске в виде файлов.
Файл — это поименованная область на магнитном или лазерном диске. Поименованная — значит, имеющая имя. В файлах могут содержаться тексты, графические и видеоизображения, звуки и музыка, таблицы и базы данных и многое другое, но нас интересуют прежде всего программы, написанные на Бейсике и данные для этих программ.
Мы уже объясняли в самом начале, как сохранить программу в виде файла и открыть уже существующий файл. Имя файлу мы даем сами, но к нему есть некоторые требования:

имя не должно быть больше чем 8 символов; имя может состоять из букв латинского алфавита, цифр и символов, например, _, -, (,), $ и некоторых других. Впрочем, злоупотреблять специальными символами не стоит — букв и цифр вполне хватает; в имени файла запрещены символы <Пробел>, *, точка, запятая, кавычки, двоеточие.

У файла также есть расширение имени. Оно имеет длину не более трех символов, указывается через точку после имени и характеризует тип файла. Изучаемая нами версия Бейсика (как, впрочем, и практически все другие) автоматически при сохранении добавляет к имени файла расширение bas, что упрощает поиск написанных нами программ и работу с ними.
Для того чтобы хранить свои файлы и результаты работы с ними на диске, лучше завести свой личный каталог (или папку — это одно и то же). Надеюсь, вы знаете как это делается.
В файлах вы можете хранить как исходные данные для обработки, так и результаты работы вашей программы.
Для работы в Бейсике нам чаще нужны файлы, хранящие однородные по типу или структуре сведения о каких-либо объектах. Набор данных о каком-либо одном объекте называется записью.
За самой последней записью находится невидимый символ конца файла, который устанавливается автоматически. Файл может быть пустым, т. е. содержать 0 байт информации, но имя файла и символ конца файла будут присутствовать всегда. Таков закон.
Записи могут содержать данные разных типов, но должны быть обязательно одинаковы по структуре, например:

"Запорожец", "4067 ЛДЕ", "1972", "100$"
"ГАЗ-34", "6666 ЛАА", 1989, "3500$"

В соответствии со способом доступа к файлам они делятся на два вида.


Способы доступа к файлам

В изучаемом нами Бейсике существуют два метода доступа к информации, хранящейся в файлах:

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

Файлы последовательного доступа наиболее просты как в организации, так и в работе с ними. Записи обрабатываются последовательно одна за другой. Информация в таких файлах хранится в виде текста в кодах ASCII. Подобные файлы легко просмотреть на экране, используя любой простейший редактор, или в самом Бейсике. Но, как всегда, у каждой медали две стороны. Простота — хорошо, а последовательность в данном случае — плохо. Если информация об интересующих меня объектах упорядочена в файле по алфавиту, то мне всякий раз придется перебирать практически весь файл, чтобы добраться до нужной записи. Отсюда, при большом информационном объеме файла обработка его резко замедляется.
Файлы прямого доступа хранят информацию в специальном формате, в котором каждая запись занимает строго фиксированную одинаковую с остальными длину. То, что такие файлы могут занимать на диске больше места, чем файлы последовательного доступа, с лихвой компенсируется скоростью работы с ними.

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


Операции над файлами

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

открытие файла; чтение и запись обрабатываемых данных; закрытие файла.

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


Открытие файла

Для открытия файла предназначен оператор open, имеющий следующий формат:

OPEN имя_файла FOR режим AS # номер файла

С именем файла должно быть уже все понятно. Режим определяет доступ к данным файла. Возможны следующие режимы:

input. Это режим чтения информации из файла. В случае, если указывается несуществующее имя файла, возникнет сообщение об ошибке "Файл не найден". output. Режим записи информации в файл. Обычно при этом создается новый файл. Если же открывается для записи уже существующий файл, то ранее хранимая в нем информация будет безвозвратно утеряна. append. Режим добавления информации в файл. Новая информация будет размешена в конце файла, за последней записью.

Номер файла предваряется необязательным знаком #, после которого следует целое число от 1 до 255.

Запись в файл

Рассмотрим пример записи в файл.

OPEN "capitals.dat" FOR OUTPUT AS #1 FOR X=l TO 5
INPUT "ВВЕДИТЕ НАЗВАНИЕ СТОЛИЦЫ"; F$
PRINT #1, F$ NEXT X CLOSE #1 END

В результате работы программы мы получим (полужирным шрифтом выделены данные, вводимые пользователем с клавиатуры):

ВВЕДИТЕ НАЗВАНИЕ СТОЛИЦЫ? МОСКВА ВВЕДИТЕ НАЗВАНИЕ СТОЛИЦЫ? САНКТ-ПЕТЕРБУРГ ВВЕДИТЕ НАЗВАНИЕ СТОЛИЦЫ? ТАЛЛИН ВВЕДИТЕ НАЗВАНИЕ СТОЛИЦЫ? РИГА ВВЕДИТЕ НАЗВАНИЕ СТОЛИЦЫ? ВИЛЬНЮС

При этом на диске в текущем каталоге образуется файл, содержащий пять строковых значений. Имя файла будет capitals.dat.
Удобнее всего при работе с файлами сделать текущим каталог, где эти файлы содержатся или будут содержаться, а при обращении к ним указывать только их имена.
В качестве параметра имя_файла можно использовать переменную текстового типа. Это позволяет вводить имя файла с клавиатуры и является универсальным способом работы с файлами. Например:

INPUT " Введите имя файла "; FileName$ OPEN FileName$ FOR OUTPUT AS #1

После ключевого слова as указывается номер файла. Больше открыть файл с таким номером в данной программе нельзя. Для каждого последующего файла должен быть указан свой собственный неповторимый номер в пределах от 1 до 255. Сколько всего может быть открыто файлов, зависит от файла конфигурации вашего компьютера config.sys, в котором число одновременно открытых файлов определяется командой files.

Предупреждение
Во избежание неприятностей не открывайте одновременно слишком много файлов. Рекомендуется по окончании работы с файлом сразу закрыть его.

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

' Программа создания файла данных об автомобилях
CLS
INPUT " Введите имя файла"; F$
' Открытие файла
OPEN F$ FOR OUTPUT AS #1
DO
INPUT "Марка автомобиля? (Для окончания работы введите QWE.); М$
IF UCASE$(M$)="QWE" OR UCASE$(M$)="ЙЦУ" THEN 1
INPUT "Номер автомобиля?"; N$
INPUT "Цвет автомобиля?"; С$
INPUT "Год производства автомобиля?"; G$
INPUT "Продажная цена автомобиля?"; S$
WRITE #1, М$, N$, C$, G$, S3 LOOP
' Закрытие файла 1 : CLOSE #1 PRINT "Файл сформирован"

Программа действует следующим образом. Запрашивает имя файла, открывает его для записи, запрашивает информацию, записывает ее в файл до введения пользователем сочетания букв "QWE" или "ЙЦУ" (эти символы расположены на одних клавишах, вследствие чего пользователь может случайно набрать как одну комбинацию, так и другую). Запись в файл может производиться операторами

PRINT # номер_файла, выражение

ИЛИ

WRITE # номер_файла, выражение

Результат работы этих операторов одинаков.

Для закрытия файлов применяется оператор

CLOSE # номер_файла

Предупреждение
Если номер файла в операторе close указан, то будет закрыт именно этот, вполне определенный файл. Если же номер не указан, будут закрыты все открытые файлы.

Наберите эту программу с именем создаваемого файла avto.dat
Занесите сведения о пяти автомобилях: двух "Москвичах" и трех "Волгах". После чего просмотрите созданный вами файл в редакторе Бейсика. Для этого надо в меню Файл выбрать команду Открыть, затем в появившемся диалоговом окне ввести имя файла avto.dat и нажать клавишу <Enter>. Вы увидите, что данные в файле записаны в кавычках, через запятую, т. е. все они текстового типа.

Чтение из файла

Чтение из файла производится аналогично записи, но — вместо режима output используется режим input. Будьте внимательны! Прочитаем занесенные нами данные из файла avto.dat.

' Программа чтения файла данных об автомобилях
CLS
INPUT " Введите имя файла"; F$
1 Открытие файла
OPEN F$ FOR INPUT AS #1
PRINT "База данных автомобилей на 17 декабря 2000 года"
1=1
DO
PRINT "Вывести данные об"; I; "автомобиле?"
INPUT "Для окончания введите QWE, для продолжения — <Enter>"; M$
IF UCASE$(M$)="QWE" OR UCASE$(M$)="ЙЦУ" THEN 1
INPUT #1, M$, N$, C$, G$, S$
PRINT M$, N$, C$, G$, S$
1=1+1 LOOP UNTIL EOF(l) 1 Закрытие файла 1 : CLOSE #1 PRINT "Файл закрыт"

Обратите внимание на оператор loop until eof(D. Он означает, что считывание ведется до тех пор, пока не будет обнаружен символ конца файла (end of file), а в скобках указан номер открытого файла.
Выведите с помощью этой программы данные о первых трех автомобилях.

Изменения данных в файле

Для изменения какой-либо записи, удаления старых или добавления новых данных в последовательном файле необходимо открыть два файла: подлежащий изменению и новый, в котором создается обновленная версия исходного файла. Старый файл в дальнейшем можно удалить. Приведенная ниже программа в файле avto.dat изменяет "МОСКВИЧ" на "МЕРСЕДЕС". В первых строках открываются исходный файл avto.dat и новый файл avto2.dat, сначала пустой. Очередная запись считывается из файла avto.dat и, при условии, что это не "МОСКВИЧ", переписывается без изменения в новый файл. Если же встречается значение "МОСКВИЧ", то оно заменяется на "МЕРСЕДЕС" путем присваивания нового значения переменной м$. В следующей строке данное значение попадает в выходной файл. После того как весь входной файл просмотрен, оба файла закрываются.

OPEN "avto.dat" FOR INPUT AS #1 OPEN "avto2.dat" FOR OUTPUT AS #2 FOR 1=1 TO 5
INPUT #1, M$, N$, C$, G$, S$
IF UCASE$(M$)="MOCKBM4" THEN М$="МЕРСЕДЕС"
PRINT #2, M$, N$, C$, G$, S$ NEXT I CLOSE 1, 2 KILL "avto.dat"
NAME "avto2.dat" AS "avto.dat" END

Заключительный этап — удаление исходного и переименование нового файла, которому придается прежнее имя, что обеспечивает и в дальнейшем наличие на дискете файла avto.dat.

Добавление данных в файл

Указание for append в операторе open подготавливает файл для вывода данных и смещает указатель на конец файла. Последующие операторы приписывают новую информацию к уже имеющейся. В предложенной далее программе в файл данных об автомобилях добавляются сведения о двух новых поступлениях.

' Программа создания файла данных об автомобилях
CLS
INPUT " Введите имя файла"; F$
' Открытие файла
OPEN F$ FOR APPEND AS #1
DO
INPUT "Марка автомобиля? (Для окончания работы введите QWE.); М$
IF UCASE$(M$)="QWE" OR UCASE$(M$)="ЙЦУ" THEN 1
INPUT "Номер автомобиля?"; N$
INPUT "Цвет автомобиля?"; С$
INPUT "Год производства автомобиля?"; G$
INPUT "Продажная цена автомобиля?"; S$
WRITE #1, М$, N$, C$, G$, S$ LOOP
' Закрытие файла 1 : CLOSE #1 PRINT "Файл дополнен"

Выполните упражнения.
293. Школе необходим последовательный файл для учета выпускников.

Создайте последовательный файл для канцелярии по учету выпускников. Храните в нем фамилию, имя, год выпуска, любимый вид спорта и нынешний род занятий выпускника. Для образца составьте файл на десять человек. Воспользуйтесь этим файлом и напечатайте приглашения на очередной домашний матч "Зенита" тем выпускникам, которые назвали футбол своим любимым видом спорта.

294. Компьютерная фирма ведет файл со сведениями о двадцати своих сотрудниках.

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

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

Напишите программу ввода данных; заполните файлы для трех регионов. Просмотрите все три файла и подсчитайте средний уровень снежных осадков по трем областям. Результат выведите на экран.

296. Налоговая инспекция поощряет налогоплательщиков, вносящих подоходный налог до истечения апрельского контрольного срока, делая им скидку.

Создайте файл, в котором содержались бы имена, сведения о сроках уплаты и размере налога для каждого налогоплательщика (ограничьтесь группой из шести человек). Пусть ваша программа читает файл и делает скидку в 10% для тех, кто уплатил налог досрочно, а также выводит на экран их имена и размер скидки в рублях.

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

Напишите программу, которая создала бы последовательный файл контрагентов. Напишите программу, которая создала бы два последовательных файла с именами good.dat и bad.dat соответственно для фирм с высокой и низкой кредитоспособностью. Пусть ваша программа спрашивает у бухгалтера, какой из двух списков ему представить, а затем выдает названия фирм и их местоположение из соответствующего файла.

298. Предположим, адвокат Михаил Бурщевский с помощью компьютера ведет учет своих клиентов и их дел (табл. 1.4).

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

Таблица 1.4. Исходные данные задачи

Имя клиента Обвинение Исход дела
Сердюков Клевета Выиграно
Прохоров Оскорбление Проиграно
Мицкевич Поджог ?????
Максимова Взлом Выиграно
Лерман Взятка Проиграно

299. Хоккейные команды "Черные ястребы" и "Красные крылья" хранят в последовательных файлах имена всех своих двенадцати нападающих, число заброшенных ими шайб, сделанных голевых передач и заработанное штрафное время.

Создайте файлы black.dat и red.dat, содержащие информацию о каждой из двух команд. Ваша программа по данным, извлеченным из этих файлов, должна создавать новый файл allstars.dat, в котором содержались бы имя, команда и сумма очков (голы и передачи) для шести лучших игроков обеих команд. Пусть имена и показатели результативности хоккеистов выводятся на экран.

300. Имена и адреса всех, кто обращается за информацией в фирму, попадают в список рекламной рассылки.

Создайте основной файл master.dat из десяти записей в качестве списка рассылки и меньший файл family.dat из пяти записей для вновь обратившихся с запросами в фирму. Добавьте данные из второго файла в конец первого. Напишите программу, которая случайным образом выбирала бы из основного файла одну запись и посылала бы адресату письмо с уведомлением о выигрыше приза.

301. Инспектор колледжа ведет файл академических занятий студентов.

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

Таблица 1.5. Исходные данные

Фамилия студента Курс Оценочный коэффициент
Югов
Программирование
78
Северов
Японский язык
91
Западов
Психология
56
Востоков
Психология
45
Зюйдов
Корейский язык
89
Вестов
Программирование
66
Полюсов
Психология
90

Выберите "умных" студентов, т. е. тех, кто имеет оценку выше 88, и запишите сведения о них в файл best.dat. Пусть программа помогает инспектору формировать на основе этого файла группы углубленного обучения. По названию курса она должна выдавать список "умных" студентов, зачисленных в такую группу.