Цикл с постусловием: repeat..Until
Цикл с постусловием напоминает цикл с предусловием. Отличие заключается в том, что проверка выхода из цикла выполняется в конце цикла. Блок-схема цикла приведена ниже:
Как видно из блок-схемы операторы тела цикла будут выполняться пока условие ложно. Выход из цикла выполняется, когда условие приобретает значение истина.
Синтаксис оператора имеет следующий вид:
Repeat
<операторы>
Until <условие>;
Если перевести на русский язык, получим: повторять операторы тела цикла до тех пор, пока условие ложно.
Следует отметить, что в данной конструкции последовательность операторов, определяющих тело цикла, не заключается в операторные скобки begin.. end., поскольку ими служит пара операторов repeat..until.
При использовании цикла repeat..until следует иметь в виду следующее:
1. Цикл обязательно выполнится хотя бы один раз;
2. Хотя бы один из операторов тела цикла должен влиять на условие выполнения цикла, иначе цикл будет повторяться бесконечное число раз;
Пример 1.Найти сумму ряда чисел: 1+1/2+1/3+…1/100 с использованием цикла repeat.
Var
i :integer;
sum:real;
begin
sum:=0; i:=1;
repeat
sum:=sum+ 1/i;
i:=i+1;
until i>100;
end;
Пример 2. Рисовать концентрические прямоугольники с центром в середине экрана, пока они входят на экран. Внешний вид экрана приведен на рисунке:
Программный код имеет следующий вид:
var x0,y0:integer;
sh,i:integer;
begin
sh:=10; {расстояние между прямоугольниками}
{ координаты левого верхнего угла}
x0:=width div 2 - sh; y0:=height div 2 - sh ;
with canvas do
begin
pen.Color:=clBlue;
pen.Width :=3;
{ делаем прямоугольники прозрачными }
brush.Style:=bsClear;
i:=1;
repeat
rectangle(x0,y0,x0+2*sh*i,y0+2*sh*i);
i:=i+1;
x0:=x0-sh;
y0:=y0-sh;
until (x0<=0) or (y0<=0) or
(x0+2*i*sh>=ClientWidth) or (y0+2*i*sh>=ClientHeight)
end;
Использование операторов Continue и Break в циклах
В теле цикла могут использоваться операторы Break и Continue.
Оператор Break обеспечивает выход из циклов for, while, repeat, и продолжает выполнение программы с оператора, непосредственно следующего за циклом. Например:
var
n:integer;
begin
n:=100;
while True do
begin
n:=n - 2;
if n = 0 then Break;
{ другие операторы цикла }
end;
end;
end;
В данном учебном примере в теле цикла выполняется изменение переменной n, если значение n становится равным 0, то с помощью оператора break выполняется выход из этого бесконечного цикла.
Оператор Continue позволяет перейти на начало цикла for, while, repeat. Пример использования Continue будет приведен ниже.
Задание случайных чисел. Функция Random. Процедура Randomize
При отладке широкого класса алгоритмов ввод значений переменных с клавиатуры, либо программным путем с помощью инициализации переменных является очень трудоемким. Значения переменных можно получать во время выполнения программы с помощью генерации случайных чисел, для этого используются функция Random и процедура Randomize.
Функция Random обеспечивает генерацию псевдослучайного числа. Синтаксис функции:
function Random [ ( Range: Integer) ];
Функция Random возвращает случайное число X, равномерно распределенное в интервале 0 <= X < Range.
Если функция используется без аргументов, возвращается вещественное число типа real в интервале 0 <= X < 1.
Для инициализации датчика случайных чисел используется процедура Randomize. Синтаксис:
Randomize.
Процедура не имеет аргументов. Достаточно выполнить процедуру один раз в теле программы. Ее единственное назначение это обеспечение возможности получения каждый раз разных последовательностей случайных чисел.
Генерация случайных чисел широко используется при создании игр, она позволяет исключить повторение игровых ситуаций при новых запусках программы.
Например:
Random(4) – вернет случайное число от 0 до 3.
Random(15)+1 – вернет случайное число от 1 до 15.
Вложенные циклы
При создания сложных алгоритмов часто приходится использовать вложенные циклы. Это означает, что внутри одного цикла может содержаться один или несколько вложенных циклов. Различные варианты вложений циклов приведены на рисунке.
В качестве примера использования вложенного цикла рассмотрим такую задачу: нарисовать игровое поле размером 10 на 10, состоящее из разноцветных клеточек случайного цвета, как изображено на рисунке:
Для решения задачи введем ряд переменных:
X0,Y0 –задают координаты левого верхнего угла поля;
DX,DY – размер клеточки по X и Y;
TX,TY – переменные для хранения координат текущей клеточки по X и Y.
Col – переменная, в которой будет содержаться цвет очередной клеточки, который будем задавать случайным путем.
Алгоритм решения задачи очень прост. Так как поле состоит из рядов клеточек, то во внутреннем (вложенном) цикле будем рисовать, например, горизонтальный ряд клеточек. Во внешнем цикле будем сдвигаться по Y и снова с помощью внутреннего цикла рисовать очередной горизонтальный ряд.
Так как число шагов и внешнего и внутреннего цикла известно, это 10, то будем использовать циклы со счетчиком – for. Для задания счетчиков цикла обычно используются переменные i,j или k. Итак, опишем все необходимые переменные:
Var
x0, y0, dx, dy, tx, ty : integer;
i, j : integer;
col:TColor;
Зададим начальные значения для переменных (инициализируем переменные):
x0:=20; y0:=20; dx:=30;dy:=30;
Так как цвет клеточки будет формироваться случайным путем, необходимо выполнить процедуру Randomize один раз в теле программы, например, на событие OnCreate формы.
Программный код для рисования поля может выглядеть таким образом:
with canvas do
begin
ty:=y0;
{ внешний цикл}
for i:=1 to 10 do
begin
tx:=x0;
{вложенный цикл}
for j:=1 to 10 do
begin
col:=RGB(random(256),random(256),random(256));
brush.Color:=col;
rectangle(tx,ty,tx+dx,ty+dy);
tx:=tx+dx;
end;
ty:=ty+dy;
end;
end;
Перед входом во вложенный цикл необходимо установить значение переменной TX, которая во вложенном цикле будет использоваться для задания X-координаты очередной клеточки:
tx:=x0;
Во вложенном цикле выполняется рисование очередного горизонтального ряда клеточек. Счетчик j задает число повторов внутреннего цикла. Во вложенном цикле необходимо смещаться по оси X для рисования очередного элемента ряда:
tx:=tx+dx;
Во внешнем цикле переменная i задает число повторов внешнего цикла. Перед рисованием очередного ряда необходимо сместиться по оси Y:
ty:=ty+dy;
И установить переменную tx, равной X0:
tx:=x0;
Задания для самостоятельной работы
- Найти сумму ряда чисел 1+2*2+3*3+...+n*n, где n вводится с клавиатуры. Вывести результат в окне.
- Найти сумму ряда чисел: 1+1/2+1/3+...+1/n, где n вводится с клавиатуры. Вывести результат в окне.
3. По введенному числу M распечатать все 3-х значные десятичные числа, сумма цифр которых равна M. Посчитать также количество таких чисел или сообщить, что таких чисел нет.
4. Ежемесячная стипендия студента составляет А рублей, а расходы на проживание превышают стипендию с составляют В рублей в месяц. Рост цен ежемесячно увеличивает расходы на проживание на 3%. Напишите программу расчета необходимой суммы денег, которые нужно единовременно попросить у родителей, чтобы можно было прожить учебный год(10 месяцев), использую только эти деньги и стипендию. Создайте удобный интерфейс для ввода информации.
5. У студента имеются накопления S рублей. Ежемесячная стипендия составляет A рублей, а расходы на проживание превышают стипендию и составляют B рублей в месяц. Рост цен ежемесячно увеличивает расходы на 3%. Напишите программу расчета времени (в месяцах), которое может прожить студент, использую только эти накопления и стипендию. Подумайте, изменится ли алгоритм, если инфляция не постоянна.
- Нарисовать 20 прямоугольников (окружностей) случайного цвета и размера в случайных местах экрана.
- Нарисовать 15 концентрических окружностей случайного цвета с центром в середине экрана, радиус каждой следующей окружности больше предыдущей на 10 пикселей. Прижать окружности к правому краю, к левому краю, к верхнему краю, нижнему краю.
- Нарисовать шахматную доску. Расставить начальную позицию белых и черных шашек, как показано на рисунке
9. Написать программу, которая выводит на экран изображенный ниже узор.
10. Написать программу, которая выводит на экран изображенный ниже узор:
11. Написать программу, которая выводит на экран оцифрованную координатную сетку.
12. Нарисовать поле для игры «Сапер» размером 10 на 10 клеточек, нарисовать 10 мин голубого цвета в случайных местах поля, как показано на рисунке:
Контрольные вопросы
- Что такое цикл? Какие виды циклов применяются в Pascal?
- Для чего используется цикл со счетчиком? Как работает цикл со счетчиком? Какой оператор языка Pascal реализует цикл со счетчиком?
- В каких случаях следует использовать цикл с предусловием? Какова блок-схема работы цикла с предусловием, поясните?
- Какой оператор языка Pascal реализует цикл с предусловием?
- Может ли цикл с предусловием не выполниться ни разу? В каких случаях?
- Может ли цикл с предусловием выполняться бесконечное число раз? В каких случаях?
- Цикл с постусловием: в каких случаях используется? Какова блок-схема выполнения цикла с постусловием?
- Какой оператор языка Pascal позволяет реализовать цикл с постусловием?
- Может ли цикл с постусловием не выполниться ни разу?
- Что необходимо предпринять, чтобы прервать программу, которая зациклилась (зависла)?
- Какой оператор позволяет немедленно выйти из цикла?
- Какой оператор позволяет перейти на начало цикла?
- Для чего используется функция Random?
- Для чего используется процедура Randomize?
Занятие 8. Массивы
Для решения многих задач приходится работать с однотипными данными, причем обработка этих данных часто выполняется по одному и тому же закону. Например, дана тысяча вещественных чисел, каждое число требуется увеличить на 2. Если решать эту задачу традиционным способом, следует описать 1000 переменных, назначить им начальные значения, это 1000 операторов, затем каждую переменную увеличить на 2, это еще 1000 операторов. Для более компактного описания подобного алгоритма можно использовать массивы.
Одномерные массивы
Под одномерным массивом понимается набор однотипных данных с общим именем, доступ к каждому элементу массива выполняется по порядковому номеру элемента в массиве. Номер элемента в массиве носит название индекса массива. Количество элементов в массиве называется размером массива.
Перед использованием массив необходимо описать. Массивы, как и переменные, описываются в разделе описаний процедуры или программы. При описании массива указывается его имя, диапазон изменения индекса, тип элемента.
Синтаксис описания массива:
<ИмяМассива> : array[<ДиапазонИндекса>] of <тип>;
Ключевое слово array позволяет описать массив.
Ключевое слово of – используется для задания типа элемента массива.
При задании типа массива можно использовать любой тип Pascal.
Например, для решения задачи, приведенной выше, следует описать такой массив:
Var
Mas : array[1..1000] of real;
Диапазон изменения индекса массива задается двумя числами, первое задает начальное значение индекса массива, второе задает конечное значение индекса массива.
Этот массив можно описать также таким образом:
Const
N=1000
Var
Mas : array[1..N] of real;
Последний способ хорош тем, что при изменении размера массива нужно изменить только одну константу N.
Для доступа к элементу массива используется следующий синтаксис:
<Имя массива>[ИндексЭлемента ]:=<Значение>;
Например:
Mas[30]:=25;
Где 30-тому элементу массива присваивается значение 25.
Выше приведенную задачу, но с десятью вещественными числами, значения которых инициализируются случайным способом, можно решить, например, так:
Const
N=10;
Var
Mas : array[1..N] of real;
i:integer;
str:string;
Begin
Str:=’’;
For i:=1 to N do
Begin
Mas[i]:= random(200) + random;
Mas[i]:= Mas[i] + 2;
Str:=Str + FloatToStr(Mas[i]) + ‘ ‘;
End;
ShowMessage(str);
End;
Наряду с одномерными массивами часто используются двумерные массивы.
Двумерные массивы
Данные могут быть организованы в виде таблицы (матрицы), где расположение каждого элемента матрицы определяется номером строки и столбца. Например, место в зрительном зале задается указанием номера ряда и номера места в ряду. Такие данные удобно описывать как двумерный массив. В отличие от одномерного массива каждому элементу двумерного массива соответствует пара индексов. Первый индекс – это номер строки, второй – номер столбца, где расположен элемент массива.
Размер двумерного массива задается парой чисел, первое задает число строк в массиве, второе число столбцов. Например, описать двумерный массив, размером 5 строк и 4 столбца:
Var
Table : array[1..5,1..4] of integer;
Элемент Table[3,2] расположен в третьей строке и втором столбце.
Компонент TStringGrid
Для наилучшего визуального представления содержимого одномерного или двумерного массива можно использовать компонент TStringGrid, который расположен на вкладке Additional. Компонент представляет собой сетку, состоящую из набора ячеек, как показано на рисунке.
|
Доступ к ячейкам сетки можно получать программным путем. Ячейка сетки может содержать числовую или текстовую информацию. По умолчанию сетка состоит из 5 строк и 5 столбцов. С помощью свойств можно изменить размер сетки, содержимое ее ячеек, цвет и размер фиксированной части. Нулевой столбец и нулевая строка сетки закрашены другим цветом, именно они и задают так называемую фиксированную часть сетки.
Основные свойства компонента приведены в таблице:
Свойство | Описание |
ColCount | Задает количество столбцов в таблице. |
RowCount | Задает количество строк в таблице. |
Color | Цвет фона. |
FixedColor | Цвет фиксированной части (0 строка, 0 столбец). |
FixedCols | Число фиксированных столбцов. |
FixedRows | Число фиксированных строк. |
DefaultColWidth | Задает ширину всех столбцов в пикселах |
DefaultRowHeight | Задает высоту всех строк в пикселах |
GridLineWidth | Толщина линий сетки. |
Options | Опции, позволяют менять ширину строк и столбцов сетки. Например: goEditing – если равно true, то можно изменять содержимое ячеек сетки |
Cells | Двумерный массив, позволяет получать доступ к ячейкам сетки: Cells[col,row : integer]:string. Где col – номер столбца, row – номер строки |
При использовании компонента StringGrid следует иметь в виду, что элементы массива Cells это строки, при этом первый индекс массива Cells задает номер столбца, а второй индекс задает номер строки. Для того, чтобы можно было заполнять ячейки сетки во время выполнения программы необходимо опцию goEditing сделать равной true, по умолчанию она равна false.
Пример 1. Например, заполнить сетку размером 10 на 10 случайными целыми числами от 1 до 100. Для отображения результатов использовать компонент StringGrid.
Размер сетки и размер ячейки сетки можно задать либо на этапе проектирования с помощью инспектора объектов, либо программным путем с помощью свойств ColCount, RowCount, DefaultColWidth, DefaultRowHeight. Программный код, запускаемый по кнопке «Заполнить сетку», может иметь следующий вид:
var i,j:integer;
begin
randomize;
for i:=0 to 9 do
for j:=0 to 9 do
StringGrid1.Cells[i,j]:=IntToStr(random(100)+1);
Пример 2. Найти наименьший и наибольший элементы массива из 10 элементов, если значения элементов массива формируются случайным способом числами от 1 до 100. Вывести результат на экран с помощью StringGrid. Внешний вид экрана приведен на рисунке:
Программный код может иметь, например, следующий вид:
var i,a,min,max:integer;
begin
randomize;
min:=100; max:=0;
for i:=0 to 9 do
begin
a:=random(100)+1;
StringGrid1.Cells[i,0]:=IntToStr(a);
if min>a then min:= a;
if max<a then max:= a;
end;
Label1.Caption:='Минимальный '+IntToStr(min);
Label2.Caption:='Максимальный '+IntToStr(max);
end;
Задание для самостоятельной работы
1. Дана последовательность из N различных целых положительных чисел. Написать программу определяющую:
· максимальное и минимальное число из этой последовательности;
· сумму всех чисел из этой последовательности;
· среднее арифметическое чисел этой последовательности.
2. Для игры N человек встали в круг. Каждый игрок загадал число от 1 до 20. Счастливчиком считается тот, у кого сосед слева и справа загадал одинаковое число. Написать программу, вычисляющую, сколько счастливчиков в кругу.
3. У Вас есть доллары. Вы хотите поменять их на рубли. Есть информация о стоимости купли-продажи долларов в банках города. В городе N банков. Напишите программу, определяющую какой банк выбрать, чтобы выгодно обменять доллары на рубли.
4. Результат сдачи экзамена группой из N студентов находится в массиве Rezultat. Посчитать количество студентов, сдавших экзамен на 2,3,4 и 5.
5. Напишите программу, которая вычисляет интервал в днях между двумя датами (месяц, день) текущего года.
6. Найти наименьшие среди тех элементов массива X, которые являются элементами массива Y.
7. Задан массив N целых чисел. Проинициализировать значения элементов массива случайным образом. Расположить элементы массива по возрастанию.
8. Перекидной календарь показывает дату: Y - год, M - месяц, D - день. Hапишите программу, вычисляющую дату в годах, месяцах и днях, которая была на календаре X дней назад.
Указание. Високосные годы - это те годы, у которых номер делится на 400 и те, у которых номер делится на 4, но не делится на 100. Hапример: 900 - невисокосный год, а 2000 - високосный.
9. Создать двумерный массив размером 10 на 10, заполнить его случайными числами от 1 до 100. Найти сумму элементов по каждой строке и каждому столбцу. Вывести результат с помощью компонента StringGrid.
10. Создать двумерный массив размером 10 на 10. Все не диагональные элементы имеют значение 0. Элементы, расположенные на диагоналях, имеют значение 1, как показано на рисунке:
11. Создать приложение «Календарь», в котором при выборе из списка нужного месяца в компоненте StringGrid отображаются соответствие чисел месяца дням недели, как показано на рисунке. Для выполнения этого задания потребуется использовать функцию DayOfWeek, которая возвращает порядковый номер дня недели от 1 до 7, причем первым днем недели считается воскресенье, а также функции StrToDate и DateToStr, которые преобразуют дату в строку и наоборот.
12. Для заданной матрицы, элементы которой формируются случайным путем, найти минимум среди сумм диагоналей, параллельных побочной диагонали.
13. Дана целочисленная матрица A(n,m). Заменить нулями элементы матрицы, стоящие на пересечении строк и столбцов, в которых имеется хотя бы по одному нулю.
14. Переформировать матрицу таким образом, чтобы ее столбцы располагались по убыванию их поэлементных сумм.
Контрольные вопросы
1. Что такое массив? Для чего используются массивы?
2. Как описать одномерный массив?
3. Как получить доступ к элементу одномерного массива?
4. Как описать двумерный массив? Как получить доступ к элементу двумерного массива?
Занятие 9. Строки и символы
Компьютер можно использовать для обработки не только числовой, но и текстовой информации. Для представления текстовых данных можно использовать символьный и строковый типы данных.
Символьный тип данных
Данными символьного типа являются любые символы, вводимые с клавиатуры: заглавные буквы, цифры, строчные буквы, специальные знаки и т. д. С помощью символьного типа данных можно задать одиночный символ, который можно описать либо с помощью одинарных кавычек, например: ‘A’, ’P’, ’+’, ‘=’, либо указанием его внутреннего кода, которому предшествует символ #. Например, #13 – символ Enter (Ввод), #27 – символ Escape (Отмена). Данные символьного типа описываются с помощью ключевого слова Char, например, с помощью следующего описания задается переменная Ch типа Char:
Var
Ch : Char;
Следующее описание задает две константы sm и enter:
Const
Sm=’*’; enter=#13;
Для присвоения значения символьной переменной используется следующий синтаксис, например:
Ch:=’R’;
Строковый тип данных
Под строкой понимается последовательность символов. При описании строки используется ключевое слово string. При этом допускается задание размера строки – максимальное количество символов. Если размер строки не указывается, то по умолчанию длина строки равна 255 символам. Например:
Var
Str : string;
Ss : string[7];
Строка Str – может иметь максимальный размер 255 символов. Размер строки Ss – ограничен 7 символами.
Для задания значений строковым переменным используется следующий синтаксис, например:
Str:=’Привет’;
Ss:=’Надежда’;
Если строке будет присвоено значение большей длины, она будет усечена до нужного размера.
Над строками определена единственная операция – сцепление(конкатенация) строк, когда в конец первой строки подписывается вторая строка. Операция обозначается знаком +(плюс). Например:
Str:=Str + Ss;
ShowMessage(Str);
Строку можно рассматривать как массив символов вида:
Var Ss : array[0..7] of char;
При этом нулевой элемент строки содержит число символов в строке.
Доступ к нужному символу строки можно получать как к элементу массива, т.е. по его порядковому номеру.