mod – взятие остатка от целочисленного деления.

advertisement
1-
Лекции по Turbo Pascal
7 класс
Паскаль.
Программа - алгоритм, записанный на языке программирования, служащий для выполнения каких-либо
действий.
Транслятор.
Допустим, что написана программа решения задачи на каком-то языке программирования, но компьютер
понимает только команды, переведенные в двоичный код. Этот перевод можно осуществить с помощью
трансляторов.
Транслятор программа, переводящая текст алгоритма, записанного на каком-то языке
программирования, на язык машинных кодов.
Различают два вида трансляторов: компиляторы и интерпретаторы. Они различаются с точки зрения
выполнения работы.
Компилятор читает всю программу целиком, делает ее перевод и создает законченный вариант программы на
машинном языке, который затем загружается в компьютер и выполняется.
Интерпретатор переводит и выполняет программу строка за строкой (как синхронный переводчик).
Компилятор осуществляет синтаксический контроль программы и при обнаружении ошибок выдает
диагностические сообщения. Если ошибок нет, результатом компиляции является программа на языке машинных
команд (ее называют объектной).
Интегрированная среда Turbo Pascal.
Краткое знакомство.
Язык Паскаль появился в 1984 году. Он разработан Н.Виртом в 1968-1970 г.г., получил широкое
распространение благодаря наглядности программ и легкости при изучении.
Turbo Pascal 7.0 позволяет:
а) создавать тексты программ;
б) компилировать их (находить и исправлять ошибки);
г) компоновать программы из отдельных частей;
д) использовать модули библиотек;
е) отлаживать и выполнять программы.
Система ТР состоит из множества файлов, основные из которых:
 TURBO.EXE, который содержит готовую к работе диалоговую систему программирования ( в нее входят
текстовый редактор, компилятор, компоновщик, загрузчик);
 TURBO.TPL - основная библиотека ТР;
 TURBO.HLP - справочная служба.
Для загрузки программы Turbo Pascal 7.0
системы экран разделен на три части:
надо: запустить файл Turbo.ехе. После загрузки
1. Главное меню.
2. Основное, или рабочее, окно.
3. Строка, в которой указывается назначение основных функциональных клавиш.
Меню Turbo Pascal
1. File – сохранение, открытие программы, работа с каталогами.
2. Edit – редактирование программы.
3. Search – поиск и замена.
4. Run – исполнение программы.
5. Compile – компиляция программы, т.е. перевод на машинный язык.
6. Debug – отладка программы.
7. Tools – дополнительные возможности.
8. Options – настройка системы.
9. Window – работа с окнами.
10. Help – помощь.
Функциональные клавиши Турбо Паскаль.
F1 - помощь;
F2 - сохранение редактируемого текста на диске;
F3 - загрузка текста с диска в окно редактирования;
Лекции по Turbo Pascal
2-
F9 - компилировать программу, но не выполнять ее;
F10 - переход к верхнему меню;
CTRL-F9 - выполнить прогон программы (компилировать ее и выполнить);
ALT-F5 - просмотр результатов выполнения программы;
Esc - переход из главного меню в окно редактирования.
ALT-X - выход из системы Турбо Паскаль.
File состоит из следующих команд:
New – создать новое рабочее окно.
Open – открыть сохраненную ранее на диске программу.
Save – сохранить программу под текущим именем.
Save as – сохранение программы под новым именем.
Save all – сохранение всех окон под текущими именами.
Change dir – изменение текущего каталога.
Exit – выход из режима Turbo Pascal.
Работа с окнами в Turbo Pascal
1. Удаление окна – мышью щелкнуть на значок []; нажать комбинацию клавиш Alt+F3; в
меню Window исполнить команду Close.
2. Изменение размеров – зацепить мышкой за нижний угол окна и двигать, пока окно не примет
необходимые размеры; нажать комбинацию клавиш Ctrl+F5 и с нажатой клавишей Shift, с
помощью стрелок изменять размеры, зафиксировать нажатием Enter.
3. Передвижение окна – зацепить окно за верхнюю рамку и двигать.
4. Раскрытие окна на весь экран – щелкнуть мышью на []; в меню Window исполнить команду
Zoom; нажать клавишу F5.
5. Смена активного окна – активное окно имеет двойную рамку, чтобы сделать окно активным
необходимо щелкнуть мышью на нужном окне; нажать F6; в меню Window исполнить
команду Next.
Tile – расположение открытых окон без перекрытий
Cascade – расположение открытых окон уступами.
Работа с блоками в Turbo Pascal
Блок это выделенная часть программы. Блоки можно переносить, копировать, удалять.
Ctrl+K,B – отметить начало блока;
Ctrl+K,K – отметить конец блока;
Ctrl+K,C – скопировать блок; в меню Edit выбрать команду Copy, затем команду Past.
Ctrl+K,V – переместить блок; в меню Edit выбрать команду Cut, затем команду Past.
Ctrl+K,Y – удалить блок; в меню Edit выбрать команду Clear.
Ctrl+K,H – снять выделение блока.
Выделить блок можно выделить еще следующим образом: прижать клавишу Shift и управляя
стрелками продлить выделение на весь блок; либо с помощью мыши: прижать левую клавишу мыши
протянуть выделение на весь блок. Повторное нажатие клавиши мыши приведет к снятию выделения.
Редактирование программы.
Перемещение курсора в начало строки – Home;
Перемещение курсора в конец строки – End;
Переключение между русским и латинским алфавитом - Ctrl+Shift (справа); Ctrl+Shift (слева);
Набор заглавной буквы – Shift+<клавиша с буквой>;
Удаление неправильного символа – установить курсор на этот символ и нажать клавишу Delete,
либо установив курсор после неправильного символа и нажать BS;
Разрезать строчку на две – установить курсор на «место разреза» и нажать Enter;
Склеить две строки – установить курсор в конец первой из склеиваемых строк и нажать Delete или в
начало второй и нажать BS;
Вставить между двумя строчками новую пустую – установить курсор в конец первой из двух строк
или в начало второй и нажать Enter;
Удалить строчку целиком – установить на нее курсор и нажать комбинацию клавиш Ctrl+Y;
Отменить последнюю операцию по редактированию текста Alt+BS;
Лекции по Turbo Pascal
3-
Запустить программу на исполнение - Ctrl+F9.
Алфавит языка Turbo Pascal
Алфавит языка Turbo Pascal содержит:
1. латинские строчные и прописные буквы, а также символ подчеркивания «_», который
приравнен к буквам;
2. цифры;
3. символ пробел;
4. символы с кодами от 0 до 31 (управляющие коды);
5. специальные символы: + - * / = < > [ ] . , ( ) : ; ^ @ { } $ # ‘
6. составные символы: <= >= <> := (* *) (. .) ..
При конструировании имен объектов программы (переменных, констант, типов, подпрограмм и т.д.)
можно использовать только латинские буквы и цифры (причем первый символ должен быть
обязательно буквой, большие и маленькие буквы в именах объектов считаются одинаковыми).
В языке Turbo Pascal есть зарезервированные слова, которые, так же нельзя использовать в качестве
имен чего-либо (например begin, end, var, for, while, repeat и т.д.).
Структура программы на языке Turbo Pascal
program <имя программы>;
uses <имена подключаемых библиотек>;
type <описание типов данных>;
const <описание констант>;
label <описание меток>;
var <описание переменных>;
<описание подпрограмм>;
begin
<операторы>;
end.
Любой из перечисленных выше разделов может отсутствовать, за исключением раздела операторов.
Поэтому самая короткая программа на языке Turbo Pascal выглядит так: begin end.
Правда, она ничего не делает, но с точки зрения синтаксиса языка, она написана верно.
Переменная - это область памяти, названная собственным именем, которая может менять свое значение в
процессе выполнения программы. Переменная характеризуется именем, типом и значением.
Константа - не изменяет своего значения в процессе выполнения программы, она может быть задана явно
своим значением или обозначена именем.
Имя (идентификатор) переменной или константы задается латинскими буквами и арабскими
цифрами. В качестве идентификатора нельзя использовать служебные слова. Идентификатор должен
быть уникальным, т.е. в данном блоке программы один идентификатор не может быть использован для
обозначения более чем одного объекта.
Например : Zap, gor,X, p1, summa, a28,rar_1, proba, x1,y1,max,min и т.д.
Все переменные, которые будут использованы в разделе операторов, должны быть объявлены в
разделе описания переменных, начинающемся словом var.
Описываются переменные так:
<имя переменной>: <имя типа>; (можно указывать несколько имен переменных через запятую)
Тип переменной – это множество значений, который она может принимать.
byte – целое число в диапазоне 0..255;
shortint – целое число в диапазоне -127..127;
word – целое число в диапазоне 0..65535;
integer – целое число в диапазоне -32768..32767;
longint – целое число в диапазоне -2147483648..2147483647;
real – вещественное число;
char – символ или #<код>;
boolean – логический тип {true,false}.
Лекции по Turbo Pascal
4-
Типы переменных
Тип
Целый
ShortInt
Integer
Longint
Byte
Word
Real
Вещественный
Single
Double
Extended
Comp
Логический
Boolean
Cимвольный
Char
Строковый
String
Массивы
Записи
Множества
Файлы
Указатели
array
record
set
file
pointer
Диапазон значений
-128...127
-32768 ...32767
-2147483648 ...
2147483647
0 .... 255
0 ... 65535
2,9 10-39..... 1,7 1038
11..12 значащих цифр
7..8 значащих цифр
15..16 значащих цифр
19..20 значащих цифр
19..20 значащих цифр
TRUE
FALSE
1 символ
Массив символов, по
умолчанию длина 256 символов.
Операция присваивания
В результате выполнения операции присваивания переменная получает значение. В общем виде эта
операция выглядит так:
<имя переменной>:=<выражение>;
Где := это символ операции присваивания. В Turbo Pascal после каждой операции ставится символ
«точка с запятой».
Выполнение инструкции присваивания заключается в следующем: сначала вычисляется результат
выражения, находящегося справа от символа присваивания, затем вычисленное значение записывается
в переменную, имя которой стоит слева от символа присваивания.
Например, в результате выполнения операций:
1.
i:=0; значение переменной i становится равным нулю;
2.
a:=b+c; значением переменной а будет число, равное сумме значений переменных b и c;
3.
j:=j+1; значение переменной j увеличится на единицу.
Операция присваивания считается верной, если тип выражения соответствует или может быть
приведен к типу переменной. Переменной типа real можно присвоить значение выражения типа real
или integer. Переменной типа integer можно присвоить значение выражения только типа integer.
Например, если переменные i и n типа integer, а d типа real, то операции:
i:=n/10; и i:=1.0; - неправильные, а d:=i; - правильная.
Процедура вывода информации.
В любой программе должны быть инструкции, обеспечивающие прием исходных данных и выдачу
пользователю результатов.
Вывод информации на экран.
Команда write предназначена для вывода на экран монитора сообщений и значений переменных. В
этой команде после слова write в скобках задается список имен переменных. Кроме имен переменных в
список можно включить сообщение – текст, заключенный в апострофы.
Примеры: write (Summa);
Лекции по Turbo Pascal
5-
write (‘Результат вычислений’);
write (‘Корни уравнения: х1=’,x1,’ x2=’,x2);
После имени переменной через двоеточие можно поместить формат поля вывода значения
переменной. Для переменной типа integer формат – это целое число, определяющее ширину поля
вывода (количество позиций на экране). Например, команда write(d:5) показывает, что для вывода
значения переменной d используется 5 позиций. Если число занимает меньше позиций, чем указано в
формате, то неиспользуемые позиции заполняются пробелами, а само изображение выравнивается по
правой границе поля.
Например, если значение переменной kol типа integer равно 15, то в результате выполнения
инструкции: write (‘Всего изделий:’,kol:5); на экран будет выведено: Всего изделий: 15.
Для переменных типа real формат представляет собой два целых числа, разделенных двоеточием.
Первое число определяет ширину поля вывода, второе – число цифр, стоящих справа от десятичной
точки. Если задать только ширину поля, то на экране появится число, представленное в формате с
плавающей точкой.
Пусть переменные х1 и х2 типа real имеют значения 13,25 и -0,3401; тогда в результате выполнения
инструкции: write (‘х1=’,x1:5:2,’ x2=’,x2:12); на экране будет выведено: х1=13.25 х2=-3.40100Е-01.
Если ширины поля, указанной в формате, недостаточно для вывода значения переменной, то
выводится число в формате с плавающей точкой и десятью цифрами после запятой (все поле вывода в
этом случае занимает 17 позиций).
После выполнения команды write курсор остается в той позиции экрана, в которой он находился
после вывода последнего сообщения этой команды. Следующая команда write начинает вывод именно с
этой позиции. Например, в результате выполнения команд:
х:=2.73;
write (‘Значение перем’);
write (‘енной’);
write (‘х=’);
write (х:8:5);
на экран будет выведено:
Значение переменной х=-2.73000
Инструкция отличается от инструкции write только тем, что после вывода сообщения или значений
переменных курсор переводится в начало следующей строки. например, если значением переменной х1
является число -3,561, а переменной х2 – число 10,345, то результатом выполнения команд:
writeln (‘Значения корней уравнения:’);
writeln (‘х1=’,х1:7:3);
writeln (‘х2=’,х2:7:3);
будет следующий текст на экране:
Значения корней уравнения:
х1=-3.5610
х2= 10.345
Пример программы №1
program primer1;
var
a,b:integer;
begin
a:=5;
b:=3;
writeln (‘5+3=’,a+b);
end.
Процедура ввода информации.
Команда read предназначена для ввода с клавиатуры значений переменных (исходных данных). в
общем виде инструкция выглядит так:
read (переменная 1, переменная 2,…переменная n);
Лекции по Turbo Pascal
6-
где переменная это имя переменной, значение которой должно быть введено с клавиатуры во время
выполнения программы.
примеры:
read (а);
read (Cena,kol);
при выполнении команды происходит следующее: программа приостанавливает свою работу и ждет,
пока на клавиатуре будут набраны нужные данные и нажата клавиша <Enter>. После нажатия <Enter>
введенное значение присваивается переменной, имя которой указано в инструкции (по порядку).
Например, в результате выполнения команды read (t) и ввода с клавиатуры строки 21, значением
переменной t будет число 21.
Одна команда read позволяет получить значения нескольких переменных. В этом случае вводимые
числа должны набираться в одной строке и разделяться пробелами. например, если тип переменных а,b
и c – real, то в результате выполнения команды read (a,b,c) и ввода с клавиатуры строки 4.5 23 0.17
значения переменных будут следующими: a=4.5, b=23.0, c=0.17.
Если в строке набрано больше чисел, чем задано переменных в команде, то оставшаяся часть строки
будет обработана следующей инструкцией read. Например, в результате выполнения команд:
read (а,b);
read (c);
и ввода с клавиатуры строки: 10 25 18
переменные примут следующие значения: a=10, b=25, c=18.
Инструкция readln отличается от инструкции read тем, что после выделения очередного числа из
введенной с клавиатуры строки присваивания его последней переменной из списка инструкции readln
оставшаяся часть строки теряется, и следующая инструкция read или readln будет требовать нового
ввода. Например, в результате выполнения команд:
readln(а,b);
read (c);
при наборе пользователем строки: 10 25 18
переменная а получит значение 10, b – 25. После чего программа будет ожидать ввода нового числа,
чтобы присвоить его переменной с.
Перед каждой командой read или readln следует располагать команду write, чтобы подсказать
пользователю, какие данные ожидает от него программа. Например, фрагмент программы вычисления
стоимости покупки может быть таким:
writeln (‘введите исходные данные’);
write (‘Цена изделия:’);
readln (Cena);
write (‘Количество в партии:’);
readln (kol);
write (‘Скидка:’);
readln (skidka);
Если тип данных, вводимых с клавиатуры, не соответствует или не может быть приведен к типу
переменных, имена которых указаны в инструкции read или readln, то программа аварийно завершает
работу (команды, следующие за этой не выполняются), и на экран выводится сообщение об ошибке.
Первая программа.
Задача 1 : Написать программу, которая вводит значения двух любых чисел, выводит на экран сумму,
разность, произведение и частное от деления этих чисел. Ввод каждого числа произвести с отдельной строке.
Каждый результат также нужно поместить на отдельную строку, пояснив в комментарии, чему соответствует
выводимое число.
program exampl_1;
var a,b : integer;
begin
writeln('Введите первое число’);
readln(a);
writeln('Введите второе число’);
readln(b);
Лекции по Turbo Pascal
7-
writeln('A+B= ', a+b:5);
writeln('A-B= ', a-b:5);
writeln('A*B= ', a*b:7);
writeln('A div B= ', a div b:5);
writeln('Нажмите <Enter>');
readln;
end.
Сохранение программы.
Для того чтобы сохранить программу, необходимо либо, либо :
 нажать Enter, в вертикальном меню выбрать команду Save as... и нажать клавишу Enter;
 в появившемся окне ввести имя файла и нажать Enter;
Компиляция программы
или
 выйти в верхнее меню и выбрать команду Compile и нажать клавишу Enter;
или
 нажать клавишу ALT-F9.
Запуск программы на выполнение.
или
 выйти в верхнее меню и выбрать команду RUN и нажать клавишу Enter;
или
 нажать клавишу CTRL-F9.
Алгоритм работы с программой
1. Написать программу на бумаге.
2. Запустить Турво Паскаль.
3. Набрать программу при помощи клавиатуры.
4. Сохранить программу на диске.
5. Запустить программу на компиляцию.
6. Запустить программу на выполнение.
Наша программа есть пример линейного алгоритма.
Линейные алгоритмы описывают решение задач с последовательным выполнением действий. Обычно
такие действия идут в следующем порядке :
 ввод исходных данных (может отсутствовать, тогда данные задаются внутри программы),
 последовательные команды - обычно вычислительного характера;
 вывод результатов (должен присутствовать обязательно).
Задание: Исправить программу «пример1» так, чтобы значения переменных вводились
пользователем с клавиатуры и результат сложения записывался в переменную summa.
program primer2;
const
p=3.14; { число ПИ }
var
r: real; { радиус }
c,s: real; { длина и площадь }
begin
write (‘Чему равен радиус окружности? ’);
redln (r);
c:=2*p*r;
s:=p*r*r;
writeln(‘длина окружности=’,c);
writeln(‘площадь окружности=’,s);
readln;
end.
Комментарий – это текст в фигурных скобках, который никак не воспринимается при выполнении
программы. Комментарий предназначен для удобства программиста.
Лекции по Turbo Pascal
8-
Задание: Исправить программу так, чтобы c и s выводились на экран в форме записи с
фиксированной точкой и с точностью до сотых.
Составление линейных алгоритмов.
Алгоритм – последовательность действий со строго определенными правилами выполнения.
Программа – это набор инструкций для вычислительных машин и устройств.
Виды программ – компьютерные программы, программы управления роботами, станками и другими
программируемыми устройствами.
Языки программирования – языки для записи программ для вычислительных машин и устройств
(Turbo Pascal, Basic, Delphi и т.д.).
Типы алгоритмов – линейные, ветвящиеся, циклические, вспомогательные и т.д.
Линейные алгоритмы – линейная последовательность операторов и операций.
Ветвящиеся алгоритмы – алгоритмы с альтернативным выбором действий и групп операций.
Циклические алгоритмы – алгоритмы с циклическим повторением действий и групп операций.
Вспомогательные алгоритмы – алгоритмы решения определенных подзадач, состоящие из групп
операций.
Задание: Составить программу, которая по двум введенным с клавиатуры целым числам вычисляла
бы и выводила на экран в удобном виде:
1. их сумму;
2. их произведение;
3. их разность;
4. их частное;
5. их среднее арифметическое;
6. сумму квадратов этих чисел;
с точностью до сотых.
Стандартные операции и функции.
Операции бывают следующих видов:
 арифметические операции;
 операции отношений;
 булевские (логические) операции;
 поразрядные логические и сдвиговые операции;
 операции над множествами.
Арифметические операции:
«+» - сложение;
«*» - умножение;
«-» - вычитание;
«/» - деление; (результат всегда должен иметь вещественный тип).
div – деление нацело (с отбрасыванием дробной части);
mod – взятие остатка от целочисленного деления.
Стандартные математические функции
abs(x)
exp(x)
sin(x) и cos(x)
arctan(x)
ln(x)
sqr(x)
sqrt(x)
random(x)
Pi
odd(x)
Абсолютное значение х, т.е. х
Значением функции является е в степени х.
Значение синуса или косинуса х, х должен
задаваться в радианах.
Арктангенс х.
Натуральный логарифм х (х>0)
Квадрат х.
Квадратный корень из х.
Случайное число из диапазона
0<=...< x
Значение пи.
Значение функции true, если х нечетен, и
false в противном случае.
Лекции по Turbo Pascal
9-
Значением является х увеличенное на n.
Значением является х уменьшенное на n.
Целая часть числа х.
Дробная часть числа х.
Целая часть в форме longint.
Значение х округленное до следующего
целого числа.
Правила записи арифметических
выражений.
1. Все данные, входящие в арифметическое выражение, должны быть одного типа. Допускается использовать
вместе данные целого и действительного типа.
2. Записывать все составные части в одну строку без подстрочных и надстрочных индексов.
3. Использовать скобки одного типа - круглые. ( [{ и другие скобки применять запрещается)
4. Нельзя записывать подряд 2 знака арифметических операций.
5. Вычисления выполняются слева направо в соответствии со старшинством операций:
1) вычисление функций;
2) * / DIV (деление нацело)
MOD (получение остатка от деления)
3) + Правила записи стандартных функций.
1. Имя функции записывается латинскими буквами.
2. Аргумент функции записывается в круглых скобках после имени функции.
3. Аргументом функции может быть : константа, переменная или арифметическое выражение.
Например :
inc(x,n)
dec(x,n)
int(x)
frac(x)
trunc(x)
round(x)
ax2 + bx + c
записывают так
a*x*x +b*x + c
2
b  4ac
записывают так
sqrt(b*b – 4*a*c)
записывают так
(a + c – 2*b)/(3-x)
a  c  2b
3 x
Рассмотрим примеры использования арифметических действий :
Правильно :
VAR a,b : integer;
r,s : integer;
............................
r:=a div b;
{r=3 при a=7, b=2}
r:= a mod b; {r=1 при a=7,b=2}
s:=a*b;
s:=a div b;
Неправильно :
VAR a,b : integer;
r : integer;
r:=a/b; {если результат объявлен как целочисленный, нельзя использовать наклонную черту деления}
VAR a,b : real;
r : integer;
.................
r:=a div b; { нельзя использовать операцию div для вещественных чисел}
r:=a mod b; { операция mod используется только по отношению к целым числам}
VAR a,b : integer;
r : real;
....................
r:=a div b; {r должно быть целым}
Слева по отношению к оператору присваивания должен стоять более широкий тип.
VAR a : integer;
b : real;
Лекции по Turbo Pascal
10
-
c : real;
...........
c:=a+b {правильно}
a:=c+b; {неправильно}
Примеры: 23 div 5 = 4
23 mod 5 = 3
16 div 4 = 4
16 mod 4 = 0
5 div 8 = 0
5 mod 8 = 5
37 div 10 = 3
37 mod 10 = 7
Определить количество слив, если их делили на 5 человек:
write (‘Кол-во слив = ');
readln (a);
b:= a mod 5;
writeln(‘Осталось ‘,b,’ слив’);
Определить сколько попугаев уберется на удаве, если длина удава b, а длина попугая а.
write ('a='); readln (a);
write ('b='); readln (b);
c:= b div a;
writeln ('Поместится', с, ‘попугаев');
В любом выражении, если один или более операндов имеют вещественный тип, то результат будет
так же вещественного типа. Операнды операторов div и mod всегда должны быть целого типа.
При вычислении выражений принят следующий приоритет: 1) *, /, div, mod; 2) +, -. порядок
выполнения операций регулируется с помощью скобок. В Turbo Pascal нет операции возведения в
степень.
Задание: Внести в программу составленную ранее необходимые изменения для высчитывания целой
части от деления и остатка от деления первого числа на второе и вывода этих результатов на экран. а
так же вывода на экран информации вида: a=b*c +r, где a – первое число, b – второе число, c – частное, r
– остаток.
Целочисленное деление.
Задачи:
1. Дано расстояние в сантиметрах. Найти число полных метров в нем.
2. Дана масса в килограммах. Найти число полных тонн в ней.
3. Дан прямоугольник с размерами 543×130 мм. Сколько квадратов со стороной 130 мм можно
отрезать от него.
4. С клавиатуры вводится двухзначное число, вычислить сумму его цифр.
5. С клавиатуры вводятся трехзначное (четырехзначное, пятизначное, шестизначное) число,
вычислить сумму его цифр.
6. С клавиатуры вводится трехзначное число, необходимо получить новое число приписав к
исходному справа число 45.
7. С клавиатуры вводится четырехзначное число, необходимо получить новое число приписав к
нему слева цифру 9. Найти остаток от деления полученного числа на 3.
8. Дано трехзначное число. В нем зачеркнули первую слева цифру и приписали ее в начале.
Найти полученное число.
9. Дано трехзначное число. Найти число, полученное при перестановке второй и третьей цифр
заданного числа.
10. Дано число а1а2а3а4а5а6. Получить новое число следующего вида: а6а4а2а1. для
полученного числа найти целую часть от деления на 8 и остаток от деления на 111.
11. Даны трехзначное и четырехзначные числа: а1а2а3 и b1b2b3b4. Получить новое число вида:
b1a1b2a2b3a3b4. У нового числа найти целую часть и остаток от деления на число 35.
Операции отношений:
< - меньше;
> - больше;
= - равно;
<> - не равно;
Лекции по Turbo Pascal
11
-
>= - больше или равно;
<= - меньше или равно.
Функции:
Арифметические функции:
abs (x) – модуль числа х, тип результата совпадает с типом аргумента;
sqr (x) – квадрат числа х, тип результата совпадает с типом аргумента;
sqrt (x) – квадратный корень из числа х, аргумент и результат должны иметь вещественный тип;
Пример: вычислить гипотенузу прямоугольного треугольника, если длина катетов a и b.
write ('a='); readln (a);
write ('b='); readln (b);
c:= sqrt (sqr(a) + sqr(b) );
writeln ('c=', с:5:2);
Вычислить модуль разности чисел a и b.
write ('a='); readln (a);
write ('b='); readln (b);
c:= abs (a - b);
writeln ('модуль=', с);
Тригонометрические функции:
sin (x) – синус числа х, выраженного в радианах, аргумент и результат должны иметь вещественный
тип;
cos (x) – косинус числа х, выраженного в радианах, аргумент и результат должны иметь
вещественный тип;
arctan (x) – арктангенс числа х, результат будет выражен в радианах, аргумент должен быть
вещественного типа;
Пример: вычислить синус, косинус, тангенс и котангенс угла 30.
a:=Pi/180*30;
s:=sin(a); c:=cos(a);
t:=s/c;
ct:=c/s;
Экспонента и логарифм:
exp (x) – ех, аргумент и результат должны иметь вещественный тип;
ln (x) – натуральный логарифм числа х, аргумент и результат должны иметь вещественный тип;
exp (b*ln(a)) – степень числа, где а основание, а b показатель степени, т.е. ab.
Примеры вычисления степени:
(x-3)7
exp(7*ln(x-3))
2x
exp(x*ln2)
3
x
exp(1/3*ln(x))
Преобразование типов:
Round (x) – перевод дробного числа в целое с округлением;
Trunc (х) – перевод дробного числа в целое отбрасыванием дробной части.
Примеры преобразования типов:
a1:=Round(2.34);
а1=2
a2:=Trunc(2.34);
а2=2
b1:=Round(8.51);
b1=9
b2:=Trunc(8.51);
b1=8
c1:=Round(-3.7);
c1=-4
int (x) – целая часть числа х, аргумент и результат должны иметь вещественный тип;
frac (x) – дробная часть числа х, аргумент и результат должны иметь вещественный тип;
Изменение аргумента:
inc (x) – увеличение числа х на единицу, аргумент и результат должны быть целого типа;
inc (x, a) – увеличение числа х на число а, оба аргумента и результат должны быть целого типа;
dec (x) – уменьшение числа х на единицу, аргумент и результат должны быть целого типа;
dec (x, a) – уменьшение числа х на число а, оба аргумента и результат должны быть целого типа.
Генерация случайных чисел:
Лекции по Turbo Pascal
12
-
Randomize – установка датчика случайных чисел в исходное состояние;
Random - формирование случайного дробного числа из диапазона от 0 до 1.
Примеры получения дробных случайных чисел:
a:=Random;
0<a<1
x:=Random+10;
10<x<11
y:=5*Random;
0<y<5
c:=10*Random-5;
-5<c<5
b:=7*Random-3;
-3<b<4
Random (n) – формирование случайного целого числа из диапазона от 0 до n-1, где n – натуральное
число.
Примеры получения целых случайных чисел:
a:=Random(3);
0, 1, 2
x:=Random(10);
0, 1, 2,…,9
y:=Random(5)+3;
3, 4, 5,…,7
c:=Random(8)-5;
-5, -4,…,2
Смоделировать 5-кратное бросание игрального кубика:
randomize;
for i=1 to 5 do begin
x:=random(6)+1;
writeln(i,‘ бросок: ',x,’очков’);
end;
Смоделировать 10-кратное бросание монеты:
randomize;
for i=1 to 10 do
if random(2)=0
then writeln(’орел’)
else writeln(’решка’);
Приоритетность выполнения действий:
1.Выражение в скобках
2.Функции
3.Знак числа (+,-), not, @
4.*, /, div, mod, and, shl, shr
5.+, -, or, xor
6.=, <>, <, >, <=, >=, in
Задание: Составить программу, которая по введенным значениям чисел а и b, высчитывала бы и
выводила бы на экран значения следующих функций:
a) y = 7a2 – 3a + 6;
3,2  1  a
b) y  sin
;
5a
c) y = a3 – 2,5ab + 1,78a2 – 12,5b + 1;
d) y = 3,56(a + b)3 – 5,8b2 + 3,8a – 1,5;
2b
a 2
a
e) y 
;
1
b
a 2  10
2
b
2
a

25
f) y 
;
ab
b
2
Лекции по Turbo Pascal
13
-
g) y 
a  2 sin b
.
5,5a
Вывод на экран организовать в следующем виде: у1(1.22, 0.45)=…и т.д.
Контрольная работа № 1 по теме: «Линейные алгоритмы. Деление нацело».
Стандартный модуль CRT.
Помимо встроенных процедур и функций Turbo Pascal предоставляет программисту множество
функций и процедур различного назначения, объединенных в группы – библиотеки. Каждая библиотека
состоит из функций и процедур, предназначенных для решения определенного типа задач. Например,
есть библиотека математических функций, библиотека управления экраном, библиотека функций и
процедур ввода с клавиатуры, библиотека для работы с графическим экраном и т.д.
Начнем рассмотрение первой из таких библиотек – это модуль CRT. Библиотека содержит функции
и процедуры, полезные при выводе на экран.
Некоторые процедуры стандартного модуля CRT:
Clrscr - экран очищается текущим фоновым цветом, при этом курсор устанавливается в левый
верхний угол экрана;
TextColor (c) – устанавливает цвет символов, где с – название или номер цвета: 0-черный, 1 – синий,
2 – зеленый, 3 – голубой, 4 – красный, 5 – фиолетовый, 6 – оранжевый, 7 – серый, 8 –
темно-серый, 9 – светло-синий, 10 – светло-зеленый, 11 – светло-голубой, 12 –
светло-красный, 13 – светло-фиолетовый, 14 – желтый, 15 – белый.
TextBackGround (с) – устанавливает цвет фона, где с – название или номер цвета: 0-черный, 1 –
синий, 2 – зеленый, 3 – голубой, 4 – красный, 5 – фиолетовый, 6 – оранжевый,
7 – серый.
GotoXY (x, y) – устанавливает курсор в позицию экрана с координатами х и у, где х – номер столбца
позиции (1..80), у – номер строки позиции (1..25).
TextMode (r) – установка режима экрана, где r – это номер текстового режима, который может
принимать следующие значения: 1 - 4025; 3 - 8025; 257 - 4050; 259 - 8050.
Delay (ms) - задержка выполнения программы (миллисекунды);
Sound (f) – включение динамика, где f - это частота сигнала (Гц);
NoSound – отключение динамика;
Значение частот:
Нота
Октава
до
ре
ми фа соль ля
си
Большая 130 147 165 175 196 220 246
Малая 262 294 330 349 392 440 494
Первая 523 587 659 698 783 880 998
Вторая 1046 1175 1319 1397 1568 1760 1975
Гамма:
Uses Crt;
Var i : Integer;
Const f : array[1..7] of word = (523, 587, 659, 698, 783, 880, 998);
Begin
For i:=1 to 7 do begin
Sound(f[i]); delay(100);
end;
NoSound;
End.
ClrEol - очищается строка от текущей позиции до конца строки без изменения позиции курсора;
DelLine - удаляется строка, на которой находится курсор, и все строки, расположенные ниже,
смещаются на позицию вверх;
InsLine - вставляется пустая строка, начиная с позиции, где находится курсор;
WhereX – функция, определяющая координату х курсора, результат возвращается типа integer;
WhereY– функция, определяющая координату y курсора, результат возвращается типа integer;
Лекции по Turbo Pascal
14
-
Window (x1,y1,x2,y2) – задание текстового окна, после задания окна все координаты задаются
относительно этого активного окна;
KeyPressed – функция проверки буфера клавиатуры, результат булевского типа: True – если в буфере
клавиатуры есть символы и False – если буфер клавиатуры пуст;
Примеры использования функции KeyPressed:
Repeat
<Операторы>
Until KeyPressed;
или:
While Not KeyPressed
begin
<Операторы>
end;
ReadKey – чтение первого байта (символа) из буфера клавиатуры. Если буфер клавиатуры пуст, то
ожидание нажатия клавиш символа из буфера клавиатуры, результат функции должен
быть типа char;
Пример фрагмента программы для чтения расширенного кода:
Key:=ReadKey; {чтение первого байта (#0)}
If Key=#0 Then
Key:=ReadKey; {чтение второго байта}
Коды некоторых клавиш:
Enter
- 13
 - 0 75
Esc
- 27
 - 0 72
BackSpace- 8
 - 0 77
Space
- 32
 - 0 80
Tab
- 9
Home - 0 71
a
- 97
End - 0 79
A
- 65
Insert - 0 82
Пример фрагмента программы управления движением:
Repeat
Key:=ReadKey;
If Key=#0 Then Key:=ReadKey;
Case Key of
75 : Left;
77 : Right;
72 : Up;
80 : Down;
End;
Until Key=#27;
Highvideo – символы выводятся на экран с повышенной яркостью;
Lowvideo – символы выводятся на экран с пониженной яркостью.
Задание: Составить программу вывода на экран поздравления друга с Днем Рождения (использовать
разумно разные цвета и местоположение текста на экране).
Самостоятельная работа по теме: «Модуль CRT».
Условия в Turbo Pascal. Виды условий.
Алгоритмы решения большинства задач не являются последовательными. Действия, которые
необходимо выполнить, могут зависеть от определенного условия, например исходных данных, или
результатов, полученных во время выполнения программы. Например, если нам необходимо
переменной max присвоить значение большей из переменных х1 или х2, мы должны определить
сначала какое число больше а уже после этого заносить его значение в переменную max.
В языке Pascal условие – это выражение логического типа (Boolean), которое может принимать одно
из двух значений: истина или ложь.
Лекции по Turbo Pascal
15
-
В Pascal имеется шесть операторов, позволяющих сравнивать между собой значения числовых
переменных, а также значения переменной и константу (число).
Использование операторов сравнения позволяет записывать простые условия. Например, х1>x2 или
х1=х2, или х1<>х2 и т.п.
Из простых условий, которые являются выражениями логического типа, можно строить сложные
условия с применением к ним, как к операндам, логических операторов:
Not – отрицание;
And – логическое «и»;
Or – логическое «или».
При записи сложных условий важно учитывать то, что логические операторы имеют более высокий
приоритет, чем операторы сравнения, поэтому простые условия следует брать в скобки.
Например, нам необходимо из трех чисел выбрать большее, можно составить такое условие: (x>y) and
(x>z), или условие попадания точки в интервал :
будет выглядеть так:
(х<= -3) or (x>=7). Возможно составление и более сложных условий: (a=5) or ((a>10) and (a<1)).
Итак, следовательно, условия могут быть либо простыми, либо составными, полученными из простых
с помощью логических связок.
Условный оператор.
В Turbo Pascal включены два условных оператора – if и case (хотя исторически так сложилось что
последний называется оператором выбора), каждый из которых может быть записан в двух формах:
полной и неполной.
Синтаксис инструкции IF:
If условие
then
begin
{инструкции выполняемые, если условие истинно};
end
else
begin
{инструкции выполняемые, если условие ложно};
end;
Инструкция if выполняется следующим образом:
1. вычисляется значение условия (выражение логического типа).
2. Если значение выражения условия равно true, то выполняются инструкции, следующие за
словом then. Если значение выражения условия равно false, то выполняются инструкции,
следующие за словом else.
Примечания:
1. Перед ключевым словом else символ «;» никогда не ставится.
2. Если при выполнении (невыполнении) условия надо выполнить только одну инструкцию, то
слова begin и end после then (else) могут быть опущены.
Пример: необходимо вывести на экран значение большего из двух введенных с клавиатуры чисел.
Пусть первое число х, а второе число у, тогда фрагмент программы будет выглядеть так:
if x>y then writeln (‘большее из данных двух чисел ’, x)
else writeln ( ‘большее из данных двух чисел ’,y);
Если какое-либо действие нужно выполнить только при выполнении условия, инструкция if может
быть записана так:
If условие
then
begin
{инструкции выполняемые, если условие истинно};
end;
Пример: вычислить значение функции y=1/x. Фрагмент программы будет выглядеть так:
Лекции по Turbo Pascal
16
-
If x<>0 then y:=1/x;
Иногда возникает необходимость использования вложенных условных операторов.
Пример: С клавиатуры задаются три числа, необходимо вывести на экран значение большего из этих
чисел. Фрагмент такой программы будет выглядеть так:
if x>y
then begin
if x>z then writeln (‘большее из данных чисел ’, x)
else writeln ( ‘большее из данных чисел ’,z);
end
else writeln (‘большее из данных чисел ’, y);
Либо можно построить несколько по другому, например так:
if (x>y) and (x>z)
then begin writeln (‘большее из данных чисел ’, x)
else
if y>z then writeln (‘большее из данных чисел ’, y)
else writeln ( ‘большее из данных чисел ’,z);
Задание: Написать полностью программы для разобранных выше примеров.
Задачи:
1. Рассчитать значение y при заданном значении x:
 sin 2 x
, x0
y
2
1  2 sin x , x  0
2. Дано целое число. Определить:
а) является ли оно чётным;
б) оканчивается ли оно цифрой 7;
в) оканчивается ли оно чётной цифрой. Составное условие не использовать.
3. Дано двузначное число. Определить:
а) какая из его цифр больше: первая или вторая;
б) одинаковы ли его цифры?
4. Дано двузначное число. Определить:
а) кратна ли трём сумма его цифр;
б) кратна ли сумма его цифр числу A?
5. Дано трёхзначное число. Определить, равен ли квадрат этого числа сумме кубов его цифр.
6. Дано трёхзначное число. Определить:
а) является ли сумма его цифр двузначным числом;
б) является ли произведение его цифр трёхзначным числом;
в) больше ли числа A произведение его цифр;
г) кратна ли пяти сумма его цифр;
д) кратна ли сумма его цифр числу A.
7. Дано трёхзначное число.
а) верно ли, что все его цифры одинаковые?
б) определить, есть ли среди его цифр одинаковые?
8. Дано четырёхзначное число. Определить:
а) равна ли сумма двух первых его цифр сумме двух его последних цифр;
б) кратна ли трём сумма его цифр;
в) кратно ли четырём произведение его цифр;
г) кратно ли произведение его цифр числу A.
9. Составить программу для вычисления значения функции y(x):
 x 2 , если sin x  0,
 kx, если k  x,
y
где : k  
k  x, если k  x,
 x , если sin x  0.
10. Дано натуральное число.
а) Верно ли, что оно заканчивается нечетной цифрой?
Лекции по Turbo Pascal
17
-
б) Верно ли, что оно заканчивается четной цифрой?
x 2
 2,4  x  5,7,
y
 4 в противном случае.
12. Определить, является ли число A делителем числа B, или наоборот. Ответом должны
служить сообщения: "да, одно из чисел является делителем другого" или "нет, ни одно из
чисел не является делителем другого".
13. Год является високосным, если его номер кратен 4, однако из кратных 100 високосными
являются лишь кратные 400 (например, 1700, 1800 и 1900 – не високосные года, 2000 –
високосный). Дано натуральное число N. Определить, является ли високосным год с таким
номером.
14. Дано четырехзначное число. Определить:
а) входит ли в него цифра 4;
б) входит ли в него цифра B.
15. Дано четырехзначное число. Определить:
а) входят ли в него цифры 4 или 7; б) входят ли в него цифры 3, 6 или 9.
16. Дано натуральное число n (n  9999).Выяснить, различны ли все четыре цифры этого числа
(если оно записано четырьмя цифрами). Например, в числе 3678 все цифры различны, в
числе 0023 – нет.
17. Определить, является ли заданное шестизначное число счастливым.
(Счастливым
называют такое шестизначное число, у которого сумма его первых трех цифр равна сумме
его последних трех цифр).
18. Составить программу, которая уменьшает первое веденное число в два раза, если оно
больше второго введенного числа по абсолютной величине.
19. Даны два числа. Если квадратный корень из второго числа меньше первого числа, то
увеличить второе число в пять раз.
20. Даны три целых числа. Вывести на экран те из них, которые являются четными.
21. Даны три вещественных числа. Возвести в квадрат те из них, значения которых
неотрицательны.
22. Даны три вещественных числа. Вывести на экран:
а) те из них, которые принадлежат интервалу (1,6 – 3,8);
б) те из них, которые принадлежат интервалу (0,7 – 5,1).
23. Даны четыре вещественных числа. Найти сумму тех чисел, которые больше пяти.
24. Даны четыре целых числа. Определить сумму тех из них, которые кратны трем.
11. Дано вещественное число x. Вычислить y(x), если
 1, если a  0,

25. Составить программу для вычисления значения функции z(a): z   0, если a  0,
 1, если a  0.

при x  0,
 0,

при 0  x  1,
26. Дано вещественное число x.Вычислить f(x), если: f   x,
 x 2 , в остальных случаях.

27. Даны вещественные числа a, b, c (a ≠ 0).Выяснить, имеет ли уравнение ax2+bx+c=0
вещественные корни. Если такие корни имеются, то найти их. В противном случае ответом
должно служить сообщение, что вещественных корней нет.
28. Вывести на экран номер четверти координатной плоскости, которой принадлежит точка с
координатами (x, y), при условии, что x ≠ 0 и y ≠ 0.
29. Для натурального числа k напечатать фразу “мы нашли k грибов в лесу“, согласовав
окончание слова “гриб” с числом k.
Самостоятельная работа на условный оператор.
Оператор выбора.
Рассмотренный условный оператор If позволяет выбирать только одно из двух возможных действий в
зависимости от логического выражения.
Лекции по Turbo Pascal
18
-
Оператор выбора case является обобщением оператора If – он дает возможность выполнять одно из
нескольких действий в зависимости от значения переключателя.
В качестве переключателя используется выражение, которое располагается между ключевыми
словами case и of. Результатом этого выражения может быть только значение порядкового типа, общее
количество элемент которого не превышает 65535.
Синтаксис инструкции case:
case выражение of
список констант_1 : begin
{последовательность инструкций 1};
end;
список констант_2 : begin
{последовательность инструкций 2};
end;
список констант_n : begin
{последовательность инструкций n};
end
else begin
{последовательность инструкций, выполняемая в случае, если выражение
не попало ни в один из списков констант};
end;
end;
Где выражение – это выражение, от значения которого зависит дальнейший ход программы (одна из
последовательностей инструкций, которая должна быть выполнена).
Список констант – константы, разделенные запятыми. Если константы представляют диапазон чисел,
то вместо списка можно указать первую и последнюю константу диапазона, разделив их двумя точками.
Например список 1, 2, 3, 4, 5, 6 может быть заменен диапазоном 1..6.
При выполнении инструкции case происходит следующее: вычисляется значение выражения
оператора case, затем полученное значение последовательно сравнивается с константами из списков
констант. Если значение выражения совпадает с константой из списка, то выполняется
соответствующая этому списку последовательность инструкций, и на этом выполнение инструкции
case завершается. Если значение выражения не совпадает ни с одной константой из всех списков, то
выполняется последовательность инструкций идущих после else. Синтаксис инструкции case позволяет
не использовать else и соответствующую последовательность инструкций. В этом случае, если значение
выражения не совпадает ни с одной константой из всех списков, то выполняется следующая за cаse
команда.
Примеры:
Case day of
Case day of
Case day of
1, 2, 3, 4, 5: write (‘ рабочий день’);
1..5: write (‘ рабочий день’);
6: write (‘суббота’);
6: write (‘суббота’);
6: write (‘суббота’);
7: write (‘воскресенье’)
7: write (‘воскресенье’);
7: write (‘воскресенье’);
else write (‘ рабочий день’);
end;
end;
end;
Задание: При выводе числовой информации с пояснительным текстом возникает проблема
согласования выводимого значения и окончания пояснительного текста. Например, рубль, рубля или
рублей, либо год, года, лет. Составить программу, запрашивающую количество лет и выводящую
сообщение: «Вам …лет».
Задачи:
1) Составить программу, которая в зависимости от порядкового номера месяца (1, 2, …, 12)
выводит на экран его название (январь, февраль, …, декабрь).
2) Составить программу, которая в зависимости от порядкового номера месяца (1, 2, …, 12)
выводит на экран количество дней в этом месяце. Рассмотреть 2 случая:
а)
год не является високосным (см. задачу 13);
б) год високосный (информация об этом вводится с клавиатуры).
Самостоятельная работа на условный оператор и оператор выбора.
Лекции по Turbo Pascal
19
-
Циклы.
При решении многих задач некоторую последовательность действий приходится выполнять
несколько раз. Например, программа контроля знаний выводит вопрос, принимает ответ, добавляет
оценку за ответ к сумме баллов, затем повторяет это действие еще раз, и еще, до тех пор, пока не будут
выведены все вопросы. Другой пример. Чтобы найти фамилию человека в списке, надо проверять
первую фамилию списка, потом вторую, третью и т.д. до тех пор, пока не будет найдена нужная или не
будет достигнут конец списка. Такие повторяющиеся действия называются циклами и реализуются в
программе с использованием операторов циклов.
Оператор цикла for.
Оператор for используется если надо выполнить некоторую последовательность действий несколько
раз, причем заранее известно число таких повторений. Также удобно использовать этот оператор, когда
необходимо некоторым образом использовать в теле цикла информацию о номере очередной итерации.
Синтаксис оператора цикл for:
For i:=n1 to n2 do
begin
{последовательность операторов};
end;
Либо:
For i:=n2 downto n1 do
begin
{последовательность операторов};
end;
Где i – это счетчик цикла, который обязательно должен быть объявлен в разделе var, и иметь
целочисленный тип;
n1 – начальное значение счетчика, которое является значением выражение, определяющее начальное
значение переменной – счетчика цикла;
n2 – конечное значение счетчика, которое является выражением, определяющим конечное значение
переменной – счетчика циклов.
Примечания:
1) Если между begin и end находится только одна инструкция, то begin и end можно не писать.
2) Шаг изменения переменной – счетчика циклов может быть равен только 1(если используется
ключевое слово to) или –1 (если используется ключевое слово downto).
3) Категорически не рекомендуется проводить какое–либо изменение переменной – счетчика
цикла внутри тела цикла.
Оператор цикла for работает следующим образом:
1) Вычисляется начальные и конечные значения параметра цикла;
2) Если начальное значение превосходит конечное, то тело цикла не выполняется. В противном
случае, изменяется параметр цикла и вместе с каждым его значением выполняется тело цикла.
Примеры:
 у=1+1/2+1/3+…+1/n
у:=0;
for i:=1 to n do
y:=y+1/i;
writeln (‘y=’,y:5:2);
 Вывести на экран и вычислить сумму квадратов целых чисел от 1 до n.
s:=0;
for i:=1 to n do begin
s:=s+sqr(i);
writeln (sqr(i));
end;
writeln (‘s=’,s);
 y=xk
Лекции по Turbo Pascal
20
-
y:=1;
for i:=1 to k do
y:=y*x;
writeln (‘y=’,y:5:2);
Задание: Составить полностью программы для разобранных выше примеров.
Задачи:
1. Напечатать "столбиком":
а) все целые числа от 20 до 35;
б) квадраты всех целых чисел от a до b (значение b вводится с клавиатуры; b≥10);
в) третьи степени всех целых чисел от a до 50 (значение a вводится с клавиатуры; a≤10);
г) все целые числа от a до b (значение a и b вводятся с клавиатуры; b≤a).
2. Одна штука некоторого товара стоит 20.4 руб. Напечатать таблицу стоимости 2, 3, ..., 20 штук
этого товара.
3. Напечатать таблицу соответствия между весом в фунтах и весом в килограммах для значений
1, 2, ..., 10 фунтов (1 фунт = 453 г).
4. Напечатать таблицу перевода 1, 2, ..., 20 долларов США в рубли по текущему курсу (значение
курса вводится с клавиатуры).
5. Составить таблицу умножения на 9.
6. Составить таблицу умножения на число n (значение n вводится с клавиатуры; 1≤n≤9).
7.
Рассчитать значения y для значений x, равных 4, 5, ..., 28:
y = 2y2 + 5,5t – 2,
t = x + 2.
8.
Рассчитать значения z для значений a, равных 2, 3, ..., 17:
z = 3,5t2 – 7t + 16,
t = 4a.
9. Найти:
a) сумму всех целых чисел от 100 до 500;
б) сумму всех целых чисел от a до 500 (значение a вводится с клавиатуры; a≤500);
в) сумму всех целых чисел от -10 до b (значение b вводится с клавиатуры; b≥ -10);
г) сумму всех целых чисел от a до b (значения a и b вводятся с клавиатуры; b≥a).
10.
Найти:
а) среднее арифметическое всех целых чисел от 1 до 1000;
б) среднее арифметическое всех целых чисел от 100 до b (значение b вводится с клавиатуры;
b≥100);
в) среднее арифметическое всех целых чисел от a до 200 (значение a вводится с клавиатуры;
a≤200);
11.
Найти:
a) сумму кубов всех целых чисел от 20 до 40;
б) сумму квадратов всех целых чисел от a до 50 (значение a вводится с клавиатуры; 0≤a≤50);
в) сумму квадратов всех целых чисел от 1 до n (значение n вводится с клавиатуры; 1≤n≤100);
г) сумму квадратов всех целых чисел от a до b (значение a и b вводится с клавиатуры; b≥a).
12.
Дано натуральное число n. Найти сумму n2 + (n+1)2 + ... + (2n)2.
Самостоятельная работа на цикл с параметром.
Оператор цикла с предусловием while.
Оператор цикла while используется в программе, если надо провести некоторые повторные
вычисления (цикл), однако число повторов заранее неизвестно и определяется самим ходом
вычисления.
В общем виде оператор выглядит так:
while условие do
begin
{последовательность операторов};
end;
Лекции по Turbo Pascal
21
-
где условие – выражение логического типа.
Оператор цикла while работает следующим образом:
1. Вычисляется условие.
2. Если условие ложно, то вход в цикл не выполняется и управление передается оператору,
следующему непосредственно за операторами тела цикла.
3. Если же условие истинно, то происходит вход в цикл и однократное выполнение операторов.
Как только достигнут конец тела цикла, управление передается на его заголовок, где снова
вычисляется его условие.
Примечание:
1. Для того чтобы последовательность инструкций между begin и end была выполнена хотя бы
один раз, необходимо, чтобы перед выполнением инструкции while условие было истинно;
2. Для того чтобы цикл завершился, необходимо чтобы последовательность инструкций между
begin и end изменяла значения переменных, входящих в выражение условие.ъ
Примеры: Вычислить сумму нечетных чисел от 1 до некоторого числа n. (n=1, s=1; n=2, s=1+3=4;
n=12, s=1+3+5+7+9+11=36).
program summa;
uses crt;
var
n, s, i: integer;
begin
clrscr;
s:=0; i:=1;
writeln (‘Введите натуральное число n’); readln(n);
while i<=n do
begin
s:=s+i;
i:=i+2;
end;
writeln (‘сумма нечетных чисел от 1 до ’, n, ‘=’,s);
readln;
end.
Составить таблицу значений функции y  x на отрезке [2;4] с шагом 0,2.
program func;
uses crt;
var
x, y: real;
begin
clrscr;
x:=2;
while x<=4 do
begin
y:=sqrt(x);
writeln (y:6:3);
x:=x+0.2;
end;
readln;
end.
Задание: Составить программу составляющую таблицу значений функции y  x на отрезке [a;b] с
шагом 0,2.
Задачи:
1. Дано натуральное число. Определить:
а) количество цифр в нем;
б) сумму его цифр;
Лекции по Turbo Pascal
22
-
в) произведение его цифр;
г) среднее арифметическое его цифр;
д) сумму квадратов его цифр;
е) сумму кубов его цифр;
ж) его первую цифру;
2. Напечатать минимальное число, больше 200, которое нацело делится на 17.
3. Найти максимальное из натуральных чисел, не превышающих 5000, которое нацело
делится на 39.
4. Даны натуральные числа a и b, обозначающие соответственно числитель и знаменатель
дроби. Сократить дробь, т.е. найти такие натуральные числа p и q, не имеющие общих
делителей, что p/q=a/b.
5. Даны натуральные числа m и n. Получить все кратные им числа, не превышающие m*n.
Условный оператор не использовать.
6. Даны натуральные числа a и b. Найти НОД(a,b) и НОК(a,b).
7. Дано натуральное число.
а) Получить число, получаемое при прочтении его цифр справа налево.
б) Приписать по двойке в начало и конец записи этого числа.
в) Удалить из него все цифры А.
г) Переставить его первую и последние цифры.
д) Приписать к нему такое же число.
8. Дано натуральное число. Определить номер цифры 3 в нем, считая от конца числа. Если
такой цифры нет, ответом должно быть число 0, если таких цифр в числе несколько должен быть определен номер самой правой из них.
9. Дано натуральное число. Определить сумму m его последних цифр.
10. Дано натуральное число. Найти его наименьший делитель, отличный от 1.
11. Дан прямоугольник с размерами 425x131. От него отрезают квадраты со стороной 131, пока
это возможно. Затем от оставшегося прямоугольника вновь отрезают квадраты со стороной,
равной 425-131*3=32, и т. д. На какие квадраты и в каком их количестве будет разрезан
исходный прямоугольник?
12. Дан прямоугольник с размерами axb. От него отрезают квадраты максимального размера,
пока это возможно. Затем от оставшегося прямоугольника вновь отрезают квадраты
максимально возможного размера и т.д. На какие квадраты и в каком их количестве будет
разрезан исходный прямоугольник?
13. Дана непустая последовательность целых чисел, оканчивающаяся нулем. Найти:
а) сумму всех чисел последовательности;
б) количество всех чисел последовательности.
14. Определить:
а) является ли заданное число степенью числа 3;
б) является ли заданное число степенью числа 5.
15. Дано число n.
а) Напечатать те натуральные числа, квадрат которых не превышает n.
б) Найти первое натуральное число, квадрат которого больше n.
16. Дано натуральное число.
а) Верно ли, что сумма его цифр больше 10?
б) Верно ли, что произведение его цифр меньше 50?
в) Верно ли, что количество его цифр есть четное число?
г) Верно ли, что это число четырехзначное?
Составное условие и вложенный условный оператор не использовать.
д) Верно ли, что его первая цифра не превышает 6?
е) Верно ли, что оно начинается и заканчивается одной и той же цифрой?
ж) Определить, какая из его цифр больше: первая или последняя.
17. Дано натуральное число.
а) Верно ли, что сумма его цифр больше к, а само число четное?
Лекции по Turbo Pascal
23
-
б) Верно ли, что количество его цифр есть четное число, а само число не превышает b?
в) Верно ли, что оно начинается на X и заканчивается на Y?
г) Верно ли, что произведение его цифр меньше А, а само число делится на В?
д) Верно ли, что сумма его цифр больше M, а само число делится на N?
18. Дано натуральное число. Определить:
а) есть ли в нем цифра 3;
б) есть ли в нем цифры 2 и 5.
19. Дано натуральное число.
а) Определить, есть ли в нем цифра А.
б) Верно ли, что в нем нет цифры В?
в) Верно ли, что цифра А встречается в нем более К раз?
г) Определить, есть ли в нем цифры А и В.
20. Дано натуральное число. Выяснить, является ли оно палиндромом ("перевертышем"), т.е.
числом, десятичная запись которого читается одинаково слева направо и справа налево.
21. Напечатать полную таблицу умножения в виде:
1*1=1 1*2=2 …
1*9=9
2*1=1 2*2=4 …
2*9=18
…
…
…
…
9*1=9 9*2=18 …
9*9=81
22. Найти все натуральные числа, меньшие 200, у которых сумма цифр равна 13.
23. Найти все целые числа от 30 до 350, у которых сумма цифр равна 15.
24. Найти все целые числа из промежутка от 1 до 100, у которых есть цифра ‘7’.
25. Найти все целые числа из промежутка т 50 до 150, у которых есть цифра ‘9’.
26. Найти все целые числа из промежутка от 10 до 200, у которых есть цифры ‘2’ и ’5’.
27. Найти размеры всех прямоугольников, площадь которых равна заданному натуральному
числу s и стороны которого выражены натуральными числами. При этом решения, которые
получаются перестановкой размеров сторон:
а) считать разными;
б) считать совподающими.
Оператор цикла с постусловием repeat.
Инструкция repeat как и инструкция while, используется в программе, если надо провести некоторые
повторяющиеся вычисления (цикл), однако число повторений не известно и определяется самим ходом
вычислений.
В общем виде оператор выглядит так:
repeat
{последовательность операторов};
until условие;
где условие – выражение логического типа.
Оператор работает следующим образом:
1. Выполняются инструкции следующие за слово repeat.
2. Вычисляется значение условия. Если условие ложно, то повторно выполняются инструкции
цикла. Если же условие истинно, то выполнение цикла заканчивается.
Таким образом, операторы находящиеся между repeat и until выполняются до тех пор, пока условие
ложно.
Примечания:
1. Последовательность инструкций между repeat и until всегда будет выполнена хотя бы один раз.
2. Для того чтобы цикл завершился, необходимо, чтобы последовательность операторов между
repeat и until изменяла значения переменных, входящих в выражение условие.
Инструкция полезна при создании программ, обрабатывающих ввод с клавиатуры.
Пример: Составить программу вычисляющую сумму положительных чисел, вводимых с клавиатуры.
program polog;
uses crt;
var
Лекции по Turbo Pascal
24
-
n, s: integer;
begin
clrscr;
s:=0;
repeat
write (‘->’);
readln (n);
if n>0 then s:=s+n;
until n<=0;
writeln (‘Сумма введенных положительных чисел =’,s);
readln;
end.
Пример: С клавиатуры вводится число, проверить является ли оно простым.
program prost;
uses crt;
var
r, n, d: integer;
begin
clrscr;
writeln (‘Введите целое число’); readln (n);
d:=2;
repeat
r:=n mod d;
if r<>0 then d:=d+1;
until r=0;
if d=n then
writeln (n,‘ – простое число’)
else writeln (n,‘ – составное число’)
readln;
end.
Задачи:
1. Дано натуральное число.
а) Получить все его делители.
б) Найти сумму его делителей.
в) Найти сумму его четных делителей.
г) Определить количество его делителей.
д) Определить количество его нечетных делителей.
е) Определить количество его делителей. Сколько из них четных?
ж) Найти количество его делителей, больших D.
2. Натуральное число называется совершенным, если оно равно сумме своих делителей, включая
1 и, естественно, исключая это самое число. Например, число 6 - совершенное (6=1+2+3). Дано
натуральное число. Выяснить, является ли оно совершенным.
3. Найти количество делителей каждого из целых чисел от 120 до 140.
4. Найти все целые числа из промежутка от 1 до 300, у которых ровно 5 делителей.
5. Найти все целые числа из промежутка от 200 до 500, у которых ровно 6 делителей.
6. Найти все целые числа из промежутка от А до В, у которых количество делителей равно К.
Если таких чисел нет, то должно быть напечатано соответствующее сообщение.
7. Найти натуральное число из интервала от А до В, у которого количество делителей
максимально. Если таких чисел несколько, то должно быть найдено:
а) максимальное из них;
б) минимальное из них.
8. Найти все трёхзначные простые числа.
9. Найти 100 первых простых чисел.
Лекции по Turbo Pascal
25
-
10. Найти сумму делителей каждого из целых чисел от 50 до 70.
11. Найти все целые числа из промежутка от 100 до 300, у которых сумма делителей равна 50.
12. Найти все целые числа из промежутка от 300 до 600, у которых сумма делителей кратна 10.
13. Два натуральных числа называются дружественными, если каждое из них равно сумме всех
делителей другого (само другое число в качестве делителя не рассматривается).Найти все
пары дружественных чисел, меньших 50000.
14. Дана непустая последовательность неотрицательных целых чисел, оканчивающаяся
отрицательным числом. Найти среднее арифметическое всех чисел последовательности (без
учета отрицательного числа).
15. Дана непустая последовательность целых чисел, оканчивающаяся числом -1. Определить, есть
ли в последовательности хотя бы одно число, кратное 7. В случае положительного ответа
определить порядковый номер первого из них.
16. Дана последовательность натуральных чисел а1,а2,...,а15. Определить, есть ли в
последовательности хотя бы одна пара одинаковых "соседних" чисел. В случае
положительного ответа определить порядковые номера чисел первой из таких пар.
17. Дана последовательность целых чисел, оканчивающаяся числом 9999. Количество чисел в
последовательности не меньше двух. Определить, есть ли в ней хотя бы одна пара "соседних"
четных чисел. В случае положительного ответа определить порядковые номера чисел первой
из таких пар.
18. Дана последовательность вещественных чисел, оканчивающаяся числом 10000. Количество
чисел в последовательности не меньше двух. Определить, является ли последовательность
упорядоченной по возрастанию. В случае отрицательного ответа определить порядковый
номер первого числа, "нарушающего" такую упорядоченность.
Самостоятельная работа на циклы с параметром.
Сравнение работы операторов цикла (repeat, while, for).
№ Цикл с предусловием while Цикл с постусловием repeat
n/n
(пока условие истинно)
(до истинности условия)
1 До начала цикла должны быть сделаны начальные установки
переменных, управляющих условием цикла, для корректного
входа в цикл.
2 В теле цикла должны присутствовать операторы, изменяющие
переменные условия так, чтобы цикл через некоторое число
итераций закончился.
3 Цикл работает пока условие Цикл работает пока условие
истинно.
ложно.
4
Цикл завершается, когда
условие становится
ложным.
Цикл завершается, когда
условие становится истинным.
5
Цикл может не выполниться
ни разу, если исходное
значение условия при входе
в цикл ложно
Цикл обязательно выполняется
как минимум один раз.
6
Если в теле цикла требуется
более одного оператора, то
необходимо использовать
составной оператор.
Независимо от количества
операторов в теле цикла
использование составного
оператора не требуется.
Зачет по операторам цикла.
Лекции по Turbo Pascal
Цикл со счетчиком for
Начальная установка переменной
счетчика цикла до заголовка не
требуется
Изменение в теле цикла значений
переменных, стоящих в заголовке
цикла, не допускается.
Количество итераций цикла
неизменно и точно определяется
значениями верхней и нижней
границ и шага цикла.
Нормальный ход работы цикла
может быть нарушен оператором
goto или процедурами Break и
Continue.
Цикл может не выполниться ни
разу, если шаг цикла будет
изменять значение счетчика цикла
от нижней границы в
направлении, противоположном
верхней границы.
Если в теле цикла требуется более
одного оператора, то необходимо
использовать составной оператор.
26
-
Вложенные циклы
Для решения задачи достаточно часто требуется использовать две и более циклические конструкции, одна из
которых расположена внутри другой (других). Такие конструкции называют вложенными циклами.
Какие
именно циклы при этом используются, роли не играет, они могут быть организованы посредством любых
рассмотренных ранее операторов (For, While, Repeat ... Until).
Задача : Сколько можно купить быков, коров и телят, если бык стоит 10 рублей, корова - 5 рублей, теленок полтинник (0,5 рубля), при условии, что на 100 рублей надо купить 100 голов скота.
Решение : Обозначим через b- количество быков, k - количество коров, t - количество телят. После этого
можно записать два уравнения:
10b+5k+0,5t=100 и b+k+t=100
Преобразуем их :
20b+10k+t=200 и b+k+t=100
На 100 рублей можно купить :
*
не более 10 быков, т.е. 0<=b<=10;
*
не более 20 коров, т.е. 0<=k<=20;
*
не более 200 телят, т.е. 0<=t<=200;
Таким образом получаем :
Program skot;
Var b,k,t : integer;
Begin
For b:=0 to 10 do
For k:=0 to 20 do
For t:=0 to 200 do
if (20*b+10*k+t=200) and (b+k+t=100) then
writeln(‘быков ‘,b,‘ коров ’,k,’ телят ’,t);
end.
Условие будет проверятся 11*21*201=46431 раз. Но задачу можно сократить на один цикл если
количество телят вычислять по формуле:
t=100-(b+k)
Массивы.
Массив – это упорядоченный набор однотипных элементов, имеющих общее имя.
Объявление массива.
Перед использованием массив, как и любая переменная, должен быть объявлен в разделе объявления
переменных. В общем виде объявление массива выглядит так:
имя: array [нижний_индекс..верхний_индекс] of тип;
где
имя – имя переменной – массива.
array – ключевое слово, обозначающее, что переменная является массивом;
нижний_индекс и верхний_индекс – целые числа, определяющие диапазон изменения индексов
(номеров) элементов массива и, неявно, количество элементов (размер) массива;
тип – тип элементов массива.
Примеры объявления массивов:
t: array[1..31] of real;
k: array[0..2] of integer;
n: array[1..30] of longint;
Чтобы в программе использовать элемент массива, надо указать имя массива и номер элемента
(индекс), заключив его в квадратные скобки. индекс может быть константой или выражением целого
типа.
Например: t[1]:=1.22;
d:=k[1]*k[1]-4*k[2]*k[1];
readln (n[i+1]);
writeln (t[m]);
1) Оператор присваивания.
А[1]:=3;
А[2]:=4;
Лекции по Turbo Pascal
27
-
........
или
B[1]:=’Иванов’;
B[2]:=’Петров’;
........
Такой способ задания значений используется, если массив небольшой.
2) Оператором ввода с клавиатуры.
For i:=1 to 10 do
begin
Writeln(‘введите ’,i,’-ый элемент массива’);
Readln(a[i]);
{в качестве индекса используется параметр цикла }
end;
Этот способ задания значений также используется для небольших массивов.
3) Заполнение массива с использованием генератора случайных чисел.
.......
RANDOMIZE;
For i:=1 to 10 do
a[i]:=Random(x);
…....
{массив заполнится целыми числами в диапазоне от 0 до Х}
4) Заполнение по формуле.
Каждый элемент массива должен быть рассчитан по формуле (например ai=sin i - cos i)
for i:=1 to 10 do
a[i]:=sin(i)-cos(i);
Вывод массива.
For i:=1 to 10 do writeln(a[i]);
Вывод пятого элемента массива записывается так : write(a[5]);
Алгоритмы работы с массивами
1) Сумма элементов массива.
Program symma;
var a: array [1..10] of integer;
i, s : integer;
begin
s:=0;
for i:=1 to 10 do
begin
readln(a[i]);
s:=s+a[i];
end;
writeln (‘Сумма= ’,s);
еnd.
2) Сумма положительных чисел.
Program symma2;
var a: array [1..10] of integer;
i, s : integer;
begin
s:=0;
for i:=1 to 10 do
begin
readln(a[i]);
if a[i]>0 then s:=s+a[i];
end;
writeln (‘Сумма положительных чисел = ’,s);
еnd.
3) Сумма и количество положительных чисел.
Program symma-kol;
var a: array [1..10] of integer;
Лекции по Turbo Pascal
28
-
i, s,k : integer;
begin
s:=0; k:=0;
for i:=1 to 10 do
if a[i]>0 then begin k:=k+1; s:=s+a[i]; end;
writeln (‘Сумма ’,s, ‘ количество’, k);
еnd.
4) Поиск заданного элемента в массиве.
Найти элементы массива большие числа 5.
Program elem;
var a: array [1..10] of integer;
i : integer;
begin
for i:=1 to 10 do
if a[i]>5 then writeln(a[i]);
еnd.
5) Поиск наибольшего (наименьшего) элемента в массиве.
Program mm;
var a: array [1..10] of integer;
i, max, min : integer;
begin
for i:=1 to 10 do readln(a[i]);
max:=a[1]; min:=a[1];
for i:=1 to 10 do
begin
if a[i]>max Then max:=a[i];
if a[i]<min Then min:=a[i];
end;
writeln (‘ max=’,max,’ min=’, min);
еnd.
6) Упорядочение массива
Упорядочение (сортировка) - это расположение значений элементов массива в порядке возрастания или
убывания их значений.
Некоторые типичные действия с массивами:
 вывод массива;
 ввод массива;
 поиск в массиве заданного элемента;
 поиск в массиве минимального или максимального элемента;
 сортировка массива.
Вывод массива.
Под выводом массива понимается вывод на экран значений элементов массива. если в программе
необходимо вывести значения всех элементов массива, то для этого удобно использовать оператор
цикла for, переменная – счетчик которой может быть использована как индекс элемента массива.
var
a: array [1..20] of integer;
i, n: integer;
begin
clrscr;
for i:=1 to n do
writeln (a[i]); {вывод в столбик}
либо write (a[i],’ ‘); {вывод в строчку}
либо writeln (‘a[‘,i,’]=’,a[i]); {вывод с пояснениями}
readln;
end
Лекции по Turbo Pascal
29
-
Задание:
1. В массиве хранятся значения роста двадцати человек. С помощью датчика случайных чисел
заполнить массив целыми значениями, лежащими в диапазоне от 50 до 100 включительно.
2. Заполнить массив из двенадцати элементов следующим образом:
1
2
…
12
3. Заполнить массив из двадцати элементов следующим образом:
20
19
…
1
Ввод массива.
Под вводом массива понимается ввод значений элементов массива. Как и вывод массива, ввод удобно
реализовать с помощью оператора цикла for. Чтобы пользователь программы знал, ввода какого
элемента массива ожидает программа, следует организовать вывод подсказок перед вводом очередного
элемента массива. В подсказке обычно указывают индекс элемента массива.
var
a: array [1..20] of integer;
i, n: integer;
begin
clrscr;
writeln (’Введите количество элементов массива’); readln (n);
for i:=1 to n do begin
write (‘a[‘,i,’]=’);
readln (a[i]);
end;
Пример: Найти сумму элементов массива.
var
a: array [1..20] of integer;
i, n, s: integer;
begin
clrscr;
s:=0;
writeln (’Введите количество элементов массива’); readln (n);
for i:=1 to n do begin
write (‘a[‘,i,’]=’);
readln (a[i]);
s:=s+a[i];
end;
writeln (‘Сумма элементов массива=’,s);
readln;
end.
Задание:
1. Заполнить массив:
а) десятью первыми членами арифметической прогрессии с известным первым членом
прогрессии a и ее разностью p;
б) двадцатью первыми членами геометрической прогрессии с известным первым членом
прогрессии a и ее знаменателем z.
2. Дан массив. Все его элементы:
а) уменьшить на 20;
б) умножить на последний элемент;
в) увеличить на число b.
3. Определить:
а) сумму всех элементов массива;
б) произведение всех элементов массива;
в) сумму квадратов всех элементов массива;
Лекции по Turbo Pascal
30
-
г) сумму шести первых элементов массива;
д) сумму элементов массива с k1-го по k2-й (значения k1 и k2 вводятся с клавиатуры; k2>k1);
е) среднее арифметическое всех элементов массива;
ж) среднее арифметическое элементов массива с s1-го по s2-й (значения s1 и s2 вводятся с
клавиатуры; s2>s1).
4. Дан массив. Напечатать:
а) все неотрицательные элементы;
б) все элементы, не превышающие числа 100.
5. Дан массив целых чисел. Напечатать:
а) все четные элементы;
б) все элементы, оканчивающиеся нулем.
6. Дан массив натуральных чисел. Напечатать:
а) все элементы массива, являющиеся двузначными числами;
б) все элементы массива, являющиеся трехзначными числами.
7. Дан массив. Напечатать:
а) второй, четвертый и т.д. элементы;
б) третий, шестой и т.д. элементы.
Поиск в массиве.
При решении многих задач возникает необходимость установить, содержит ли массив определенную
информацию или нет. Например, определить есть ли в массиве нулевые элементы. Задачи такого типа
называются поиском в массиве.
Для организации поиска в массиве могут быть использованы различные алгоритмы. Наиболее
простой – это алгоритм простого перебора. Поиск осуществляется последовательным сравнением
элементов массива с образцом.
Например:
 Определить сколько раз в массиве встречается число а.
var
b: array [1..20] of integer;
i, n, k, a: integer;
begin
clrscr;
k:=0;
writeln (‘Введите искомое число’); readln (a);
writeln (’Введите количество элементов массива’); readln (n);
for i:=1 to n do begin
write (‘b[‘,i,’]=’);
readln (b[i]);
if b[i]=a then inc(k);
end;
writeln (‘Количество элементов равных ’,a,’ в массиве ’,k);
readln;
end.
Задачи:
1. Выяснить, верно ли, что сумма элементов массива есть неотрицательное число.
2. Дан массив целых чисел. Выяснить:
а) верно ли, что сумма элементов массива есть четное число;
б) верно ли, что сумма квадратов элементов массива есть пятизначное число.
3. Определить количество положительных и количество отрицательных элементов массива.
4. Дан массив. Найти:
а) сумму элементов массива, значение которых не превышает 20;
б) сумму элементов массива, больших числа a.
5. Дан массив целых чисел. Найти:
а) сумму нечетных элементов;
Лекции по Turbo Pascal
31
-
б) сумму элементов, кратных заданному числу;
в) сумму элементов массива, кратных a или b.
6. Определить сумму второго, четвертого, шестого и т.д. элементов массива.
7. Определить частное от деления суммы положительных элементов массива на модуль
суммы отрицательных элементов.
8. Дан массив целых чисел. Определить количество четных элементов и количество
элементов, оканчивающихся на цифру 5.
9. Определить количество элементов массива, принадлежащих промежутку от a до b
(значения a и b вводятся с клавиатуры; b>a).
10. Найти число пар ''соседних'' элементов массива, являющихся четными числами.
11. Найти число пар ''соседних'' элементов массива, оканчивающихся нулем.
12. Найти число элементов массива, которые больше своих ''соседей'', т.е. предшествующего и
последующего.
13. Найти среднее арифметическое элементов массива, больших числа 10.
14. Найти средние арифметические положительных и отрицательных элементов массива.
15. Дан массив вещественных чисел.
а) Каждый отрицательный элемент заменить на его абсолютную величину.
б) Все элементы с нечетными номерами заменить на их квадратный корень.
в) Из всех положительных элементов вычесть элемент с номером k1, из остальных элемент с номером k2.
г) Все элементы с нечетными номерами увеличить на 1, с четными - уменьшить на 1.
д) Из всех положительных элементов вычесть элемент с номером k1, из всех
отрицательных - число n. Нулевые элементы оставить без изменения.
е) Ко всем нулевым элементам прибавить n, из всех положительных элементов вычесть
a, ко всем отрицательным прибавить b.
16. Дан массив вещественных чисел.
а) Каждый элемент, больший 10, заменить на его квадратный корень.
б) Все элементы массива с четными номерами заменить на их абсолютную величину.
в) Ко всем отрицательным элементам прибавить элемент с номером m1, к остальным элемент с номером m2.
г) Все элементы с четными номерами удвоить, с нечетными - уменьшить на 1.
д) Ко всем отрицательным элементам прибавить элемент с номером a1, из всех нулевых
вычесть число b. Положительные элементы оставить без изменения.
е) Из всех положительных элементов вычесть a, из всех отрицательных вычесть b. Ко
всем нулевым элементам прибавить c.
17. Дан массив целых чисел.
а) Все элементы, оканчивающиеся цифрой 4, уменьшить вдвое.
б) Все четные элементы заменить на их квадраты, а нечетные удвоить.
в) Четные элементы увеличить на a, а из элементов с четными номерами вычесть b.
18. Дан массив целых чисел.
а) Все элементы, кратные числу 10, заменить нулем.
б) Все нечетные элементы удвоить, а четные уменьшить вдвое.
в) Нечетные элементы уменьшить на m, а элементы с нечетными номерами увеличить
на n.
Самостоятельная работа на ввод и вывод массива.
Поиск в массиве минимального или максимального элемента.
Алгоритм поиска минимального (максимального) элемента массива довольно очевиден: делается
предположение, что первый элемент массива является минимальным (максимальным), затем остальные
элементы массива сравниваются с этим элементом. Если обнаруживается, что проверяемый элемент
меньше (больше) принятого за минимальный (максимальный), то этот элемент принимается за
минимальный (максимальный) и продолжается проверка остальных элементов.
Найти минимальный элемент массива и его индекс.
var
Лекции по Turbo Pascal
32
-
a: array [1..20] of integer;
i, n, k, min, nmin: integer;
begin
clrscr;
writeln (’Введите количество элементов массива’); readln (n);
for i:=1 to n do begin
write (‘a[‘,i,’]=’);
readln (a[i]);
end;
min:=a[1]; nmin:=1;
for i:=2 to n do
if min>b[i] then begin
min:=b[i];
nmin:=i;
end;
writeln (‘Минимальный элемент массива ’, min, ‘ его индекс ’, nmin);
readln;
end.
Задачи:
1. Дан массив. Определить:
а) максимальный элемент;
б) минимальный элемент;
в) на сколько максимальный элемент больше минимального;
г) индекс максимального элемента;
д) индекс минимального и индекс максимального элементов.
2. Дан массив. Определить:
а) количество максимальных элементов в массиве;
б) количество минимальных элементов в массиве.
3. Изменить знак у максимального по модулю элемента массива. Минимальный элемент
массива при этом не определять.
4. Дан массив. Найти количество элементов, значение которых больше среднего
арифметического минимального и максимального элементов массива, и напечатать их
номера.
5. Найти элемент, наиболее близкий к среднему значению всех элементов массива.
6. Дан массив. Скопировать все его элементы в другой массив такого же размера:
а) в том же порядке расположения элементов;
б) в обратном порядке расположения элементов.
7. Дан массив. Переписать его второй, четвертый и т.д. элементы в другой массив такого же
размера:
а) расположив элементы на тех же местах, что и в исходном массиве;
б) расположив элементы подряд с начала массива.
8. Из элементов массива A сформировать массив B того же размера по правилу: если номер i
элемента массива A четный, то Bi = Ai2, в противном случае Bi = 2·Ai.
9. Из элементов массива A, заполненного целыми числами, сформировать массив B того же
размера по правилу: четные элементы массива A удвоить, нечетные оставить без
изменения.
10. Даны два массива одного размера. Получить третий массив, каждый элемент которого
равен:
а) сумме элементов с одинаковыми номерами в заданных массивах;
б) произведению элементов с одинаковыми номерами в заданных массивах;
в) максимальному из элементов с одинаковыми номерами в заданных массивах.
Лекции по Turbo Pascal
33
-
11. Даны два массива одного размера, в которых нет нулевых элементов. Получить третий
массив, каждый элемент которого равен 1, если элементы заданных массивов с тем же
номером имеют одинаковый знак, и равен нулю в противном случае.
12. Дан массив целых чисел.
а) Напечатать все элементы, предшествующие первому элементу с заданным значением
n. Если элементов, равных n, в массиве нет, то должны быть напечатаны все
элементы.
б) Напечатать все элементы, следующие за последним элементом, оканчивающимся
цифрой "7". Если элементов, оканчивающихся цифрой "7", в массиве нет, то ни один
элемент не должен быть напечатан.
13. Найти количество различных элементов в массиве.
14. Дано натуральное число n. Определить количество различных цифр в нем. Например, в
числе 1234 количество различных цифр равно 4, в числе 22424 - 2, в числе 333 - 1.
15. Дан массив целых чисел. Найти:
а) номер первого нечетного элемента. Если нечетных элементов в массиве нет, то
должно быть напечатано соответствующее сообщение;
б) номер первого элемента, кратного числу 13. Если нечетных элементов в массиве нет,
то должно быть напечатано соответствующее сообщение;
16. Дан массив вещественных чисел. Определить, есть ли в нем отрицательные числа. В случае
положительного ответа:
а) определить номер первого из них и напечатать все следующие за ним элементы;
б) определить номер последнего из них напечатать все элементы, расположенные слева
от него.
Самостоятельная работа на поиск в массиве.
Обмены и перестановки. Для перестановки элементов вводят вспомогательную переменную, которой
присваивают значение первого элемента, после чего первому элементу присваивают значение второго
элемента, а второму – значение вспомогательной переменной.
Задачи:
1. Дан массив. Поменять местами:
а) второй и пятый элементы;
б) m-й и n-й элементы;
в) третий и максимальный элементы. Если элементов с максимальным значением
несколько, то в обмене должен участвовать первый из них;
г) первый и минимальный элементы. Если элементов с минимальным значением
несколько, то в обмене должен участвовать последний из них.
2. Дан массив из четного числа элементов. Поменять местами:
а) его половины;
б) первый элемент со вторым, третий - с четвертым и т.д.;
в) его половины следующим способом: первый элемент поменять с последним, второй с предпоследним и т.д.
3. Дан одномерный массив из 20 элементов. Переставить первые три и последние три
элемента, сохранить порядок их следования.
4. Поменять местами первый отрицательный и последний положительный элементы массива.
Учесть возможность того, что отрицательных или положительных элементов в массиве
может не быть.
В задачах под удалением элемента массива следует понимать:
1) исключение этого элемента из массива путем смещения всех следующих за ним элементов
влево на 1 позицию;
2) присваивание последнему элементу массива значения 0.
5. Удалить из массива:
а) третий элемент;
б) k-й элемент.
6. Удалить из массива, в котором все элементы различны:
а) максимальный элемент;
б) минимальный элемент.
Лекции по Turbo Pascal
34
-
7. Удалить из массива:
а) первый отрицательный элемент (если отрицательные элементы в массиве есть);
б) удалить последний четный элемент (если четные элементы в массиве есть).
8. Удалить из массива:
а) все отрицательные элементы;
б) все элементы, большие данного числа n;
в) все элементы, начиная с n1-го по n2-й (n1n2).
9. Дан массив целых чисел. Удалить из него:
а) все четные элементы, стоящие на нечетных местах;
б) все элементы, кратные 3 и 5.
10. Удалить из массива все повторяющиеся элементы, оставив их первые вхождения, то есть в
массиве должны остаться только различные элементы.
В задачах под вставкой числа n в массив после k-го элемента следует понимать:
1) увеличение размера массива на 1;
2) смещение всех элементов, начиная с (k+1)-го, вправо на 1 позицию;
3) присваивание (k+1)-му элементу массива значения n.
11. Вставить в массив:
а) число 10 после второго элемента;
б) число 100 после m-го элемента.
12. Вставить заданное число в массив целых чисел:
а) после первого отрицательного элемента;
б) перед последним четным элементом.
13. Вставить заданное число в массив целых чисел:
а) перед всеми элементами, кратными числу a;
б) после всех отрицательных элементов.
Контрольная работа на массивы.
8 класс.
Сортировка массива.
Под сортировкой массива подразумевается процесс перестановки элементов с целью
упорядочивания их в соответствии с каким-либо критерием. Например, если имеется массив а - целых
чисел, то после сортировки по возрастанию должно выполняться условие: a[1]a[2] …a[n], где n –
верхняя граница индекса массива.
Существует много методов сортировки массивов. Но наиболее часто используемые это:

метод прямого выбора (метод главного элемента);

метод прямого обмена(метод пузырька).
Метод главного элемента.
Алгоритм сортировки массива по возрастанию методом прямого выбора или методом главного
элемента может быть представлен так:
1. Просматривая массив от первого элемента, найти минимальный и поместить на место
первого элемента, а первый на место минимального.
2. просматривая массив от второго элемента, найти минимальный и поместить его на место
второго элемента, а второй на место минимального.
3. И так далее до предпоследнего элемента.
Ниже представлена программа сортировки массива целых чисел по возрастанию.
program vosr;
uses crt;
var a: array [1..15] of integer;
i, j, k, n, m, c: integer;
begin
clrscr;
writeln (‘’); readln (n);
for i:=1 to n do begin
write (i,’:’); readln (a[i]);
end;
Лекции по Turbo Pascal
35
-
for i:=1 to n-1 do begin
k:=i;
for j:=i+1 to n do
if a[j]<a[k] then k:=j;
c:=a[i];
a[i]:=a[k];
a[k]:=c;
end;
for i:=1 to n do
writeln (a[i]);
readln;
end.
Метод прямого обмена (метод пузырька).
В основе алгоритма лежит обмен соседних элементов массива. Каждый элемент массива, начиная с
первого сравнивается со следующим и если он больше следующего, то элементы меняются местами.
Таким образом, элементы с наименьшим значением продвигаются к началу массива (всплывают), а
элементы с большим значением – к концу массива (тонут), поэтому его и называют методом пузырька.
Этот процесс повторяется на единицу меньше раз чем элементов в массиве, либо возможно другой
способ реализации этого метода, повторяется до тех пор пока находятся соседние элементы, такие что
элемент стоящий правее оказывается меньше элемента стоящего левее.
program vosr;
uses crt;
program vosr;
var a: array [1..15] of integer;
uses crt;
i, j, k, n, m, c, f: integer;
var a: array [1..15] of integer;
begin
i, j, k, n, m, c, f: integer;
clrscr;
begin
writeln (‘’); readln (n);
clrscr;
for i:=1 to n do begin
writeln (‘’); readln (n);
write (i,’:’); readln (a[i]);
for i:=1 to n do begin
end;
write (i,’:’); readln (a[i]);
for i:=1 to n-1 do begin
end;
for j:=1 to n-1 do
k:=n-1;
if a[j]>a[j+1] then begin
repeat
c:=a[j];
f:=0;
a[j]:=a[j+1];
for i:=1 to k do
a[j+1]:=c;
if a[i]>a[i+1] then begin
end;
f:=1;
end;
c:=a[i];
for i:=1 to n do
a[i]:=a[i+1];
writeln (a[i]);
a[i+1]:=c;
readln;
end;
end.
dec(k);
until f=0;
for i:=1 to n do
writeln (a[i]);
readln;
end.
6) Упорядочение массива
Лекции по Turbo Pascal
36
-
Упорядочение (сортировка) - это расположение значений элементов массива в порядке возрастания или
убывания их значений.
Сортировка простым выбором.
Рассмотрим идею этого метода на примере. Пусть исходный массив А состоит из 10 элементов : 5 13
7 9 1 8 16 4 10 2.
После сортировки массив : 1 2 4 5 7 8 9 10 13 16
Максимальный элемент текущей части массива заключен в кружок, а элемент, с которым происходит
обмен, в квадратик. Скобкой помечена рассматриваемая часть массива.
1 шаг Рассмотрим весь массив и
16. Поменяем его местами с последним
2 шаг. Рассмотрим часть массива,
Максимальный элемент этой части - 13,
его местами с последним элементом этой
5 13 7 9 1 8 16 4 10 2
найдем в нем максимальный элемент элементом - с числом 2.
исключая
последний
элемент.
он стоит на втором месте. Поменяем
части - с числом 10.
5 13 7 9 1 8 2 4 10 16
И т.д.
Фрагмент программы :
for i:=n downto 2 do
begin {цикл по длине рассматриваемой части массива}
maxi:=i;
for j:=1 to i-1 do if a[j]>a[maxi] then maxi:=j;
if maxi<>i then begin {перестановка элементов}
k:=a[i]; a[i]:=a[maxi]; a[maxi]:=k
end;
end;
«Пузырьковый метод»
Массив просматривают слева направо. Каждый предыдущий элемент сравнивается с последующим.
Если предыдущий элемент больше последующего, то предыдущий и последующий элементы меняются
местами.
Program sort1;
const n=10;
label metka;
var a: array [1..n] of integer;
i, c, k : integer;
begin
for i:=1 to n do readln(a[i]);
metka: k=0; {счетчик перестанокок}
for i:=1 to n-1 do
if a[i]>a[i+1] then begin c:=a[i];
a[i]:=a[i+1];
a[i+1]:=c;
k:=1;
end;
if k=1 then goto metka
else writeln(‘упорядочен‘);
for i:=1 to n do writeln(a[i]);
еnd.
Тоже самое, но с использованием вложенных циклов
Program sort2;
const n=10;
var a: array [1..n] of integer;
i, k, c : integer;
begin
for i:=1 to n do readln(a[i]);
for i:=1 to n-1 do
for k:=1 to n-i do
if a[k]>a[k+1] then begin c:=a[k];
a[k]:=a[k+1];
a[k+1]:=c;
Лекции по Turbo Pascal
37
-
end;
for i:=1 to n do writeln(a[i]);
еnd.
Двухмерные массивы.
Описание двумерного массива определяет имя, размер массива (количество строк и столбцов) и
базовый тип. Формат описания в разделе переменных:
Var <имя маcсива > : array [<тип индекса1> , <тип индекса2>] of <базовый тип>;
Двумерный массив — массив, у которого положение каждого элемента характеризуется двумя
числами, первое из них определяет номер строки, второе – номер столбца, на пересечении которых
находится элемент. Он так же, как и одномерный массив, состоит из значений одного типа. В
двумерных массивах хранятся значения прямоугольных таблиц. Примеры описания двумерных
массивов:
Var С : array [1. .5, 1. .10] of real;
R1, R2: array [0. .10, 1. .365] of char;
Sim : array [1. .20, 1. .10] of string[20];
Const M=10; N=20;
Var
X, S : array [1. .M, 1. .N] of byte;
1. Организация данных в виде массивов помогает нам решать многие задачи. Вот еще одна:
разработать программу, обслуживающую шахматный турнир.
В одиночных соревнованиях каждый участник имеет один результат, поэтому данные о
результатах соревнований удобно хранить в знакомых нам массивах. Игровой турнир
предполагает встречи участников друг с другом, при этом каждый участник имеет столько
результатов, со сколькими соперниками он встречался.
Обычно результаты турниров заносятся в турнирные таблицы. Средством обработки таких
таблиц в языках программирования служат двумерные массивы.
2. Описание двумерного массива в языке паскаль записывается так:
<Имя_массива> : array[<n1>..<n2>,<k1>..<k2>] of [<тип>]
где строки таблицы имеют номера с n1 по n2, а столбцы - с k1 по k2. Запись
<Имя_массива>[n,k] указывает на элемент, стоящий на пересечении n-й строки и k-го столбца.
Например, описание
Tab : array[1..10,1..15] of Integer
задает таблицу из 10 строк и 15 столбцов (всего 10 х 15 = 150 элементов), состоящую из целых
чисел. Tab[3,5] указывает на 5-й элемент в 3-й строке.
Турнирную таблицу для N участников удобно хранить в двумерном массиве N x N типа Real,
т.к. результатом шахматной партии для каждого участника может быть победа (1 очко),
поражение (0 очков) или ничья (0.5 очка). Вот описание таблицы:
Tab : array[1..N,1..N] of Real .
3. Для простоты не будем пока рассматривать фамилии участников, а будем различать их
по номерам. Вводить результаты встреч будем в таком виде: номер первого участника,
номер второго участника, результат первого участника (количество очков). Понятно, что
одна встреча приводит к заполнению сразу двух элементов таблицы. Так будет выглядеть
фрагмент программы, предназначенный для ввода результата одной встречи:
writeln('Введите номера участников встречи');
readln(n1,n2);
writeln('Сколько очков у участника ',n1,' ?');
readln(Tab[n1,n2]);
Tab[n2,n1] := 1-Tab[n1,n2];
4. Эти действия нужно повторять столько раз, сколько встреч состоится в турнире. Если все
запланированные встречи состоятся, то их количество можно сосчитать по формуле n(n-1) Лекции по Turbo Pascal
38
подумайте, почему. Однако, может случиться, что по каким-то причинам часть встреч не
состоится, а какие-то будут сыграны дважды. Поэтому удобнее как-то обозначить окончание
ввода данных в программе, например, после каждой встречи выяснять, будут ли еще
вводиться данные. Вот фрагмент программы, предназначенный для ввода результатов всех
встреч турнира:
kon := 'Д';
while kon <> 'Н' do
begin
writeln('Введите номера участников встречи');
readln(n1,n2);
writeln('Сколько очков у участника ',n1,' ?');
readln(Tab[n1,n2]);
Tab[n2,n1] := 1-Tab[n1,n2];
writeln('Будут ли еще встречи ? (Д/Н)');
readln(kon);
end;
5. По окончании турнира нужно вывести турнирную таблицу на экран:
for i := 1 to N do
begin
for k := 1 to N do
write(Tab[i,k]:3:1);
writeln;
end;
7. Бывают задачи, в которых данные удобно хранить в виде трехмерного (и даже четырех- и
более -мерного) массива. Например, результат встречи в футбольном турнире представляет
собой не одно, а три числа - количество забитых и пропущенных мячей и количество очков
(2 - победа, 0 - поражение, 1 - ничья). Такую таблицу удобно заносить в массив
Football : array[1..N,1..N,1..3] of Integer;
Элемент Football[3,5,2] содержит информацию о количестве мячей, пропущенных 3-й командой
в матче с 5-й командой.
Поразмышляйте самостоятельно над процедурой ввода результатов футбольного турнира.
Работа с элементами
В математике часто используют многомерные массивы (двумерные, трехмерные и т.д.). Мы рассмотрим
двумерные массивы, иначе называемые матрицами.
Например :
5 4 3 6
2 8 1 7
4 3 9 5
Данная матрица имеет размер 3 на 4, т.е. она состоит из трех строк и четырех столбцов. Если всю матрицу
обозначить одним именем, например А, то каждый элемент матрицы будет иметь два индекса - А[i,j]
Здесь первый индекс i обозначает номер строки (i=1,2,3), второй индекс j - номер столбца (j=1,2,3,4).
Такую матрицу можно описать следующим образом :
1 способ :С использованием типа
Type T=array [1..3,1..4] of integer;
Var A: T;
2 способ :
Var A: array [1..3,1..4] of integer;
При решении задач с использованием двумерных массивов во всех случаях (кроме некоторых частных)
организуются вложенный циклы.
Перемещение по строке :
Лекции по Turbo Pascal
39
-
for i:=1 to m do {внешний цикл, изменяется номер строки}
.......
for j:=1 to n do {внутренний цикл, изменяется номер столбца}
..........
Перемещение по столбцу :
for j:=1 to n do {внешний цикл, изменяется номер столбца}
.......
for i:=1 to m do {внутренний цикл, изменяется номер строки}
Перечислим базовые алгоритмы и рассмотрим каждый из них.
1. Заполнение двумерного массива :
а) по строке;
б) по столбцу
2. Печать в виде таблицы.
3. Вычисление суммы элементов каждой строки и каждого столбца.
4. Поиск максимального (минимального) элементов каждой строки (столбца) и их индексов.
5. Сумма элементов массива.
6. Максимальный (минимальный) элемент массива.
Ввод (заполнение) элементов двумерного массива (матрицы)
For i:=1 to n do
For j:=1 to m do
Readln(A[i,j]);
1. Заполнение двумерного массива по строке.
Массив содержит 3 строки и 4 столбца, т.е. 3х4=12 элементов
For i:=1 to 3 do
For j:=1 to 4 do
a[i,j]:=random(100);
а11
а21
.
а12
.
.
2. Заполнение двумерного массива по столбцу :
For j:=1 to 4 do
а11
а12
For i:=1 to 3 do
а21
.
a[i,j]:=random(100);
а
.
31
а13
.
.
.
.
.
а14
.
.
.
.
.
3. Печать содержимого на экран :
For i:=1 to n do
begin
For j:=1 to m do
Write (A[i,j]); {Вывод элементов одной
строки матрицы}
Writeln; { переход на следующую строку экрана}
end;
где
А - имя массива;
i - индекс строки;
j - индекс столбца;
n - количество элементов в строке;
m - количество элементов в столбце.
4. Вычисление суммы элементов каждой строки, столбца.
Дана квадратная матрица NxN, содержащая вещественные числа. Найти сумму элементов первого столбца.
Program pr2;
CONST N=3;
TYPE MAS=array [1..N,1..N] of real;
Var a: MAS;
i: 1..3;
j : 1..3;
s:real;
Лекции по Turbo Pascal
40
-
BEGIN
Writeln(‘Введите элементы массива’);
For i:=1 to n do
For j:=1 to n do
Readln(a[i,j]);
{Вывод значений массива}
For i:=1 to n do
begin
For j:=1 to n do
Write (a[i,j]:5:1);
Writeln;
end;
s:=0; j=1;
For i:=1 to n do
s:=s+a[i,j];
Writeln(‘Сумма элементов первого столбца = ’,s:5:2);
end.
5.Вычисление суммы элементов всего двумерного массива.
......
S:=0;
for i:=1 to m do
for j:=0 to n do
S:=S+a[i,j];
.............
6. Задача поиска максимального (минимального) элемента и его индексов.
Ищем максимальный элемент каждой строки :
For i:=0 to m do
begin
max:=a[i,1];
ind_L:=i; {сохраняем номер строки}
ind_C:=1; {заносим номер 1 - первый столбец}
for j:=1 to n do
if a[i,j]>max then begin
max:=a[i,j];
ind_C:=j {сохраняем номер j-ого столбца}
end;
writeln(‘max строки ’,i,’=’,max)
end;
Ищем минимальный элемент каждого столбца :
For j:=0 to n do { перемещаемся по столбцу}
begin
min:=a[1,j];
ind_L:=1; {сохраняем номер строки}
ind_C:=j; {сохраняем номер столбца}
for i:=1 to m do
if a[i,j]<min then begin
min:=a[i,j];
ind_L:=i {сохраняем номер j-ой строки}
end;
writeln(‘min ‘,j,’ столбца’,min)
end;
7. Алгоритм поиска минимального элемента и его индексов для всего массива.
Min:=a[1,1];
ind_L:=1;
ind_C:=1;
for i:=1 to m do
for j:=1 to n do
if a[i,j]<min then begin
Лекции по Turbo Pascal
41
-
min:=a[i,j]; ind_L:=i; ind_C:=j;
end;
8. Квадратные матрицы.
Type mas4x4=array[1..4,1..4] of integer;
var a: mas4x4;
Главная диагональ элементы a11, a22, a33, a44 (индексы элементов,
a11 a12 a13 a14
расположенных на главной диагонали (i=j)
Побочная диагональ - элементы a41, a32, a23, a14 (сумма индексов элементов на 1
a21
a22
a23
a24
больше размерности строки (или столбца), т.е. i+j=4=1 или i+j=n+1. На рисунке
главная диагональ закрашена сплошным серым цветом, побочная - черным.
a31
a32
a33
a34
a41
a12
a42
a13
a43
a14
a44
a23
a24
a34
Элементы, расположенные над главной диагональю, Для индексов
элементов, расположенных над главной диагональю выполняется отношение
i<j;
Элементы,
расположенные
под
главной диагональю, Для индексов
элементов, расположенных под главной
a21
диагональю выполняется отношение i>j;
a31
a32
a41
a42
a43
Примеры :
1) Найти сумму элементов главной диагонали:
S:=0;
for i:=1 to n do
S:=S+a[i,i];
2) Найти минимальный элемент побочной диагонали:
min:=a[1,n];
for i:=1 to n do
if a[i,n+1-i]<min then min:=a[i,n+1-i];
Примеры решения задач
Задача 1. Дан массив действительных чисел, состоящий из 3 строк и 5 столбцов. Вычислить произведение
всех элементов массива.
Program pr1;
CONST N=3; M=5;
TYPE MAS=array [1..N,1..M] of real;
Var b: MAS;
i: 1..N;
j : 1..M;
p:real;
BEGIN
Writeln(‘Введите элементы массива’);
For i:=1 to n do
For j:=1 to m do
Readln(b[i,j]);
{Вывод значений массива}
For i:=1 to n do
begin
For j:=1 to m do
Write (b[i,j]); {Вывод элементов одной строки матрицы}
Лекции по Turbo Pascal
42
-
Writeln; { переход на следующую строку экрана}
end;
p:=1;
For i:=1 to n do
For j:=1 to m do
p:=p*b[i,j];
Writeln(‘Произведение = ’,p:7:2);
end.
Задача 2. Дан двумерный массив A[N,M]
Сформировать массив B[N,M], где
SQR(A[I.J]), если I- НЕЧЕТНОЕ;
B[I,J] =
SQRТ(A[I.J]), если I- ЧЕТНОЕ;
Program pr3;
CONST N=3; M=5;
TYPE MAS=array [1..N,1..M] of real;
Var a,b : MAS;
i: 1..N;
j : 1..M;
BEGIN
Writeln(‘Введите элементы массива’);
For i:=1 to N do
For j:=1 to M do
Readln(a[i,j]);
{Вывод значений массива}
For i:=1 to N do
begin
For j:=1 to M do
Write (a[i,j]:5:1);
Writeln;
end;
For i:=1 to N do
if i/2= int(i/2) Then For j:=1 to M do
b[i,j]:=sqrt (a[i,j])
Else For j:=1 to M do
b[i,j]:=sqr (a[i,j])
For i:=1 to N do
begin
For j:=1 to M do
Write (b[i,j]:7:2);
Writeln;
end;
end.
Дан двухмерный массив целых чисел. Составить программу :
а) вывода на экран элемента, расположенного в правом верхнем углу массива;
б) вывода на экран элемента, расположенного в левом нижнем углу массива;
в) вывода на экран любого элемента второй строки массива;
г) вывода на экран любого элемента третьего столбца массива;
д) вывода на экран любого элемента массива.
9.2 Дан двухмерный вещественный массив. Поменять местами :
а) элементы, расположенные в верхнем правом и нижнем левом углах;
б) элементы, расположенные в нижнем правом и верхнем левом углах;
9.3 Известен номер строки, на которой расположен элемент главной диагонали двумерного массива
целых чисел. Вывести на экран значение этого элемента.
9.4 Вывести на экран (в одну строку) :
Лекции по Turbo Pascal
9.1
43
-
а) все элементы главной диагонали целочисленного массива, начиная с элемента, расположенного
в левом верхнем углу;
б) все элементы главной диагонали вещественного массива, начиная с элемента, расположенного в
правом нижнем углу.
9.5 Заменить значения всех элементов главной диагонали целочисленного массива на нулевые.
9.6 Заменить значения всех элементов побочной диагонали целочисленного массива на значения,
равные 100.
9.7 Определить :
а) сумму элементов главной диагонали вещественного массива;
б) сумму элементов побочной диагонали целочисленного массива;
в) среднее арифметическое элементов главной диагонали массива целых чисел;
г) среднее арифметическое элементов побочной диагонали вещественного массива;
д) минимальный (максимальный) элемент главной диагонали целого массива;
е) максимальный (минимальный) элемент побочной диагонали вещественного массива;
ж) координаты первого максимального элемента главной диагонали вещественного массива;
з) координаты первого минимального элемента главной диагонали целочисленного массива.
9.8 Верно ли, что сумма элементов главной диагонали целочисленного массива не превышает 100?
9.9 Дан двухмерный массив вещественных чисел .
а) вывести на экран все элементы пятой строки массива;
б) вывести на экран все элементы третьей строки массива, начиная с по следнего элемента этой
строки;
в) вывести на экран все элементы s-го столбца массива;
г) заменить значения всех элементов второй строки массива на число 5;
д) заменить значения всех элементов пятого столбца на число 10.
е) определить максимальный (минимальный) элемент третьего столбца;
9.10 Дан двухмерный целых чисел массив. Составить программу :
а) расчета произведения двух любых элементов любой строки массива
б) сумму всех элементов любой строки массива;
9.11 Дан двумерный массив целых чисел. Определить :
а) в каком столбце массива сумма элементов меньше, в первом или в последнем;
б) в какой строке произведение элементов больше, во второй или в третьей.
9.12 Заполнить двумерный массив размером 7х7 следующим образом :
а 1 0 0 0 0 0 1 б) 1 0 0 1 0 0 1
)
0 1 0 0 0 1 0
0 1 0 1 0 1 0
0 0 1 0 1 0 0
0 0 1 1 1 0 0
0 0 0 1 0 0 0
1 1 1 1 1 1 1
0 0 1 0 1 0 0
0 0 1 1 1 0 0
0 1 0 0 0 1 0
0 1 0 1 0 1 0
1 0 0 0 0 0 1
1 0 0 1 0 0 1
*
9.13
Заполнить массив 5х5 следующим образом :
а) 1 1 1 1 1
б) 1 2 3 4 5
1 2 3 4 5
16 17 18 19 6
1 3 6 10 15
15 24 25 20 7
1 4 10 20 35
14 23 22 21 8
1 5 15 35 70
13 12 11 10 9
*
9.14 Заполнить двумерный массив размером nxn числами 1, 2, ... n2, расположенным в нем по спирали
: (см 9.13б)
9.15 Дан двухмерный целочисленный массив размером 10 х 10. Вывести на экран часть массива :
а) расположенную выше главной диагонали;
б) расположенную ниже главной диагонали;
в) расположенную выше побочной диагонали;
г) расположенную ниже побочной диагонали;
Лекции по Turbo Pascal
44
9.16
9.17
9.18
9.19
9.20
9.21
Дан двумерный массив целых чисел :
а) в каждом его столбце найти максимальный (минимальный) элемент;
б) координаты максимального (минимального) элемента;
в) сумму нечетных элементов в каждом столбце (строке);
г) количество элементов кратных А или В.
д)* найти строку с максимальной суммой элементов;
е)* найти столбец с минимальной суммой элементов.
Даны два двумерных вещественных массива одинаковых размеров.
а) создать третий массив такого же размера, каждый элемент которого равен сумме
соответствующих элементов двух первых массивов.
б) создать третий массив такого же размера, каждый элемент которого равен 100, если
соответствующие элементы двух первых массивов имеют одинаковый знак, и равен нулю в
противном случае.
*
Дан двухмерный массив размером nxn , заполненный целыми числами.
а) все его элементы, кратные трем, записать в одномерный массив.
б) все его положительные элементы записать в один одномерный массив, а остальные - в другой.
Дан двухмерный массив целых чисел.
а) сформировать одномерный массив, каждый элемент которого равен сумме четных
положительных элементов соответствующего столбца двумерного массива.
б) сформировать одномерный массив, каждый элемент которого равен количеству нечетных
отрицательных элементов соответствующего столбца двумерного массива.
в) сформировать одномерный массив, каждый элемент которого равен количеству отрицательных
элементов соответствующей строке двухмерного массива, кратных 3 или 7.
г) сформировать одномерный массив, каждый элемент которого равен количеству положительных
элементов соответствующего столбца двухмерного массива, кратных 4 или 5.
*
Дан двумерный массив из четного числа столбцов. Поменять местами первый со вторым, третий
- с четвертым и т.д.
Дан двухмерный массив. а) удалить из него k-ую строку, s-ый столбец.
ЗАДАЧИ ПОВЫШЕННОЙ СЛОЖНОСТИ
9.22
9.23
9.24
9.25
9.26
9.27
9.28
Напечатать строку, образованную символами, расположенными в четырех углах символьного
массива (в любом порядке).
Составить программу, которая печатает слово, образованное несколькими идущими подряд
символами с заданными номерами, расположенными в некоторой строке символьного массива.
Дан двумерный массив размером
*
*
*
5х5,
заполненный
буквами.
*
*
Напечатать слово, образованное
*
*
*
элементами массива, отмеченными
*
*
звездочкой (*), при прочтении их:
*
*
*
а) слева направо в каждой строке,
начиная с первой;
б) сверху вниз в каждом столбце, начиная с первого.
Напечатать слова, образованные четными элементами каждой строки массива.
В каждой строке двумерного символьного массива найти количество букв «Е», расположенных
справа от буквы «Н»
Проверить, одинаковые ли строки целочисленного массива с номерами N и М.
Найти :
а) номер первой по порядку строки целочисленного массива, содержащей наибольшее число
цифр;
б) номер первого по порядку столбца символьного массива, содержащего наибольшее число
пробелов;
в) номер последней по порядку строки символьного массива, содержащей наибольшее количество
букв «Ш» и «Щ».
Лекции по Turbo Pascal
45
9.29
Шахматную доску представить в виде квадратного символьного массива размером 8 х 8.
Заполнить массив таким образом, чтобы элементы массива, соответствующие черным полям,
имели значение Х. Левое нижнее поле на шахматной доске всегда черное.
Символы и строки.
Помимо числовой информации компьютер может обрабатывать символьную информацию. Turbo
Pascal оперирует информацией, которая может быть представлена отдельными символами или строками
символов.
Символы.
Для хранения и обработки отдельных символов используются переменные типа. Значением
переменной типа char может быть любой символ. Переменная символьного типа должна быть
объявлена в разделе описания переменных так:
Имя:;
где имя – имя переменной символьного типа, char – ключевое слово обозначения символьного типа.
Примеры: otv: char;
ch: char;
Как и любая переменная программы, переменная типа char может получить свое значение в
результате выполнения команды присвоения или ввода (read, readln). Если переменная типа char
получает значение в результате выполнения операции присвоения, то справа от знака := должно стоять
выражение типа char или символьная константа – символ, заключенный в двойные кавычки.
В результате выполнения программы:
var
c1, c2, otvet: char;
begin
c1:=’*‘;
c2:=c1;
write (‘Вы хотите научиться программировать?’);
readln (otvet);
writeln (c1, ‘Ваш ответ: ’, otvet, c2);
readln;
end.
переменная с1 получает значение присваиванием значения константы, с2 – присваиванием значения
переменной с1, а значение переменной otvet вводится с клавиатуры.
Обратите внимание: переменная otvet объявлена как char, т.е. один символ. Поэтому если в ответ на
вопрос программы будет введено, например слово «Да», то переменная otvet получит значение «Д».
Переменную типа char можно сравнивать с другой переменной типа char или с символьной
константой. Сравнение основано на том, что каждому символу поставлено в соответствии число,
причем символу ‘0’ соответствует число меньшее чем символу ‘9’, а символу ‘A’ – меньшее, чем ‘B’,
символу ‘Z’ – меньшее чем ‘a’. Таким образом можно записать:
‘0’<’1’<…<’9’<…<’A’<’B’<…<’Z’<’a’<’b’<…<’z’.
Символам русского алфавита соответствуют числа большие, чем символы латинского алфавита.
Задание: С клавиатуры вводится символ, определить чем он является буквой гласной или согласной,
цифрой, знаком препинания или каким другим символом.
Строки.
Последовательность символов называют строкой. Для хранения и обработки последовательностей
символов (строк) можно использовать массив символов. Например, если программа должна вводить с
клавиатуры фамилии людей. Эту задачу можно решить вводя строки в символьный массив, длина
которого выбирается равной количеству букв самой длиной фамилии. Однако в этом случае на
клавиатуре каждый раз приходится набирать строку длиной равной ровно столько символов сколько в
самой длиной фамилии (дополняя короткие фамилии пробелами), что не очень удобно. Поэтому
помимо массивов из символов есть такое понятие как строки, это переменные типа string, Значением
переменной типа string может быть любая последовательность символов длиной не более 255.
Переменная типа string должна быть объявлена в разделе описания переменных так:
Лекции по Turbo Pascal
46
-
Имя: string;
или
Имя: string[длина];
где Имя – имя переменной; string – ключевое слово обозначения строкового типа; длина – константа
типа integer, определяющая максимальную длину последовательности символов, которая может быть
присвоена переменной.
Примеры: name: string [30]:
s: string;
Если при объявлении переменной длина не указывается, то предполагается что длина строки
равняется 255 символам, т.е. объявления s: string; и s:string[255]; эквивалентны.
В тексте программы последовательность символов, являющаяся строкой, заключается в одинартные
кавычки. Например, чтобы присвоить строковой переменной parol значение, нужно записать:
parol:=’большой секрет’;
или parol:=’2004’;
Утверждение parol:=2004; приведет к ошибке при компиляции, так как тип переменной не
соответствует типу константы.
Переменную типа string можно сравнивать с другой переменной или константой типа string,
используя операторы =, <, >, <=, >=, <>. Строки сравниваются посимвольно от первого символа. Если
все символы сравниваемых строк одинаковые, то такие строки считаются равными. Если в одинаковых
позициях строк находятся разные символы, большей считается та строка, у которой в этой позиции
находится символ с большим кодом. Например: Иванов – 1 строка, Иванов – 2 строка, тогда они равны;
васильев – 1 строка, Васильев – 2 строка, тогда 1 строка больше 2; Алексеев – 1 строка, петров – 2
строка, тогда 1 строка меньше 2; Иванова – 1 строка, Иванов – 2 строка , тогда 1 строка больше 2.
Кроме операций сравнения к строковым переменным и константам можно применить оператор
сложения, в результате выполнения которого получается новая строка, полученная склеиванием двух
или более строк. Например: name:=’Иван’;
fam:=’Иванов’;
fn:= fam +’ ‘+name;
переменная fn получит значение ’Иванов Иван’.
Задачи:
1. Составить программу:
а) которая запрашивает имя человека и повторяет его на экране;
б) которая запрашивает имя человека и повторяет его на экране с приветствием;
в) которая запрашивает название футбольной команды и повторяет его на экране со
словами: "Это чемпион!".
2. Дано слово. Получить и вывести на экран буквосочетание, состоящее из его второго и
четвертого символов.
3. Дано слово. Получить и вывести на экран буквосочетание, состоящее из его третьего и
последнего символов.
4. Составить программу, которая запрашивает отдельно имя и отдельно фамилию, а затем
выводит их как одну символьную строку.
5. Дано слово. Вывести на экран его третий символ.
6. Дано слово. Вывести на экран его последний символ.
7. Дано слово. Вывести на экран его k-й символ.
8. Дано слово. Определить, одинаковы ли второй и четвертый символы в нем.
9. Дано слово. Верно ли, что оно начинается и оканчивается на одну и ту же букву?
10. Даны два слова. Верно ли, что первое слово начинается на ту же букву, которой
оканчивается второе слово?
Turbo Pascal предоставляет несколько полезных при работе со строками функций и процедур.
Функция length.
Функция length возвращает длину строки. У функции один параметр – переменная строкового типа.
Возвращаемое значение функции (целое число) – количество символов, из которых состоит строка, без
учета начальных и завершающих пробелов. Например length(’Иванов’) равно 6, а значение length(’
Лекции по Turbo Pascal
47
-
Невский проспект ’) равно 16, так как при вычислении длины строки функция не учитывает
начальные и завершающие пробелы.
Примеры определения длины строки
• k:=length(‘мир’);
k=3
• s:=‘Кот и пес’;
n:= length(s);
n=9
• s1=‘’;
i:= length(s1);
i=0
‘’ - пустая строка!
Задачи:
1. Дано название футбольного клуба. Определить количество символов в нем.
2. Дано название города. Определить четно или нет количество символов в нем.
3. Даны две фамилии. Определить какая из них длиннее.
Функция copy.
Функция copy позволяет выделить фрагмент строки. В общем виде обращение к функции copy
выглядит так: (строка, p, n);
где строка – переменная строкового типа, содержащая строку, фрагмент которой надо получить; p –
номер первого символа в строке строка, с которого начинается выделяемая подстрока; n – длина
выделяемой подстроки. Например, в результате выполнения команд:
s:= ‘Инженер Иванов’;
fam:= copy (s, 9, 6);
значением переменной fam будет строка ‘Иванов’.
Примеры выделения символов
• s:=‘информатика’;
s1:=copy (s, 3, 5);
s1=‘форма’
s2:=copy (s, 8, 2)+ copy (s, 3, 1);
s2=‘тиф’
Задачи:
1. Дано слово. Получить его часть, образованную второй, третьей и четвертыми буквами.
2. Дано слово, состоящее из четного числа букв. Вывести на экран его первую половину, не
используя оператор цикла.
3. Дано слово. Получить его часть, образованную идущими подряд буквами, начиная с m-й и
кончая n-й.
4. Из слова "яблоко" путем вырезок его букв получить слова "блок" и "око".
5. Из слова "информатика" путем вырезок его букв получить слова "форма" и "тик".
Процедура insert.
Процедура insert позволяет добавить часть строки в исходную строку. В общем виде обращение к
процедуре выглядит так: Insert ( подстрока, строка, p);
где подстрока – строковая константа или переменная, которую необходимо добавить в строковую
переменную строка; p – номер первого символа в строке строка, с которого начинается добавление
подстроки.
Примеры вставки символов
• s:=‘мама’;
insert (‘очк’, s, 4);
s=‘мамочка’
• s1:=‘рог’;
s2:=‘по’;
insert (s1, s2, 3);
s2=‘порог’
Задачи:
1. Дано слово. Вставить букву "т" после k-й буквы.
2. Дано слово. Вставить заданную букву после первой буквы "и".
3. Дано слово. Переставить его первую букву на место последней. При этом вторую, третью, ...,
последнюю буквы сдвинуть влево на одну позицию.
Процедура delete.
Процедура delete позволяет удалить часть строки. В общем виде обращение к процедуре выглядит
Лекции по Turbo Pascal
48
-
так: delete (Строка, p, n);
где строка – переменная строкового типа; p – номер символа, с которого начинается удаляемая
подстрока; n – длина удаляемой подстроки.
Например, в результате выполнения команд:
s:= ‘Город Санкт-Петербург’;
delete (s, 7, 6);
значение переменной s будет строка ‘Город Петербург’.
Примеры удаления символов
• s:=‘котик’;
delete (s, 4, 2);
s=‘кот’
• s:=‘информатика’;
delete (s, 1, 2);
delete (s, 6, 4);
s=‘форма’
Задачи:
1. Дано слово:
а) удалить из него третью букву;
б) удалить из него k-ю букву.
2. Дано слово:
а) Удалить из него первую из букв "о", если такая буква есть.
б) Удалить из него последнюю из букв "т", если такая буква есть.
3. Дано слово. Если его длина нечетная, то удалить среднюю букву, в противном случае - две
средних буквы.
4. Дано предложение. Удалить из него все символы с n1-го по n2-й (n1n2).
5. Дано предложение. Удалить из него все буквы "с".
6. Дано слово. Удалить из него все повторяющиеся буквы, оставив их первые вхождения, то
есть в слове должны остаться только различные буквы.
7. Дано предложение. Удалить из него все буквы "о", стоящие на нечетных местах.
8.
Функция pos.
Функция pos позволяет определить положение подстроки в строке. В общем виде обращение к
функции выглядит так: pos (Подстрока, строка);
где Подстрока – строковая константа или переменная, которую надо найти в строковой константе
или переменной строка.
Например, в результате выполнения команды: p:= pos (‘Пе’, ‘Санкт-Петербург’); значение
переменной p будет равно 7. Если в строке нет искомой подстроки, то функция возвращает ноль.
Примеры определения позиции
• k:=pos(‘р’, ’мир’);
k=3
• s:=‘колокол’;
n:=pos(‘кол’, s);
n=1
• s1:=‘ок’; s2:=‘кок’;
i:=pos(s1, s2);
i=2
• k:=pos(‘п’, ’мама’);
k=0
Например
var
st: string;
begin
write (‘Введите строку: ’);
readln (st);
while (pos (‘ ‘, st)=1) and (length (st)>0) do
delete (st, 1, 1);
write (‘Строка без начальных пробелов: ’, st);
end.
Данная программа использует функцию pos и процедуру delete для удаления пробелов в начале
введенной с клавиатуры строки. пробелы удаляются в цикле while до тех пор, пока функция pos
Лекции по Turbo Pascal
49
-
обнаруживает пробел в начале строки (значение pos при этом равно единице). Проверка условия length
(st)>0 нужна, так как возможно, что введенная с клавиатуры строка состоит вся из пробелов.
Задачи:
1. Дано предложение, в котором имеется несколько букв "е". Найти:
а) порядковый номер первой из них;
б) порядковый номер последней из них.
2. Дано предложение. Определить, есть ли в нем буква "а". В случае положительного ответа
найти также порядковый номер первой из них.
3. Дано предложение. Определить количество букв "н", предшествующих первой запятой
предложения.
4. Дано предложение. Напечатать все символы, расположенные между первой и второй запятой.
Если второй запятой нет, то должны быть напечатаны все символы, расположенные после
единственной имеющейся запятой.
5. Дано предложение, в котором имеются одна буква "с" и одна буква "т". Определить, какая из
них встречается раньше (при просмотре слова слева направо).
Процедура val.
процедура val позволяет преобразовать изображение числа в число. В общем виде обращение к
процедуре выглядит так: val (Строка, число, код).
где строка – строковая константа или переменная, содержащая изображение числа; число переменная, которой должно быть присвоено значение, изображенное строкой строка; код –
возвращаемый процедурой код ошибки. Если строка может быть преобразована в число, то код ошибки
равен нулю.
Процедура val полезна при организации ввода с клавиатуры. Например, если в программе описана
переменная month типа integer и ее значение вводится с клавиатуры, то в результате возможной ошибки
оператора, задавшего месяц строкой символов, например 'июнь', а не цифрой, программа завершается
ошибкой времени выполнения. Однако если числовые данные вводить как строку, а затем
преобразовывать в число с помощью процедуры val, то можно избежать подобного неприятного
завершения программы. Ниже приведен пример такой программы.
var
month: integer;
st: string[10];
code: integer;
begin
repeat
write (‘Месяц->’);
readln (st);
val (st, month, code);
if code<>0 then
writeln (‘Ошибка! Месяц следует задать цифрой.’);
until code=0;
end.
Задачи:
1. Дан текст. Напечатать все имеющиеся в нем цифры.
2. Дан текст. Определить количество цифр в нем.
3. Дан текст, в котором имеются цифры.
а) Найти их сумму.
б) Найти максимальную цифру.
4. Дан текст, в начале которого имеются пробелы и в котором имеются цифры. Найти
порядковый номер максимальной цифры, считая, что первый номер имеет первый
непробел. Если максимальных цифр несколько, то должен быть найден номер первой из
них.
Процедура str.
Процедура str позволяет преобразовать число в его изображение, т.е. в строку. В общем виде
Лекции по Turbo Pascal
50
-
обращение к процедуре выглядит так: str (выражение, строка).
где выражение – выражение или переменная целого или вещественного типа, строка – строковая
переменная, которой будет присвоено изображение выражения.
Задачи общие:
1. Дано предложение. Определить число букв "о" в нем.
2. Дано предложение. Определить число пробелов в нем.
3. Дано предложение. Определить число вхождений в него некоторого символа.
4. Дано предложение. Определить долю (в %) букв "а" в нем.
5. Дан текст. Сколько раз в нем встречается символ "+" и сколько раз символ "*".
6. Дано предложение. Определить сколько в нем одинаковых соседних букв.
7. Дано предложение. Определить число вхождений в него буквосочетания "ро".
8. Дано предложение. В нем слова разделены одним пробелом (начальные и конечные
пробелы в предложении отсутствуют). Определить количество слов в предложении.
9. Дано предложение. В нем слова разделены одним или несколькими пробелами. Определить
количество слов в предложении.
10. Дан текст. Подсчитать общее число вхождений в него символов "+" и "-".
11. Дано предложение. Определить, сколько в нем гласных букв.
12. Дано предложение. Все буквы "е" в нем заменить на букву "и".
13. Дано предложение. Все его символы, стоящие на четных местах заменить на букву "ы".
14. Дано предложение. Заменить в нем все вхождения буквосочетания "ах" на "ух".
15. Дано предложение. Заменить в нем все вхождения буквосочетания "бит" на "рог".
16. Дана последовательность слов. Проверить, правильно ли в ней записаны сочетания "жи" и
"ши".
17. Дана последовательность слов. Проверить, правильно ли в ней записаны сочетания "ча" и
"ща". Исправить ошибки.
18. Дано слово. Определить, сколько различных букв в нем.
19. Даны два слова. Определить, можно ли из букв первого из них получить второе.
Рассмотреть два варианта:
1) повторяющиеся буквы второго слова могут в первом слове не повторяться;
2) каждая буква второго слова должна входить в первое слово столько же раз,
сколько и во второе.
20. Даны три слова. Напечатать только те буквы слов, которые есть только в одном из слов.
Рассмотреть два варианта:
1) повторяющиеся буквы каждого слова рассматриваются;
2) повторяющиеся буквы каждого слова не рассматриваются.
21. Даны три слова. Напечатать их общие буквы. Повторяющиеся буквы каждого слова не
рассматривать.
22. Даны три слова. Напечатать неповторяющиеся в них буквы.
Массивы из строк.
Работа с массивом из строк аналогична работе с целочисленными массивами. При объявлении
массива тип элементов в нем должен быть типа string.
Задачи:
1. В массиве из строк определить количество строк начинающихся на букву «А» и ввести их
на экран.
2. В массиве найти строки, длина которых равна заданному числу, либо сообщить о их
отсутствии.
3. В массиве найти строки, начинающиеся гласной русской буквой.
4. Отсортировать массив из строк по убыванию их длин.
5. Отсортировать массив из строк по алфавиту.
6. Дано предложение из 10 слов. Заполнить ими массив из 10 элементов.
7. Дано предложение. Напечатать его в обратном порядке слов, например, предложение "мама
мыла раму" должно быть напечатано в виде "раму мыла мама".
8. Даны две строки. определить можно ли вторую строчку получить вычеркиванием символов
Лекции по Turbo Pascal
51
-
первой строки. если можно то указать номера оставшихся символов первой строки.
9. Даны несколько строк текста, в которых нет начальных и конечных пробелов. Необходимо
изменить эти строки так, чтобы их длины были одинаковыми. Это следует сделать путем
вставки между словами дополнительных пробелов. Количество пробелов между
отдельными словами внутри отдельной строки должно отличаться не более чем на 1.
Зачет по строкам.
Системы счисления.
Система счисления это способ наименования и записи чисел. Все они делятся на две большие
группы: позиционные и непозиционные.
В непозиционной системе счисления каждый знак, употребляемый для записи чисел, всегда
обозначает одно и то же число. Цифра – это знак, используемый для изображения числа.
Примером непозиционной системы счисления может служить римская. В ней были определены
следующие обозначения чисел: I – 1, V – 5, X – 10, L – 50, C – 100, D – 500, M – 1000.
Тогда число 378 в римской нумерологии будет выглядеть так: CCCLXXVII.
Славянская система счисления тоже являлась непозиционной, в ней использовались буквы алфавита,
над которыми ставился специальный значок ~ - называемый титло.
Запись чисел в этих системах очень громоздко и не удобно, так как требует использования большого
числа знаков, требуемых для записи какого - либо числа. Чтобы несколько уменьшить количество
используемых знаков для записи чисел, в римской системе было введено следующее правило: Если
поместить букву обозначающую меньшее число, слева от буквы обозначающей большее, то меньшее
следует из большего вычитать. IV – 4, IX – 9, XL – 40, XC – 90.
С помощью всех введенных знаков тысячу изобразить легко, но трудно изобразить сто тысяч.
Ясно, что сколько не вводить новых знаков, всегда можно придумать число, которое трудно
изобразить уже введенными знаками. Такое затруднение характерно для любой непозиционной системы
счисления. Также очень сложны и неудобны в этих системах счисления арифметические действия.
CCCLIX+CLXXIV=DXXXIII. Еще труднее производить умножение. Поэтому должно быть понятно,
почему были вытеснены такие системы счисления из обихода позиционными. Хотя надо отметить, что
именно римская система используется до сих пор, только в тех случаях, где нет необходимости
производить с числами какие – либо действия. Например, при обозначении столетий, глав в книгах,
часов на циферблатах.
Общепринятой позиционной системой счисления является десятичная, берущая свое начало от счета
на пальцах. Она была изобретена в Индии, затем заимствована там арабами и уже через арабские
страны пришла в Европу. Значение каждой цифры в позиционной системе счисления определяется не
только ею самой, но так же и местом (позицией), которое она занимает в записи числа. Для
позиционной системы счисления так же характерно то, что число разбивается на разряды, которые
считаются справа налево и каждая цифра в записи числа означает определенное количество единиц
именно того разряда в котором эта цифра стоит (568 – 5 сотен, 6 десятков, 8 единиц). Единица каждого
следующего разряда всегда в определенное количество раз превосходить единицу предыдущего. Это
отношение называют основанием системы счисления.
Числа, которыми мы привыкли пользоваться называются десятичными и арифметика, которой мы
пользуемся, также называется десятичной. Это потому, что каждое число можно составить из набора
цифр содержащего 10 символов - цифр - "0123456789". Но десятичная арифметика не единственная.
Если мы возьмём только пять цифр, то на их основе можно построить пятеричную арифметику, из семи
цифр - семеричную. В областях знаний связанных с компьютерной техникой часто используют
арифметику, в которой числа составляются из шестнадцати цифр, соответственно эта арифметика
называется шестнадцатеричной. Чтобы понять, что такое число в не десятичной арифметике сначала
выясним, что такое число в десятичной арифметике.
Возьмём, к примеру, число 246. Эта запись означает, что в числе две сотни, четыре десятка и
шесть единиц. Следовательно, можно записать следующее равенство:
246 = 200 + 40 + 6 = 2 * 102 + 4 * 101 + 6 * 100
Здесь знаками равенства отделены три способа записи одного и того же числа. Наиболее
интересна нам сейчас третья форма записи: 2 * 102 + 4 * 101 + 6 * 100 . Она устроена следующим
образом:
Лекции по Turbo Pascal
52
-
В нашем числе три цифры. Старшая цифра "2" имеет номер 3. Так вот она умножается на 10 во
второй степени. Следующая цифра "4" имеет порядковый номер 2 и умножается на 10 в первой. Уже
видно, что цифры умножаются на десять в степени на единицу меньше порядкового номера цифры.
Уяснив сказанное, мы можем записать общую формулу представления десятичного числа. Пусть дано
число, в котором N цифр. Будем обозначать i-ю цифру через ai. Тогда число можно записать в
следующем виде: anan-1….a2a1. Это первая форма, а третья форма записи будет выглядеть так:
anan-1….a2a1 = an * 10n-1 + an-1 * 10n-2 + …. + a2 * 101 + a1 * 100
где ai это символ из набора "0123456789"
В этой записи очень хорошо видна роль десятки. Десятка является основой образования числа. И
кстати она так и называется "основание системы счисления", а сама система счисления, поэтому так и
называется "десятичной". Конечно, никакими особыми свойствами число десять не обладает. Мы
вполне можем заменить десять на любое другое число. Например, число в пятеричной системе
счисления можно записать так:
anan-1….a2a1 = an * 5n-1 + an-1 * 5n-2 + …. + a2 * 51 + a1 * 50
где ai это символ из набора "012345"
В общем, заменяем 10 на любое другое число и получаем совершенно другую систему счисления
и другую арифметику. Наиболее простая арифметика получается, если 10 заменить на 2. Полученная
система счисления называется двоичной и число в ней определяется следующим образом:
anan-1….a2a1 = an * 2n-1 + an-1 * 2n-2 + …. + a2 * 21 + a1 * 20
где ai это символ из набора "01"
Эта система самая простая из всех возможных, так как в ней любое число образуется только из
двух цифр 0 и 1. Понятно, что проще уже некуда. Примеры двоичных чисел: 10, 111, 101.
Очень важный вопрос. Можно ли, например двоичное число (или число из какой-нибудь другой
системы счисления) представить в виде десятичного числа и наоборот, можно ли десятичное число
представить в виде двоичного (или числа из какой-нибудь другой системы счисления).
Двоичное в десятичное. Это очень просто. Метод такого перевода даёт наш способ записи чисел.
Возьмём, к примеру, следующее двоичное число 1011. Разложим его по степеням двойки. Получим
следующее:
1001 = 1 * 23 + 0 * 22 + 0 * 21 + 1 * 20
Выполним все записанные действия и получим:
1 * 23 + 0 * 22 + 0 * 21 + 1 * 20 = 8 + 0+ 0 + 1 = 9. Таким образом, получаем, что 1011(двоичное) = 9
(десятичное). Сразу видно и небольшое неудобство двоичной системы. То же самое число, которое, в
десятичной системе записано одним знаком в двоичной системе, для своей записи требует четыре знака.
Но это плата за простоту (бесплатно ничего не бывает). Но выигрыш двоичная система даёт огромный в
арифметических действиях. И далее мы это увидим.
В свое время в Древнем Вавилоне использовалась шестидесятеричная система счисления, ее
отголоски находят у нас применение в переводе часов в минуты, минут в градусы и т.д.
При использовании системы счисления выше десятичной в обиход идут буквы, то есть, например,
для шестнадцатеричной системы счисления будут использованы следующие цифры: 0, 1, 2, 3, 4, 5, 6, 7,
8, 9, a, b, c, d, e, f.
Представьте в виде десятичного числа следующие числа.
а) 1101000112 (419);
б) 34106(798);
с) d7e816(55272);
в) 522456(7013);
г) 17688(1012);
д) 10100039270);
е) 2a01b12(58775).
Самостоятельная работа на перевод чисел в десятичную систему счисления.
Для того, чтобы преобразовать десятичное число в двоичное, его нужно разложить по степеням
двойки. Но если разложение по степеням десятки получается сразу, то, как разложить по степеням
двойки надо немного подумать. Для начала рассмотрим, как это сделать методом подбора. Возьмём
десятичное число 12.
Шаг первый. 22 = 4, этого мало. Также мало и 23 = 8, а 24=16 это уже много. Поэтому оставим 23
=8. 12 - 8 = 4. Теперь нужно представить в виде степени двойки 4.
Шаг второй. 4 = 22.
Тогда наше число 12 = 23 + 22. Старшая цифра имеет номер 4, старшая степень = 3, следовательно,
должны быть слагаемые со степенями двойки 1 и 0. Но они нам не нужны, поэтому чтобы избавится от
Лекции по Turbo Pascal
53
-
ненужных степеней, и оставить нужные запишем число так: 1*23 + 1*22 +0*21 + 0*20 = 1100 - это и есть
двоичное представление числа 12. Нетрудно заметить, что каждая очередная степень - это наибольшая
степень двойки, которая меньше разлагаемого числа.
Для перевода целого десятичного числа N в систему счисления с основанием q необходимо N
разделить с остатком ("нацело") на q , записанное в той же десятичной системе. Затем неполное
частное, полученное от такого деления, нужно снова разделить с остатком на q , и т.д., пока последнее
полученное неполное частное не станет равным нулю. Представлением числа N в новой системе
счисления будет последовательность остатков деления, изображенных одной q-ичной цифрой и
записанных в порядке, обратном порядку их получения.
Пример: Переведем число 75 из десятичной системы в двоичную, восьмеричную и
шестнадцатеричную:
Ответ:
7510
=
1
001
0112
=
1138
=
4B16.
Преобразуйте десятичные числа в двоичные:
а) 14 б) 29 в) 134 г) 158 е) 1190 ж) 2019
Самостоятельная работа на перевод чисел из десятичной системы счисления.
Арифметические действия в системах счисления.
Рассмотрим основные арифметические операции: сложение, вычитание, умножение и деление.
Правила выполнения этих операций в десятичной системе хорошо известны — это сложение,
вычитание, умножение столбиком и деление углом. Эти правила применимы и ко всем другим
позиционным системам счисления. Только таблицами сложения и умножения надо пользоваться
особыми для каждой системы.
Сложение
Таблицы сложения легко составить, используя Правило Счета.
Сложение в двоичной системе
Сложение в восьмеричной системе
Лекции по Turbo Pascal
54
-
Сложение в шестнадцатиричной системе
При сложении цифры суммируются по разрядам, и если при этом возникает избыток, то он
переносится влево.
Пример. Сложим числа 15 и 6 в различных системах счисления.
Шестнадцатеричная: F16+616
Ответ: 15+6 = 2110 = 101012 = 258 = 1516.
Проверка. Преобразуем полученные суммы к
десятичному виду:
101012 = 24 + 22 + 20 = 16+4+1=21,
258 = 2 . 81 + 5 . 80 = 16 + 5 = 21,
1516 = 1 . 161 + 5 . 160 = 16+5 = 21.
Умножение
Выполняя умножение многозначных чисел в различных позиционных системах счисления, можно
использовать обычный алгоритм перемножения чисел в столбик, но при этом результаты перемножения
и сложения однозначных чисел необходимо заимствовать из соответствующих рассматриваемой
системе таблиц умножения и сложения.
Умножение в двоичной системе
Умножение в восьмеричной системе
Лекции по Turbo Pascal
55
-
Ввиду чрезвычайной простоты таблицы умножения в двоичной системе, умножение сводится лишь
к сдвигам множимого и сложениям.
Пример. Перемножим числа 5 и 6.
Ответ:
Проверка.
111102
368
.
5
Преобразуем
=
24
=
6
=
полученные
+
23
1
3 8
3010
=
произведения
к
2
+
2
+
+
6 80
111102
=
десятичному
21
=
=
Пример. Перемножим числа 115 и 51.
Ответ: 115 . 51 = 586510 = 10110111010012 = 133518.
Проверка. Преобразуем полученные произведения к десятичному виду:
10110111010012 = 212 + 210 + 29 + 27 + 26 + 25 + 23 + 20 = 5865;
133518 = 1 . 84 + 3 . 83 + 3 . 82 + 5 . 81 + 1 . 80 = 5865.
Самостоятельная работа на сложение и умножение чисел в различных системах счисления.
Вычитание
Пример. Вычтем единицу из чисел 102, 108 и 1016
Пример. Вычтем единицу из чисел 1002, 1008 и 10016.
Лекции по Turbo Pascal
368.
виду:
30;
30.
56
-
Деление
Деление в любой позиционной системе счисления производится по тем же правилам, как и деление
углом в десятичной системе. В двоичной системе деление выполняется особенно просто, ведь
очередная цифра частного может быть только нулем или единицей.
Пример. Разделим число 30 на число 6.
Ответ: 30 : 6 = 510 = 1012 = 58.
Пример. Разделим число 5865 на число 115.
Восьмеричная: 133518 :1638
Ответ:
Проверка.
1100112 =
5865
:
Преобразуем
25 + 2 4 +
115
=
полученные
2 1 + 20 =
Пример. Разделим число 35 на число 14.
Восьмеричная: 438 : 168
Лекции по Turbo Pascal
5110
=
частные
к
51; 638 = 6 .
1100112
=
десятичному
81 + 3 . 80
638.
виду:
= 51.
57
-
Ответ: 35 : 14 = 2,510 = 10,12 = 2,48.
Проверка. Преобразуем полученные частные к десятичному виду:
10,12 = 21 + 2 -1 = 2,5;
2,48 = 2 . 80 + 4 . 8-1 = 2,5.
Перевод из двоичной системы счисления в четверичную, восьмеричную,
шестнадцатеричную и обратно.
Двоичная система, удобная для компьютеров (потому, что она имеет ряд преимуществ перед
другими системами: для ее реализации нужны технические устройства с двумя устойчивыми
состояниями (есть ток — нет тока, намагничен — не намагничен и т.п.), а не, например, с десятью, —
как в десятичной; представление информации посредством только двух состояний надежно и
помехоустойчиво; возможно применение аппарата булевой алгебры для выполнения логических
преобразований информации; двоичная арифметика намного проще десятичной. Недостаток двоичной
системы — быстрый рост числа разрядов, необходимых для записи чисел), для человека неудобна изза ее громоздкости и непривычной записи.
Перевод чисел из десятичной системы в двоичную и наоборот выполняет машина. Однако, чтобы
профессионально использовать компьютер, следует научиться понимать слово машины. Для этого и
разработаны восьмеричная и шестнадцатеричная системы.
Числа в этих системах читаются почти так же легко, как десятичные, требуют соответственно в три
(восьмеричная) и в четыре (шестнадцатеричная) раза меньше разрядов, чем в двоичной системе (ведь
числа 8 и 16 — соответственно, третья и четвертая степени числа 2).
Перевод восьмеричных и шестнадцатеричных чисел в двоичную систему очень прост: достаточно
каждую цифру заменить эквивалентной ей двоичной триадой (тройкой цифр) или тетрадой (четверкой
цифр).
Например:
Чтобы перевести число из двоичной системы в восьмеричную или шестнадцатеричную, его нужно
разбить влево и вправо от запятой на триады (для восьмеричной) или тетрады (для
шестнадцатеричной) и каждую такую группу заменить соответствующей восьмеричной
(шестнадцатеричной) цифрой.
С
Сводная таблица переводов целых чисел из одной системы счисления в другую.
Рассмотрим только те системы счисления, которые применяются в компьютерах — десятичную,
двоичную, восьмеричную и шестнадцатеричную. Для определенности возьмем произвольное
десятичное число, например 46, и для него выполним все возможные последовательные переводы из
одной системы счисления в другую. Порядок переводов определим в соответствии с рисунком:
Лекции по Turbo Pascal
58
-
На этом рисунке использованы следующие обозначения:
 в кружках записаны основания систем счисления;
 стрелки указывают направление перевода;
 номер рядом со стрелкой означает порядковый номер соответствующего примера в сводной
таблице.
Например:
означает перевод из двоичной системы в шестнадцатеричную, имеющий в
таблице порядковый номер 6.
Лекции по Turbo Pascal
59
-
Контрольная работа по системам счисления.
Задание: Написать программу позволяющую перевести число из любой системы счисления, в
любую другую. Для хорошо успевающих учеников вплоть до шестнадцатеричной системы и
позволяющей вводить число, содержащее до 200 символов.
Графический режим работы.
Помимо модуля CRT, который позволяет улучшать вывод на экран. Но как уже говорилось это не
единственная библиотека, сегодня мы начнем знакомиться с новой библиотекой, которая позволяет
работать с графическим режимом дисплея. В этом режиме любое изображение на экране синтезируется
на множество мельчайших элементов, называемых пикселями. Каждый пиксель представляет собой
светящуюся точку таких размеров, при которых промежутки между соседними пикселями отсутствуют.
Если группа смежных пикселей светятся, то они воспринимаются не как совокупность отдельных точек,
а как сплошной участок. Таким образом, на экране дисплея может быть синтезировано любое
графическое изображение.
В графическом режиме экран разделяется прямоугольной сеткой, каждый элемент которой имеет
свои координаты. Левый верхний угол экрана имеет координаты (0;0). Значение левой координаты (Х)
увеличивается в горизонтальном направлении слева направо. Значение правой координаты (У)
увеличивается в вертикальном направлении сверху вниз.
Графическому режиму как и текстовому, присуще понятие текущего указателя. Текущий указатель в
любой момент времени может находится в любой точке экрана с координатами (х;у). Его
местонахождение отображается курсором, но в графическом режиме курсор не виден.
Лекции по Turbo Pascal
60
-
Инициализация (включение) графического режима
InitGraph (gd, gm, p);
где gd – переменная типа integer, которая указывает на используемый тип графического драйвера;
gm – переменная типа integer устанавливающая разрешение экрана; p – строковая константа,
указывающая путь к драйверу.
Драйвер – это программа обеспечивающая работу отдельного устройства, в данном случае
графического адаптера, который в свою очередь позволяет реализовать графический режим.
В нашем случае gd=9 всегда.
Что касается разрешения то возможны такие варианты значений которые принимает переменная gm:
gm=0 - низкое (640x200)
gm=1 - среднее (640x350)
gm=2 - высокое (640x480)
Ну а путь к драйверу на наших машинах выглядит следующим образом: ‘c:\trans\bp\bgi’
Выключение графического режима
CIoseGraph;
Изображение точек
PutPixel (x, y, c);
где х и у – координаты точки, а с – это цвет которым будет изображена точка (номера цветов
аналогичны номерам цветам в модуле crt).
Пример: Нарисовать точку зеленого цвета в центре экрана
Program Primer;
Uses Graph;
Var Gd, Gm : Integer;
Begin
Gd:=9; Gm:=2;
InitGraph(Gd,Gm,’c:\trans\bp\bgi’);
PutPixel(320,240,2);
Readln;
CloseGraph;
End.
Задание:
1. Изобразить точку в центре экрана при низком разрешении экрана.
2. Изобразить на экране звездное небо.
3. Изобразить на экране разноцветное звездное небо.
4. Изобразить звездное небо на четверти экрана.
5. Изобразить звездное небо в центре экрана.
Изображение линий.
Цвет линии
SetColor (c);
где с – цвет которым будет изображена линия или текст.
Стиль линии
SetLineStyle (s, p, t);
где s – стиль лини; p – шаблон линии; t – толщина линии.
Переменная s может принимать следующие значения:
0
1
2
3
4
Определяется шаблоном
Лекции по Turbo Pascal
61
-
Переменная t принимает следующие значения:
1 - Тонкая
3 - Толстая
Переменная p может иметь любое значение если стиль линии не шаблон (т.е. если s<>4).
Отрезок прямой линии
Line (x1,y1, x2,y2);
где x1,y1- начальные координаты прямой линии; x2,y2 – координаты конца линии.
Отрезок до точки
LineTo (x,y);
где линия рисуется от точки в который находится указатель в данный момент; х, у – координаты
указателя после выполнения команды, т.е. линия рисуется до точки с координатами х, у.
Данную команду удобно использовать при рисовании ломанных линий.
Перемещение текущего указателя в точку с координатами (x,y)
MoveTo (x,y);
Отрезок (вектор)
LineRel (dx, dy);
где линия рисуется от точки в который находится указатель в данный момент; а конечные
координаты отрезка формируются следующим образом: к текущим координатам х и у прибавляются
соответственно dx и dy.
Задания:
1. Построить желтый треугольник, вершинами которого являются следующие точки (200;100),
(300;100), (250; 10).
2. Нарисовать домик.
3. Нарисовать лесенку, если с клавиатуры задаются следующие параметры: а – ширина
ступеньки, b – высота ступеньки, с – количество ступенек.
4. Нарисовать лесенку если помимо вышеуказанных параметров задается еще начало и
направление лесенки.
Самостоятельная работа: Нарисовать куб. (Оценивается на «5» - если нижняя левая вершина куба,
а также длина его ребра задается с клавиатуры, на «4» - если изобразили отталкиваясь от исходных
данных: вершина имеет координаты (100; 400), длина ребра 200).
Контур прямоугольника
Rectangle(x1,y1,x2,y2);
x1,y1,x2,y2 – координаты противоположных не смежных вершин прямоугольника.
Окружность
Circle (x, y, r);
где x, y – координата центра окружности, а r – радиус окружности.
Дуга окружности
Arc (x,y,nu,ku,r);
где x,y – координаты центра окружности, r – радиус окружности, nu – начальный угол с которого
начинается рисование дуги, ku – конечный угол, переменные nu,ku – измеряются в градусах.
Дуга эллипса
Ellipse(x,y,nu,ku,rx,ry);
где x,y – координаты центра эллипса, rx,ry – радиусы эллипса соответственно по оси х и по оси у, nu
– начальный угол с которого начинается рисование дуги, ku – конечный угол, переменные nu,ku –
измеряются в градусах.
Например для того чтобы нарисовать полный эллипс необходимо выполнить такую команду:
Ellipse(x,y,0,360,rx,ry);
Задание: Изобразить на экране какую–нибудь смешную рожицу.
Закрашенные фигуры
Стиль заполнения фигуры
SetFillStyle (s, c);
где s – стиль заполнения фигуры, c – номер активного цвета.
Лекции по Turbo Pascal
62
-
Виды стилей заполнения:
0 - сплошная закраска фоновым цветом
1 - сплошная закраска активным цветом
9 - закраска пикселей в шахматном порядке
12 - пользовательский стиль
2
3
4
5
6
7
8
10
11
Закрашенный прямоугольник
Bar (x1,y1, x2,y2);
x1,y1,x2,y2 – координаты противоположных не смежных вершин прямоугольника.
Параллелепипед
Bar3d(x1,y1,x2,y2,d,t);
x1,y1,x2,y2 – координаты противоположных не смежных вершин передней грани параллелепипеда,
d – ширина боковой грани, t - Верхняя грань(True (TopOn) – есть, False (TopOff) – нет).
Закрашенный эллипс
FillEllipse (x,y,Rx,Ry);
где x,y – координаты центра эллипса, Rx,Ry – радиусы эллипса соответственно по оси х и по оси у.
Закрашенный сектор круга
PieSlice (x,y,nu,ku,r);
где x,y – координаты центра круга, r – радиус круга, nu – начальный угол с которого начинается
рисование сектора круга, ku – конечный угол, переменные nu,ku – измеряются в градусах.
Закрашенный сектор эллипса
Sector(x,y,nu,ku,rx,ry);
где x,y – координаты центра эллипса, rx,ry – радиусы эллипса соответственно по оси х и по оси у, nu
– начальный угол с которого начинается рисование сектора эллипса, ku – конечный угол, переменные
nu,ku – измеряются в градусах.
Закраска произвольной фигуры
FloodFill (x,y, b);
где x,y - координаты внутренней точки; b – номер цвета границы.
Задание на оценку: Разукрасить нарисованную ранее рожицу.
Вывод текста в графике
Стиль текста
SetTextStyle(s, d, r)
где s – стиль текста, d – направление, r – размер.
стиль: 0 – побитовый
направление: 0 - горизонтально ()
размер: 1..10
1 – тройной
1 - вертикально ()
2 – малый
3 – гротесковый
4 – готический
Вывод текста
OutTextXY(x, y,s)
где, x, y – координаты, s – текст (тип - string).
Выравнивание текста
SetTextJustify(h, v)
где h - выравнивание по горизонтали, v - выравнивание по вертикали.
Выравнивание текста относительно точки привязки
Текст
h=0
Текст
Текст
Текст
Текст
Текст
h=1
h=2
v=0
v=1
v=2
Лекции по Turbo Pascal
63
-
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Преобразование чисел в текст
Str ( x, s )
где x – исходное число, s - строка (текст) - тип - string
Ширина строки - Функция
TextWidth (S)
где S – строка (ширина в пикселях)
Высота строки - Функция
TextHeight(S)
где S – строка (высота в пикселях)
Задание:
1. Заполнить экран квадратами, если сторона квадрата задается с клавиатуры и если полный
квадрат на экране не убирается его выводить не нужно совсем.
2. Нарисовать шахматную доску, если координаты верхнего левого угла и сторона квадрата
задаются с клавиатуры.
Самостоятельная работа заполнить экран окружностями, так чтобы не полные окружности на
экран не выводились, если радиус задается с клавиатуры.
Задачи:
1. Нарисовать снеговика так, чтобы в центре каждой окружности стоял его порядковый номер,
они были разноцветными, и радиус каждой последующей окружности на одну четверть
меньше предыдущей, количество окружностей, радиус большей, а также ее центр задавались
с клавиатуры.
2. Нарисовать наклонную шахматную доску.
Самостоятельная работа вложенные окружности, причем если просто вложенные окружности
то оценка четыре, если еще симметричные им то тогда пять.
Зачет по текстовому режиму.
Задачи:
Написать программу, которая сообщает пользователю: «Я умею рисовать отрезок». Запрашивает:
«Введите координаты начала и конца отрезка» и рисует отрезок с соответствующими
координатами.
Построить рисунок лодочки.
Написать программу, которая рисует концентрические окружности.
Нарисуйте радугу, т.е. разноцветные дуги концентрических окружностей опирающихся на
нижнюю границу экрана.
Написать программу, которая запрашивает координаты центра окружности, ее радиус и рисует
закрашенный круг, соответствующий введенным величинам.
Написать программу, которая рисует лучи исходящие из левого нижнего угла экрана.
В верхнем левом углу экрана нарисовать солнышко.
Написать программу, которая рисует произвольную ломанную линию.
Написать программу, рисующую произвольный бегущий отрезок.
Написать программу, которая рисует эллипсы.
Составить программу построения квадрата. На одном из его оснований построить
равносторонний треугольник со сторонами произвольной длины.
Построить ромб со стороной А и острым углом х.
Изобразите на экране движение точки по окружности.
«Нарисуйте» часы и «заставьте их «ходить».
Составить программу построения отрезка штриховой прямой линии, ограниченного точками с
координатами А(X,Y) B(X,Y). Размеры штриха и интервала между штрихами возьмите равными.
Исходные данные: значения координат точек и размер штриха введите с клавиатуры.
Изобразите на экране таяние горящей свечи.
Составить программу рисования спирали.
Составить программу вычерчивания графиков следующих функций:
Лекции по Turbo Pascal
64
-
•
•
•
а) y=sinx б) y=tgx в) y=cosx г) y=ax+b д) y=ex е) y=logx
Нарисуйте горизонтальные(вертикальные) линии длиной L располагая их по всей плоскости
экрана на расстоянии d.
Расчертите на клеточки со стороной a весь экран.
Нарисуйте :
в)
б)
а)
г)
д)
е)
ж)
9 класс.
Организация движения в Turbo Pascal.
Алгоритм организации движения:
1. Задать начальную точку привязки.
2. Нарисовать фигуру относительно этой точки привязки.
3. Сделать задержку.
4. Стереть нарисованную фигуру, то есть нарисовать ее фоновым цветом.
5. Изменить начальные координаты точки привязки.
6. Проверка окончания движения, если движение еще не закончено то выполняем пункт 2.
Пример: На экране прямая по которой движется точка. (от левого края до правого).
Задачи:
1. На экране по прямой двигается точка от левого края до правого и обратно, до тех пор, пока не
будет нажата какая-либо клавиша.
2. Даны две прямые, по которым двигаются две точки с разными скоростями.
Самостоятельная работа дан прямоугольный контур, по которому двигается точка
(координаты противоположных не смежных вершин прямоугольника задаются с
клавиатуры).
Задачи:
1. Два мячика двигаются по экрану (один сверху вниз, другой слева направо).
2. Две рожицы двигаются по экрану (одна веселая, другая грустная).
3. Бильярдный шарик двигается по экрану.
4. Броуновское движение.
Управление движением.
Пример: движение шарика только при нажатии стрелок.
Задачи:
1. Шарик двигается, а при нажатии различных клавиш изменяется его направление. скорость,
радиус и т.д.
Лекции по Turbo Pascal
65
-
Движение по окружности.
Подпрограммы.
В практике программирования часто встречаются задачи, в которых по ходу выполнения программы
приходится производить одни и те же действия или вычисления, но при различных исходных данных.
Чтобы исключить повторение одинаковых операторов и сделать тем самым программу проще и
понятнее, можно выделить эти повторяющиеся действия в самостоятельную часть программы, которая
может быть использована многократно по мере необходимости.
Автономная часть программы, реализующая определенный алгоритм и допускающая обращение к
ней из различных частей общей программы, называется подпрограммой.
Подпрограммы оформляются в виде замкнутых участков программы, имеющих четко обозначенные
вход и выход.
Обращение к подпрограмме осуществляется из основной программы через заголовок
подпрограммы. При вызове подпрограммы работа основной программы приостанавливается, и начинает
выполняться вызванная подпрограмма. Она обрабатывает данные, переданные ей из основной
программы, или просто выполняет заданную последовательность действий. По завершении выполнения
подпрограммы основная программа продолжает выполнятся с того места, где прервалось ее действие.
Передача данных из основной программы в подпрограмму (входные данные) и возврат результата
выполнения подпрограммы осуществляется с помощью параметров.
Параметры - это данные, которые передаются вызываемой подпрограмме и используются последней
в качестве входной и (или) выходной информации.
Использование подпрограмм позволяет реализовать один из самых прогрессивных методов
программирования - структурное программирование.
Процедура в Паскале
и ее формат.
Любая программа может содержать несколько процедур и функций. Процедуры и функции
объявляются в разделе описания вслед за пределом описания переменных.
Процедура - это независимая часть программы, которую можно вызывать по имени для выполнения
определенных действий.
Структура процедуры имеет вид :
Procedure имя(список формальных параметров);
(* раздел описаний *)
begin
(* раздел операторов *)
end;
Первая строка описания называется заголовком процедуры, а раздел операторов называется телом
процедуры.
В заголовке указывается служебное слово PROCEDURE, за которым следуют имя процедуры и
список формальных параметров, заключенные в круглые скобки (если такие имеются). В списке
перечисляются имена формальных параметров и их тип. Имя параметра отделяется от типа двоеточием,
а параметры друг от друга - точкой с запятой. Если несколько формальных параметров имеют
одинаковый тип, тогда их можно перечислить через запятую, а затем указать тип.
Тело процедуры заключается в операторные скобки BEGIN и END, причем после END ставится
точка с запятой.
Раздел описаний процедуры подобен программе и состоит из разделов меток, констант, типов,
переменных и , в свою очередь, процедур и функций.
Процедура вызывается по ее имени :
имя(список фактических параметров);
Формальные параметры - параметры, определенные в заголовке процедуры.
Фактические параметры - выражения, задающие конкретные значения при обращении к процедуре.
При обращении к процедуре ее формальные параметры замещаются фактическими, переданными из
основной программы.
Фактические параметры - это параметры, которые передаются процедуре при ее вызове.
Лекции по Turbo Pascal
66
-
Количество и тип формальных и фактических параметров должны в точности совпадать.
Формальные параметры описываются в заголовке процедуры и определяют тип и место подстановки
фактических параметров. Формальные параметры делятся на два вида: параметры-переменные и
параметры-значения.
Параметры-переменные отличаются тем, что передними стоит служебное слово Var. Они
используются тогда, когда необходимо, чтобы изменения значений формальных параметров в теле
процедуры приводили к изменению соответствующих фактических параметров.
Параметры-значения отличаются тем, что перед ними слово Var не ставится. Внутри процедуры
можно производить любые действия с параметрами-значениями, но все изменения никак не отражаются
на значениях соответствующих фактических параметров, то есть какими они были до вызова
процедуры, такими же и останутся после завершения ее работы.
Все переменные программы делятся на глобальные и локальные. Глобальные переменные
объявляются в разделе описаний основной программы. Локальные переменные объявляются в
процедурах и функциях. Таким образом, локальные переменные «живут» только во время работы
подпрограммы.
Пример. Составить программу для вычисления аn : целые числа а и n (n>=0) вводятся с клавиатуры.
( составить процедуру для вычисления степени целого числа).
Program ex;
var a, n : integer;
s: longint;
Procedure Degree(x,y : integer; var st : longint);
var i : integer;
begin
st:=1;
for i:=1 to y do st:=st*x;
end;
{ начало основной программы}
begin
writeln(‘введите два числа - основание и показатель степени’);
readln(a,n);
Degree(a,n,s); { обращение к процедуре }
writeln(‘Результат ’,s);
end.
Процедура названа именем Degree. В скобках записан список формальных параметров, то есть
перечислены переменные с указанием их типа. Используем три параметра: первый - основание степени,
то есть число, которое надо возвести в степень; второй - показатель степени, третий - результат. Первые
два формальных параметра - параметры значения, третий - параметр-переменная, и перед ним указано
слово var. Все они описаны как целые (x и y - переменные типа integer, st - Longint, так как степенная
функция быстро возрастает).
После заголовка процедуры идут разделы описаний. В нашем примере имеется только раздел
описания переменных, в котором описывается одна переменная i (счетчик цикла).
Далее идет тело процедуры. Оно начинается служебным словом Begin и заканчивается служебным
словом End, после которого стоит точка с запятой (в конце программы после последнего End ставится
точка). В теле процедуры вычисляется степень числа x с помощью цикла For.
В программе процедуры и функции описываются после раздела описания переменных программы,
но до начала ее основной части, то есть до Begin , начинающего эту часть программы.
!!!! Процедура вызывается как оператор, состоящий из имени процедуры. В круглых скобках
записываются фактические параметры. В нашем примере формальные параметры x, y и st принимают
значения фактических параметров a, n и s соответственно. После завершения работы процедуры
переменные a и n сохранят те же значения, что и при вызове, а s получит новое значение.
Пример 2 : Используя процедуру для вычисления степени числа, найти значение выражения : y=a4x4
+ a3x3 + a2x2 + a1x + a0
program ex2;
Лекции по Turbo Pascal
67
-
var a: array[0..4] of integer;
i, x: integer;
y,s: longint;
Procedure Degree(xx,n : integer; var st : longint);
var i : integer;
begin
st:=1;
for i:=1 to n do st:=st*xx;
end;
{ начало основной программы}
begin
write(‘введите значение переменной х ‘); readln(x);
writeln(‘введите массив коэффициентов’);
for i:=0 to 4 do begin write(‘a[‘,i,’]=’); readln(a[i]); end;
y:=a[0];
for i:=1 to 4 do
begin
Degree(x,i,s); y:=y+a[i]*s;
end;
writeln(‘y=’,y);
end.
Пример 3. Просуммировать различные части массива.
Program sumir;
var a: array [1..100] of integer; sa1, sa2,sa3 : integer;
n,l,t : integer;
procedure summa(a:array [1..100] of integer; k,m :integer; var s:integer);
var i:integer;
begin
s:=0;
for i:=k to m do s:=s+a[i];
end;
BEGIN
for t:=1 to 100 do
begin
write(‘введите очередной элемент массива ‘);
readln(a[i]);
end;
summa(a,10,20,sa1);
summa(a, n , l , sa2);
summa(a, n,n+3,sa3);
end.
Задачи:
10.17 Составить программу, в результате которой величина А меняется значением с величиной В, а
величина С - с величиной D. (Определить процедуру, осуществляющую обмен значениями двух
переменных величин)
10.18 Даны стороны двух треугольников. Найти сумму их периметров и сумму их площадей.
(Определить процедуру для расчета периметра и площади треугольника по его сторонам.)
10.19 Даны основания и высоты двух равнобедренных трапеций. Найти сумму их периметров и сумму
их площадей (Определить процедуру для расчета периметра и площади равнобедренной трапеции
по ее основаниям и высоте)
10.20 Написать рекурсивную процедуру для вывода на экран цифр натурального числа в обратном
порядке.
Лекции по Turbo Pascal
68
-
Написать рекурсивную процедуру для ввода с клавиатуры последовательности чисел и вывода ее
на экран в обратном порядке (окончание последовательности - при вводе нуля).
10.22 Написать рекурсивную процедуру перевода натурального числа из десятичной системы счисления
в двоичную.
10.21
Функции
Заголовок функции состоит из слова Function, за которым указывается имя функции, затем в круглых
скобках записывается список формальных параметров, далее ставится двоеточие и указывается тип
результата функции.
В теле функции обязательно должен быть хотя бы один оператор присваивания, в левой части
которого стоит имя функции, а в правой - ее значение. Иначе значение функции не будет определено.
Таким образом, общий вид описания функции следующий :
Function Имя[(список формальных параметров)]:Тип результата
описательная часть
Begin
тело функции, в которой обязательно должно быть
присваивание Имя_функции:=значение
End;
Пример 1 Составить программу, подсчитывающую число сочетаний без повторения из n элементов
n!
Сk 
n k!(n  k )!
по k. Число сочетания без повторения вычисляется по формуле
Обозначим через n и k переменные для хранения введенных чисел; С - переменную для хранения
результата.
Воспользуемся функцией для вычисления факториала числа n. (n!=1*2*..*n)
program sochet;
var n,k : integer;
a1,a2,a3,c : lohgint;
Function factorial(n:integer):longint;
var i: integer;
rez : longint;
begin
rez:=1;
for i:=1 to n do rez:=rez*i;
factorial:=rez;
end;
begin
writeln(‘ ввод n и k :’); readln(n,k);
a1:=factorial(n); { вычисление n!}
a2:=factorial(k); { вычисление k!}
a3:=factorial(n-k); {вычисление (n-k)!}
c:=a1 div (a2*a3); { результат}
writeln(‘результат=’,c) ;
end.
Первая строка в описании функции - это ее заголовок. Служебное слово Function (функция)
указывает на то, что именем factorial названа функция. В скобках записан список формальных
параметров функции, состоящий из одной переменной целого типа. Далее в заголовке указан тип
значения функции. В данном примере результат функции factorial - длинное целое число.
За заголовком функции следует описательная часть функции, которая, как у программы, может
состоять из разделов описания переменных, констант, типов. В данном примере есть переменные i
(счетчик цикла) rez (для накопления значения факториала).
Далее идет раздел операторов (тело функции).
Лекции по Turbo Pascal
69
-
В тексте программы описания функций всегда следуют за разделом описания переменных и до
начала основной части, как и описания процедур.
Пусть n=5, k=3. Когда в программе встречается оператор a1:=factorial(n), выполняются следующие
действия:
 выделяется память для переменных, описанных в функции factorial;
 формальному параметру присваивается значение фактического: n:=n (n=5);
 выполняется функция, вычисляется факториал числа 5;
 значение функции передается в место обращения к этой функции, то есть присваивается
переменной a1;
 в операторах a2:=factorial(k) a3:=factorial(n-k) еще дважды вызывается функция factorial с
параметрами k=3 n-k=2.
Функция - это самостоятельная часть программы, имеющая собственные переменные, которым
отводится отдельное место в памяти ЭВМ. Этим объясняется тот факт, что переменные с одинаковыми
именами, используемые в функции и в основной программе, являются разными ( переменная n
основной программы и параметр n функции). При выполнении программы машина «не путает» имена
этих переменных, т.к. области их действия не совпадают.
Пример 2 : Написать функцию, подсчитывающую количество цифр натурального числа. Используя
ее, определить, в каком из двух данных чисел больше цифр.
Program chisla;
Var n1, n2 : longint;
k1, k2 : byte;
Function kol(x : longint): byte;
var k: byte;
begin
k:=0;
While x<>0 do
begin
Inc(k);
x:=x div 10;
end;
kol:=k;
end;
BEGIN
writeln(‘Введите два числа’); readln(n1, n2);
k1:=kol(n1);
k2:=kol(n2);
if k1=k2 Then writeln(‘одинаковое количество цифр’)
else if k1>k2 Then Writeln(‘в первом числе цифр больше’)
else writeln(‘во втором числе цифр больше’)
END.
Задачи:
10.1 Рассчитать значение х, определив и использовав функцию :
а) х 
б) х 
в) х 
6 6
13  13
21  21


2
2
2
г) х 
2  sin 2 6  sin 6 1  sin 1


sin 5  5 sin 3  3 sin 4  4
8  15
д) х 
1  sin 4 7  sin 5 3  sin 2


sin 1  4 sin 7  5 sin 3  2
е) х 
2  log 2 6  log 6 1  log 1


log 5  5 log 3  3 log 4  4
8  15
7  13
7  13


12  6
12  16
12  15
12  15
Лекции по Turbo Pascal


21  7
21  7
21  32
21  32
70
10.2
10.3
10.4
10.5
10.6
Определить значение
а) z=max(a,2b)*max(2a-b,b)
б) z=min(a,3b)*min(2a-b,b)
где max(x,y), min(x,y) - максимум и минимум из чисел x,y
При решении:1) не использовать функцию max, min.
2) определить и использовать функцию max,min.
Даны основания и высоты двух равнобедренных трапеций. Найти сумму их периметров.
(Определить функцию для расчета периметра равнобедренной трапеции по ее основаниям м
высоте.)
Даны три квадратных уравнения ax2 + bx + c = 0, bx2 + ax + c = 0, cx2 + ax + + b = 0. Сколько из них
имеют вещественные корни ? (Определить функцию, позволяющую распознавать наличие
вещественных корней в квадратном уравнении.)
Найти периметр треугольника, заданного координатами своих вершин. (Определить функцию для
расчета отрезка по координатам его вершин)
Даны вещественные числа a, b, c, d, e, f, g.
Найти площадь пятиугольника,
е
изображенного на рисунке.
g
d
(Определить функцию для расчета
площади треугольника по трем
a
f
сторонам.)
b
с
Даны вещественные числа x1, y1, x2, y2,... x5, y5.Найти площадь пятиугольника (см 10.6) вершины
которого имеют координаты (x1, y1), (x2, y2), ...( x5, y5). (Определить функцию для расчета площади
треугольника по координатам его вершин).
10.8 Даны две последовательности целых чисел : а 1, а2,... а8, и b1, b2, ... b8. Найти количество четных
чисел в первой из них и количество нечетных вол второй. (Определить функцию, позволяющую
распознавать четные числа.)
10.9 Найти значение выражения (2*5! + 3*8!)/(6! + 4!), где n! функция.
10.10 Даны два натуральных числа. Выяснить, в каком из них сумма цифр больше.(сумма цифр функция).
10.11 Даны n различных чисел. Определить максимальное из них. (Определить функцию, находящую
максимум из двух различных чисел.)
10.12 Найти НОД(a,b,c)=НОД(НОД(a,b),c). (где НОД(a,b) - функция.)
10.13 Даны n натуральных чисел. Найти их НОД. (где НОД(a,b) - функция.)
10.14 Написать рекурсивную функцию :
а) вычисления суммы цифр натурального числа;
б) вычисления количества цифр натурального числа.
10.15 Даны первый член и разность арифметической прогрессии. Написать рекурсивную функцию для
нахождения :
а) n-го члена прогрессии;
б) суммы n первых членов прогрессии.
10.16 Даны первый член и знаменатель геометрической прогрессии. Написать рекурсивную функцию
для нахождения :
а) n-го члена прогрессии;
б) суммы n первых членов прогрессии.
10.7
Построение графиков функций и диаграмм.
Для начала работы, немного упростим задачу. А именно, договоримся, что функция задана явно, то
есть все наши функции имеют следующий вид y = f(x). И пока мы будем брать только такие функции
которые не имеют точек разрыва в исследуемой области определения. Грубо говоря, на
рассматриваемой области не должен вычисляться корень из отрицательного числа и не должно
выполняться деление на ноль.
Ниже приведен простейший алгоритм, который должен в принципе работать для задачи построения
графиков:
Для все Х от ЛГ до ПГ делать
Вычислить y=f(x)
Лекции по Turbo Pascal
71
-
Построить точку с координатами (x,y)
Для реальной задачи этот алгоритм работать не будет, по следующим причинам:
1. Он не учитывает, то, как устроена система координат компьютерного монитора. (Начало
координат в левом верхнем углу и y растет вниз).
2. Он не учитывает, что экран монитора имеет ограниченные размеры и если значения
функции будут слишком велики или слишком велика будет область, на которой требуется график,
то значительной части графика мы просто не увидим.
3. Если наоборот значения функции будут малы или область построения будет мала, то мы
увидим все, но получившаяся картинка будет слишком мала по своим размерам.
Попробуем учесть указанные моменты.
Все эти проблемы можно решить одним махом, если функцию нарисовать в том же масштабе, что и
экран монитора. Это очень просто. Пусть, мы желаем просмотреть картинку которая очень мала,
например она может быть нарисована в прямоугольнике который в 1000 раз меньше экрана монитора,
тогда её перед тем как выводить необходимо увеличить в 1000 раз. Если же она наоборот в 1000 раз
больше, то перед выводом её надо в 1000 раз уменьшить.
Выше описано преобразование подобия, но это преобразование ещё не полностью описывает
положение картинки на экране. Мало, чтобы картинка совпадала с экраном монитора размерами, ещё
необходимо, чтобы совпадали координаты.
Но после того как исходная область будет увеличена, она все равно будет находиться за пределами
экрана для отображения. А это означает, что после преобразования подобия необходимо осуществить
ещё параллельный перенос. После преобразования подобия вектор переноса останется прежним, если
преобразование проводить так, чтобы левый нижний угол исходной области остался на месте.
И последнее, что нужно сделать – это учесть особенное расположение начала системы координат на
экране монитора компьютера. Для этого изображение необходимо перевернуть, тогда на экране оно
останется прежним.
Итак, мы изложили все, что необходимо на языке геометрических преобразований, но так как язык
программирования не умеет работать с понятиями геометрии, и ему необходимы алгебраические
выражения, то далее мы рассмотрим каким образом всё вышесказанное записать на языке алгебры.
Введём обозначения:
Left – левая граница исходной области.
Right – правая граница исходной области.
Down – нижняя граница исходной области.
Up – верхняя граница исходной области.
Размеры экрана монитора величина фиксированная. Но для общности примем для них буквенные
обозначения:
Long_x – размер по горизонтали
Long_y – размер по вертикали
x, y – значения до выполнения преобразований
x’, y’ – значения после выполнения преобразований
Тогда преобразование подобия запишется следующим образом:
x’ = x/(Right - Left)*Long_x y’ = y/(Up - Down)*Long_y
Преобразование переноса запишем так:
x’’ = x’ – Left
y’’ = y’ – Down
И наконец преобразование “отображения сверху вниз” запишется так:
x’’’ = x’’
y’’’ = Long_y – y’’
А сейчас объединим все три преобразования в одно:
Преобразование
1) x’ = x/(Right - Left)*Long_x – Left
2) y’ = Long_y - (y/(Up - Down)*Long_y – Down)
Так как точек которые должны быть прорисованы достаточно много, необходимо выполнить цикл
обработки для все точек функции. Этот цикл будет выглядеть следующим образом:
Для все точек функции выполнить
Берём очередную точку
Лекции по Turbo Pascal
72
-
Новая точка = Преобразование над очередной точкой
Теперь осталось выяснить откуда взять все те значения для которых мы вводили обозначения и
которые используются в разработанном нами преобразовании.
Первое. Если взялись строить график, стало быть, нам известна область, на которой мы будем
строить график. Эта область конечна и её границы по координате x и есть величины Left, Right.
Предположим, что мы строим график на этой области по N точкам. Это означает, что в нашем
распоряжении массив координат y для N точек. Наибольшее значение y в этом массиве есть величина
Up и наименьшее значение y есть величина Down.
Тогда Long_x = Right – Left и Long_y = Up – Down.
Из вышесказанного ясно, что перед выполнением преобразования необходимо рассчитать числовые
значения всех требуемых точек функции в заданной области и затем найти максимальные и
минимальные значения игреков. Поэтому программа будет включать в себя следующие блоки:
Ввод границ области построения графика.
Ввод количества точек построения.
Расчёт шага построения.
Расчёт значений координат y
Расчёт максимума и минимума значений y – ков
Выполнение операций преобразования.
Выше появился термин “шаг построения”. Разумно строить точки следующим образом. Пусть самая
левая точка графика – это левая граница области построения. Следующая точка это левая + шаг
построения, то есть небольшое число. И каждая очередная точка это предыдущая + шаг построения.
Если делать так, то координаты х можно не держать в массиве. Каждую координата можно рассчитать
по очевидной формуле:
xi = Left + шаг * i если первую точку считать с номером 0 и
xi = Left + шаг * (i – 1) если первая точка имеет номер 1.
После того, как выполнены все шесть блоков, можно смело пользоваться циклической операцией
построения графика описанной в самом начале данной лекции.
Важное замечание
Необходимо помнить, что экран монитора не квадрат, а прямоугольник, кроме того, исходная
область построения графика то же прямоугольник и совсем не обязательно подобный прямоугольнику
экрана монитора. Это означает, что коэффициент подобия для координат x может оказаться иным, чем
коэффициент подобия для координат y.
Это означает, что преобразованный график, скорее всего, окажется искаженным, с точностью до
подобия или по оси Ox или по оси Oy, но это неизбежная плата за возможность просмотреть весь
график.
Построение графика в окрестности точек разрыва
Проблема построения графика в такой окрестности заключается в том, что ордината функции
изменяется очень быстро на очень маленьком интервале изменения абсциссы, а вы помните, что наш
алгоритм проводит преобразование масштабирования графика функции. Это преобразование в случае
обработки окрестности точки разрыва приведёт к тому, что большая часть графика будет изображена в
очень маленьком масштабе. Математически это будет верно, но получившаяся картинка окажется
совершенно ненаглядной, и построение графика потеряет смысл, так как главная функция графика это
всё же наглядность.
Как с этим бороться. Идея решения данной проблемы такова – необходимо научится определять
точку разрыва, и в её окрестности строить график не проводя вычислений и масштабирования, а
схематично, исходя из общих свойств точки разрыва.
Как и в случае с экстремумами и точками перегиба нам нельзя пользоваться точными
определениями математического анализа, о причинах этого мы уже говорили. Следовательно, первое,
что требуется сделать это дать определение разрыва.
Определить разрыв можно так – точка разрыва это такая точка в окрестности, которой функция
изменяется слишком быстро.
Лекции по Turbo Pascal
73
-
Это очень неточное определение. Здесь два неясных термина. Во-первых, непонятно, что значит
слишком быстро и, во-вторых, какого размера интервал принимается за окрестность точки разрыва.
Однако уже ясно, что под это определение может попасть не только точка разрыва, а и такая точка, в
окрестности которой функция просто имеет большую первую производную, то есть изменяется
действительно быстро, но это наша плата за возможность проведения численного счета. А теперь
займёмся уточнением определения.
Мы будем исходить из того, что в окрестности точки разрыва график строится схематично. Это
означает, что график строится неточно, а, следовательно, если окрестность будет велика, то и в целом
построение графика будет неточным.
Отсюда возникает первая мысль, что размер окрестности должен быть таким, чтобы визуально
окрестность точки разрыва не занимала значительную часть области построения графика. Итак нам
необходимо уметь искать окрестности точек разрыва.
Для начала заметим, что в окрестности точки разрыва график функции удовлетворяет следующим
свойствам:
1. Функция либо неограниченно растёт, либо неограниченно убывает.
2. Скорость её роста увеличивается также неограниченно.
Эти два свойства помогут нам обнаруживать необходимые окрестности с высокой степенью
точности. Введём некоторые обозначения.
Max – верхняя граница значений ординат
Min – нижняя граница значений ординат.
Шаг – шаг изменения абсциссы.
А – начало области построения графика
В – конец области построения графика
Важное замечание. Нам важно не просто найти окрестность, а во-первых, достаточно точно
определить абсциссу точки разрыва, а во-вторых, определить тип разрыва, а их может быть два:
Нестрогое описание процесса расчётов
Для поиска точек разрыва, мы пройдём всю область построения с шагом достаточно маленьким, но
таким который позволит пройти всю область за разумное время. На каждом шаге процесс будет
вычисляться новая абсцисса путем прибавления к предыдущей абсциссе величины шага. Для каждой
вновь посчитанной абсциссы будем вычислять ординату, и если посчитанная ордината окажется за
пределами отрезка [min, max] то будем предполагать, что найдена окрестность точки разрыва, после
чего должен быть запущен процесс проверки этого предположения.
Min – это минимальная из уже посчитанных ординат и max – это максимальная из уже посчитанных
ординат.
Процесс проверки предположения заключается в следующем:

Резко уменьшим шаг движения и сделав ещё некоторое количество шагов
убедимся, что функция продолжает изменятся быстрым темпом в том же направлении. Если
этого не происходит, то, следовательно, это не окрестность точки разрыва.

Продолжаем движение вперёд. Если функция скачком изменит направление
изменения (разрыв первого типа) или скачком измениться значение ординаты (разрыв
второго типа), значит, мы нашли окрестность разрыва.
Лекции по Turbo Pascal
74
-

Будем сжимать окрестность с сохранением её свойств до тех пор, пока она не
станет достаточно маленькой. Её центр и есть точка разрыва.
Строгое описание алгоритма.
Текущая точка = Началу области построения графика
Шаг = Начальное значение шага.
Номер точки разрыва = 0
Минимум = 0
Максимум = 0
Пока текущая точка не достигла конца области построения делать
Начало
Вычислить ординату текущей точки
Если ордината меньше минимума или больше максимума
То
Выполнить функцию поиска разрыва
Если разрыв найден
То
Прибавить к абсциссе текущей точки величину найденной окрестности точки разрыва.
Иначе
Если ордината больше максимума то максимум = ордината
Если ордината меньше минимума то минимум = ордината
Конец
Функция поиска точки разрыва
Шаг = Величина большая текущего шага.
Точка1 = текущая точка
Точка2 = Точка1+Шаг
Если Ордината1 > Ордината2 то Направление = вниз
Если Ордината1< Ордината2 то Направление = вверх
Есди Ордината1 = Ордината2
То результат функции = разрыв не найден, работу прекратить
Повторять
Точка1 = Точка2
Точка2 = Точка1 + Шаг
Если Ордината1 сильно отличается от ординаты2
То Результат функции = разрыв найден
Если Ордината1 > Ордината2 то Направление1 = вниз
Если Ордината1< Ордината2 то Направление1 = вверх
Если Направление1 <> Направление2
То Результат функции = разрыв найден
Конец цикла
Важное примечание
Точка разрыва это объект очень высокой степени сложности. Вряд ли можно построить алгоритм
удовлетворительно работающий для любого случая. Данный алгоритм также необходимо рассматривать
как общую схему, которую возможно придётся модифицировать для конкретных случаев.
Думаю, вы обратили внимание, что некоторые понятие здесь не вполне определены. Например не
ясно что означает фраза “Ордината1 сильно отличается от ординаты2”
Алгоритм построения графика функции:
1. Ввести начало математической системы координат. Масштаб (количество пикселей в
единичном отрезке).
2. Нарисовать оси координат и сделать разметку (это может быть либо сетка, либо просто
насечки на осях). Сделать оцифровку.
3. Построить график. Для этого:
 Перебрать все экранные координаты х (от 0 до 639).
 Перевести каждый х – экранный в х – математический. (хэ=а+хм*m, откуда получаем хм=(
Лекции по Turbo Pascal
75
-
хэ-а)/ m, где (а,в) – координаты точки начала математической системы координат, m –
масштаб).
 Проверить входит ли найденное хм в область определения функции, график которой мы
строим.
 Вычислить ум (ум=f(хм)).
 Перевести ум в уэ (уэ=round(b- ум)).
 Изобразить точку с координатами (хэ, уэ) на экране монитора.
Задачи: Построить графики функций: у=х2; у=sinx; у= x ; у=1/х.
Диаграммы.
Пусть нам дан массив из чисел, необходимо на экране изобразить столбчатую диаграмму так, чтобы
каждому числу соответствовал свой столбик, причем пропорциональность столбцов и чисел должна
соблюдаться. Все столбики должны быть разных цветов и рядом с ними должно стоять число им
соответствующее, желательно около координатной прямой проставить порядковый номер каждого
столбца.
Алгоритм построение столбчатой диаграммы:
1. Ввести массив из чисел.
2. В исходном массиве найти максимальный элемент, и для него определить масштаб для
построения столбиков (например, l=round(450/max)).
3. По количеству элементов определить ширину каждого столбика диаграммы (например,
m=round(600/n), где n – количество элементов массива).
4. Строить каждый столбик, для чего использовать процедуру изображения прямоугольника,
размеры которого определяются следующим образом: ширина стандартна для всех – это m,
высота определяется индивидуально для каждого числа, например h=l*a[i].
5. Возле каждого столбика проставлять его числовое значение и порядковый номер
(пользоваться функцией str).
Задача: Построить столбчатую диаграмму, если в исходном массиве есть еще и отрицательные
числа.
{Пример построения столбиковой диаграммы}
program BarDiagram;
uses crt,graph;
{N - количество элементов исходных данных}
{Name - наименования элементов исходных данных}
{Num - числовые значения элементов исходных данных}
const
N=6;
Name:array[1..N] of string=('1997','1998','1999','2000','2001','2002');
Num:array[1..N] of integer=(10,5,8,11,2,7);
var
Dr,Rg,MaxX,MaxY,X0,Y0,S,I,X1,Y1,X2,Y2,S1:integer;
M:real;
Nm:string;
begin
{Инициализация графического режима}
Dr:=detect;
initgraph(Dr,Rg,'');
{Определение начальных параметров}
cleardevice; {Очистка экрана}
MaxX:=getmaxx; {Определение максимальной координаты по X}
MaxY:=getmaxy; {Определение максимальной координаты по Y}
X0:=40; {Отступ от края экрана до рамки по вертикали}
Y0:=20; {Отступ от края экрана до рамки по горизонтали}
Лекции по Turbo Pascal
76
-
S:=round((MaxX-4*X0)/N); {Определение ширины одного столбца}
X1:=2*X0+2; {Начальная координата по X для первого столбца}
Y1:=MaxY-2*Y0+2; {Конечная координата по Y для всех столбцов}
X2:=X0+2; {Координата по X для вывода значений слева оси Y}
{Рисование рамки}
setfillstyle(1,1);
bar(X0,Y0,MaxX-X0,MaxY-Y0);
setcolor(14);
rectangle(X0,Y0,MaxX-X0,MaxY-Y0);
{Рисование осей}
line(2*X0,2*Y0,2*X0,MaxY-2*Y0); {Ось Y}
line(2*X0,MaxY-2*Y0,MaxX-2*X0,MaxY-2*Y0); {Ось X}
{Поиск наибольшего из значений элементов исходных данных в переменную M}
M:=Num[1];
for I:=2 to N do
if Num[I]>M then
M:=Num[I];
S1:=round((MaxY-4*Y0)/M); {Определение длины единичного отрезка на оси Y}
{Рисование диаграммы}
for I:=1 to N do
begin
Y2:=2*Y0+(MaxY-2*Y0-S1*Num[I]); {Начальная координата по Y}
str(Num[I]:4,Nm);
outtextxy(X2,Y2,Nm); {Вывод значения элемента данных слева оси Y}
line(2*X0-3,Y2-3,2*X0,Y2-3); {Рисование деления на оси Y}
outtextxy(X1,Y1,Name[I]); {Вывод названия элемента данных под осью X}
setfillstyle(1,I+1); {Определение типа заполнения столбца}
bar(X1-1,Y2-3,X1-1+S,Y1-3); {Рисование столбца}
X1:=X1+S; {Начальная координата по Х для очередного столбца}
end;
repeat
until keypressed;
closegraph {Выход из графического режима}
end.
{Пример построения линейной диаграммы}
program LineDiagram;
uses crt,graph;
{N - количество элементов исходных данных}
{Name - наименования элементов исходных данных}
{Num - числовые значения элементов исходных данных}
const
N=6;
Name:array[1..N] of string=('1997','1998','1999','2000','2001','2002');
Num:array[1..N] of integer=(10,5,8,11,2,7);
var
Dr,Rg,MaxX,MaxY,X0,Y0,S,I,X1,Y1,X2,Y2,S1,X3,Y3,X4,Y4:integer;
M:real;
Лекции по Turbo Pascal
77
-
Nm:string;
begin
{Инициализация графического режима}
Dr:=detect;
initgraph(Dr,Rg,'');
{Определение начальных параметров}
cleardevice; {Очистка экрана}
MaxX:=getmaxx; {Определение максимальной координаты по X}
MaxY:=getmaxy; {Определение максимальной координаты по Y}
X0:=40; {Отступ от края экрана до рамки по вертикали}
Y0:=20; {Отступ от края экрана до рамки по горизонтали}
S:=round((MaxX-4*X0)/N); {Определение интервала между точками по X}
X1:=2*X0+2; {Координата по X для первой точки диаграммы}
Y1:=MaxY-2*Y0+2; {Координата по Y для вывода названий под осью Y}
X2:=X0+2; {Координата по X для вывода значений слева от оси Y}
{Рисование рамки}
setfillstyle(1,1);
bar(X0,Y0,MaxX-X0,MaxY-Y0);
setcolor(14);
rectangle(X0,Y0,MaxX-X0,MaxY-Y0);
{Рисование осей}
line(2*X0,2*Y0,2*X0,MaxY-2*Y0); {Ось X}
line(2*X0,MaxY-2*Y0,MaxX-2*X0,MaxY-2*Y0); {Ось Y}
{Поиск наибольшего из значений элементов исходных данных в переменную M}
M:=Num[1];
for I:=2 to N do
if Num[I]>M then
M:=Num[I];
S1:=round((MaxY-4*Y0)/M); {Определение длины единичного отрезка на оси Y}
{Рисование диаграммы}
for I:=1 to N do
begin
Y2:=2*Y0+(MaxY-2*Y0-S1*round(Num[I])); {Координата точки по Y}
X4:=X1-1; {Конечная координата линии по X}
Y4:=Y2-3; {Конечная координата линии по Y}
str(Num[I]:4,Nm);
outtextxy(X2,Y2,Nm); {Вывод значения элемента данных слева оси Y}
line(2*X0-3,Y2,2*X0,Y2); {Рисование деления на оси Y}
outtextxy(X1,Y1,Name[I]); {Вывод названия элемента данных под осью X}
setlinestyle(0,1,1); {Определение типа линии диаграммы}
circle(X4,Y4,2); {Рисование узлов диаграммы}
if I<>1 then
line(X3,Y3,X4,Y4); {Рисование линии диаграммы}
X3:=X1-1; {Начальная координата линии по X}
Y3:=Y2-3; {Начальная координата линии по Y}
X1:=X1+S; {Координата по X для очередной точки}
end;
Лекции по Turbo Pascal
78
-
repeat
until keypressed;
closegraph {Выход из графического режима}
end.
Самостоятельная работа: Построить линейчатую диаграмму, в исходном массиве только
положительные элементы.
Построение круговой диаграммы.
{Пример построения круговой диаграммы}
program RoundDiagram;
uses crt,graph;
{N - количество элементов исходных данных}
{Name - наименования элементов исходных данных}
{Num - числовые значения элементов исходных данных}
const
N=6;
Name:array[1..N] of string=('1997','1998','1999','2000','2001','2002');
Num:array[1..N] of integer=(10,5,8,11,2,7);
var
Dr,Rg,MaxX,MaxY,Y0,I,S1,Kg,Xc,Yc,R,Yk:integer;
M,S:real;
begin
{Инициализация графического режима}
Dr:=detect;
initgraph(Dr,Rg,'');
{Определение начальных параметров}
cleardevice; {Очистка экрана}
MaxX:=getmaxx; {Определение максимальной координаты по X}
MaxY:=getmaxy; {Определение максимальной координаты по Y}
Xc:=300; {Координата центра диаграммы по X}
Yc:=250; {Координата центра диаграммы по Y}
R:=150; {Радиус диаграммы}
{Рисование рамки}
setfillstyle(1,1);
bar(0,0,MaxX,MaxY);
setcolor(14);
rectangle(0,0,MaxX,MaxY);
{Определение суммы значений элементов исходных данных в переменную S}
S:=0;
for I:=1 to N do
S:=S+Num[I];
{Рисование диаграммы}
Y0:=0; {Начальный угол сектора}
for I:=1 to N do
begin
Kg:=round(360*(Num[I]/S)); {Определение кол-ва градусов в секторе}
Yk:=Y0+Kg; {Конечный угол сектора}
if Yk>360 then
Yk:=360;
Лекции по Turbo Pascal
79
-
setfillstyle(1,I+1); {Определение типа заполнения сектора}
pieslice(Xc,Yc,Y0,Yk,R); {Рисование сектора}
Y0:=Yk {Начальный угол сектора}
end;
repeat
until keypressed;
closegraph {Выход из графического режима}
end.
Работа с файлами.
В задачах, которые мы рассматривали, данные поступали с клавиатуры, а результаты выводились на
экран дисплея. Поэтому ни исходные данные, ни результаты не сохранялись. Приходилось заново
вводить данные всякий раз, когда запускали программу. А если их очень много ? Тогда удобно
оформить исходные данные и результаты в виде файлов, которые можно хранить на диске точно так же,
как и программы.
Файл - это область памяти на внешнем носителе, в которой хранится некоторая информация. В языке
Паскаль файл представляет собой последовательность элементов одного типа. Мы будем работать
только с файлами последовательного доступа. В таких файлах, чтобы получить доступ к элементу,
необходимо последовательно просмотреть все предыдущие.
Объявление файловой переменной в разделе описания переменных имеет вид :
var <имя файла>: File of <тип элементов>;
Например:
var Ft : File of integer;
M : File of char;
Type File_integer=File of integer
File_char=File of char;
Var F1: File_integer;
F2: File_char;
Так как в описании указывается тип элементов, такие файлы называются типизированными. Все
элементы файла пронумерованы начиная с нуля.
С каждым файлом связан так называемый файловый указатель. Это неявно описанная переменная,
которая указывает на некоторый элемент файла.
(0)
(1)
...
(к)
(к+1)
...

файловый указатель
Все операции производятся с элементом, который определен файловым указателем.
Связь переменной файлового типа
с файлом на диске.
Процедура Assign(<имя файловой пер-ой>,’<имяфайла на диске>’);
Например:
Assign(F1,’A:INT.DAT’);
После установления такого соответствия все операции, выполняемые над переменной F1, будут
выполнятся над файлом, хранящимся на диске А и имеющим имя INT.DAT
Файл в каждый момент времени может находиться в одном из двух состояний: либо он открыт
только для записи, либо только для чтения.
Чтение из файла.
Под чтением из файла понимается пересылка данных из внешнего файла, находящегося на диске, в
оперативную память.
Для чтения из файла необходимо открыть для чтения посредством процедуры
Reset(<имя файловой переменной>);
Лекции по Turbo Pascal
80
-
Собственно чтение данных из файла выполняется процедурой
Read(<имя файловой переменной>,<имя переменной>);
Переменная должна иметь тот же тип, что и компоненты файла. Отметим, что если оператор ввода
имеет вид Read(<имя переменной>), то данные вводятся с клавиатурой, а если Read(<имя файловой
переменной>,<имя переменной>); то данные вводятся из файла, хранящегося на диске.
Закрытие файла
После того как данные из файла прочитаны, его необходимо закрыть посредством процедуры
Close(< имя файловой переменной>)
Общая схема чтения данных из файла, таким образом, следующая:
Reset(<имя файловой переменной>);
.......
Read(<имя файловой переменной>,<имя переменной>);
...........
Close(<имя файловой переменной>);
Признак конца файла
Так как число элементов файла не известно заранее, необходимо уметь определять, что файл
кончился. Для этого используется логическая функция Eof(<имя файловой переменной>) (Eof - End Of
File). Она принимает истинное значение (Тrue), если достигнут конец файла, и ложное (False) - в
противном случае.
Пример Прочитаем из файла целые числа и выведем их на экран:
Assign(F1,’A:INT.DAT’);
Reset(F1);
While Not Eof(F1) do
begin
read(f1,n); { считываем очередное число из файла}
write(n,’ ‘); { выводим его на экран}
end;
Close(F1);
Запись в файл
Под записью в файл понимается вывод результатов программы из оперативной памяти ЭВМ в файл
на диске.
Для записи в файл необходимо открыть файл для записи посредством процедуры
Rewrite(< Имя файловой переменной >);
Собственно запись данных в файл выполняется процедурой :
Write(<имя файловой переменной>,<значение>);
Общая схема записи данных в файл, таким образом, следующая:
Rewrite(<>);
......
Write(<имя файловой переменной>,<значение>);
..........
Close(<имя файловой переменной>);
Прямой доступ к элементам файла
Несмотря на то, что в стандартном Паскале имеются лишь файлы последовательного доступа, Турбо
Паскаль содержит процедуры и функции для более эффективной работы с файлами. В частности,
имеется возможность осуществлять прямой доступ к элементам файла.
Установка указателя.
Процедура Seek(<имя файловой переменной>,N) устанавливает файловый указатель на N-й элемент.
Например, Seek(F1,3). (на 4 элемент)
Определение номера элемента
Функция FilePos(<имя файловой переменной>) возвращает номер элемента, на который «смотрит»
файловый указатель.
Определение количества элементов в файле
Лекции по Turbo Pascal
81
-
Функция FileSize(<имя файловой переменной>) возвращает количество элементов в файле.
Удаление и переименование файлов
Erase(<имя файловой переменной>) процедура удаления файла.
Rename(<имя файловой переменной>,’<новое имя на диске>’) переименование файла.
Пример : В файле DAT1.DAT записаны целые числа. Вычислить сумму элементов файла и результат
вместе с исходными данными записать в файл DAN2.DAT
Program WW;
Var f1,f2 : file of integer;
s, n : integer;
begin
Assign(f1,’DAT1.DAT’);
Reset(F1);
Assign(f2,’DAT2.DAT’);
Rewrite(f2);
s:=0;
While Not Eof(f1) do { проверка на конец файла}
begin
read(f1,n); {чтение элемента из файла F1}
write(f2,n); { запись элемента в файл F2}
s:=s+n;
end;
write(f2,s); {запись суммы элементов в конец файла F2}
write(‘Результат находится в файле DAT2.DAT’);
Close(f1);
Close(f2);
end.
Текстовые файлы
Текстовые файлы состоят из символьных строк. Строки могут иметь различную длину, и в конце
каждой строки стоит признак конца строки. Для описания текстовых файлов используется служебное
слово Text:
Var A: Text;
Для обработки текстовых файлов используются те же процедуры и функции, что и для обработки
обычных типизированных файлов. Для связывания файловой переменной с файлом на диске
употребляется процедура Assign. Текстовые файлы могут быть открыть для чтения процедурой Reset
или для записи процедурой Rewrite.
Для чтения данных применяется процедура Read. Если необходимо после чтения данных перейти на
следующую строку, то используется процедура Readln. Если необходимо просто перейти к следующей
строке, то можно использовать процедуру Readln(<имя файловой переменной текстового файла>);
которая устанавливает файловый указатель на первый элемент следующей строки.
Процедура Write записывает данные в текущую строку. Если надо записать данные и перейти к
следующей строке, то можно использовать процедуру Writeln. Если требуется только перейти для
записи на новую строку, то применяется процедура Writeln(<имя файловой переменной текстового
файла>); которая записывает в файл признак конца строки и устанавливает файловый указатель на
начало следующей строки.
Так как в строках может быть разное количество символов, имеется логическая функция Eoln(<имя
файловой переменной текстового файла>), которая принимает значение True, если достигнут конец
строки.
Процедура Append(<имя файловой переменной текстового файла>). Она открывает файл для
«дозаписи», помещая файловый указатель в конец файла.
Пример : Дан текстовый файл, содержащий только целые числа, в каждой строке может быть
несколько чисел, которые разделяются пробелами. Вывести на экран все числа с учетом разбиения на
строки и подсчитать количество элементов в каждой строке.
Лекции по Turbo Pascal
82
-
Решение: Пусть в файле содержится следующая информация:
-32 16 0 8 7
4 5 9 13 11 -5 -8
6 -8 0 -12
5 4 3 2 1 12
1 2
Этот файл можно создать в среде Турбо Паскаль следующим образом:
 создайте новый файл посредством команды New меню File;
 запишите все числа, разделяя их пробелами, и разбейте на строки, как указано в задании;
 сохраните файл, например, под именем INT1.DAT
теперь напишем программу
program rrr;
var f : text;
x, k: integer;
begin
Assign(f,’int1.dat’);
Reset(f);
While Not Eof(f) do {пока не достигнут конец файла}
begin
k:=0;
While Not Eoln(f) do {пока не достигнут конец строки}
begin
read(f,x); {считываем очередное число}
write(x,’ ‘); {выводим его на экран}
Inc(k); {увеличиваем счетчик}
end;
writeln(‘в строке’, k, ‘ элементов’);
Readln(f) {переходим к следующей строке файла}
end;
Close(f);
end.
Пример. Записать двумерный массив вещественных чисел 5х4 в тестовый файл.
Program mas;
const m=5; n=4;
Var fil : text;
a: real;
s: char;
i,j : integer;
begin
Assign(fil,’massiv.txt’);
Rewrite(fil);
for i:=1 to m do
begin
for j:=1 to n do
begin
a:=random(100);
write(fil,a:5:3,’ ‘); {число записывается в файл в указанном формате, за ним пробел}
end;
writeln(fil); {переход в файле на новую строку}
end;
Close(fil);
{Чтение файла и вывод матрицы на экран по строкам}
Лекции по Turbo Pascal
83
-
Reset(fil); {открытие уже имеющегося файла}
while not Eof(fil) do
begin
while not Eoln(fil) do
begin
read(fil,a); {чтение числа}
write(a:5:3);
read(fil,s); { чтение пробела после числа}
write(s);
end;
writeln;
readln(fil);
end;
Close(fil);
end.
Пример. Дан текстовый файл f. Переписать в файл g все компоненты исходного файла f в обратном
порядке.
program tofile;
var f, g : text;
n, i, j : integer;
s : string;
x : array [1..32000] of char;
begin
assign(f,’f.txt’); assign(g,’g.txt’);
rewrite(g); rewrite(f);
writeln(‘Введите число строк в создаваемом вами файле ‘);
readln(n);
writeln(‘вводите строки, после введения каждой нажмите Enter’);
for i:=1 to n do begin readln(s); write(f,s); end;
reset(f);
i:=0;
writeln(‘Исходный файл :’);
while(not eof(f)) and (i<32000) do
begin i:=i+1; read(f,x[i]); write(x[i]); end;
writeln;
writeln(‘Измененный файл :’);
for j:=i downto 1 do
begin write(g,x[j]); write(x[j]); end;
writeln;
close(f); close(g);
end.
Задача. Дан текстовый файл. Вставить в начало каждой строки ее номер и записать преобразованные
строки в новый файл.
Задача. Даны два текстовых файла. Записать в третий файл только те строки, которые есть и в
первом, и во втором файлах.
Запись.
При использовании массивов основное ограничение заключается в том, что все элементы должны
иметь один и тот же тип. Но при решении многих задач возникает необходимость хранить и
обрабатывать совокупность данных различного типа.
Лекции по Turbo Pascal
84
-
Пусть известны фамилии и оценки (в баллах) по пяти дисциплинам каждого из двадцати пяти
учеников класса. Требуется вычислить среднюю оценку каждого из учеников и выбрать человека,
имеющего максимальный средний балл.
В данном случае фамилия может быть представлена символьной строкой, оценки - это целые числа, а
средний балл должен быть представлен вещественным числом. В Паскале для описания объектов,
содержащих данные разных типов, используются записи.
Запись - это структурированный тип, описывающий набор данных разных типов. Составляющие
запись объекты называются ее полями. Каждое поле имеет уникальное (в пределах записи) имя. Чтобы
описать запись, необходимо указать ее имя, имена объектов, составляющих запись, и их типы.
Общий вид описания записи :
Type <имя записи> = Record
<поле 1> : <тип 1>;
<поле 2> : <тип 2>
<поле n> : <тип n>
End;
Применительно к рассматриваемой задаче запись можно описать так :
Type
pupil = Record
fam : string[15];
{поле фамилии}
b1,b2,b3,b4,b5 : 2..5; {поля баллов}
sb : Real
{средний бал}
End;
Чтобы хранить в памяти ЭВМ информацию обо всех 25 учениках класса, необходимо ввести массив
klass - массив записей.
Var klass : array[1..25] Of pupil;
Доступ к полям записи можно осуществить двумя способами:
1. С указанием имени переменной и имени поля. Например, klass[2].fam, klass[3].sb, klass[1].b4
Ввод фамилий и оценок учащихся, т.е. элементов массива klass, можно записать так:
for i:=1 to 25 do
begin
readln(klass[i].fam);
readln(klass[i].b1);
readln(klass[i].b2);
readln(klass[i].b3);
readln(klass[i].b4);
readln(klass[i].b5);
end;
2. С использованием оператора присоединения.
Имеется возможность осуществлять доступ к полям записи таким образом, как если бы они были
простыми переменными. Общий вид оператора присоединения:
With <имя записи> Do <оператор>;
Внутри оператора присоединения к компонентам записи можно обращаться только с помощью
имени соответствующего поля.
Пример
for i:=1 to 25 do
With klass[i] do
begin
readln(fam);
readln(b1,b2,b3,b4,b5);
end;
Программа для решения рассматриваемой задачи может быть записана следующим образом:
program zap;
Type pupil = Record
Лекции по Turbo Pascal
85
-
fam : string[15];
{поле фамилии}
b1,b2,b3,b4,b5 : 2..5; {поля баллов}
sb : Real
{средний бал}
End;
Var klass : array[1..25] Of pupil;
p: pupl;
i,m : integer;
sbmax : real;
begin
for i:=1 to 25 do
with klass[i] do
begin
writeln(‘Введите фамилию и пять оценок’);
readln(fam);
readln(b1,b2,b3,b4,b5);
end;
for i:=1 to m do {вычисление среднего балла}
with klass[i] do sb:=(b1+b2+b3+b4+b5)/5;
sbmax:=0;
{ поиск максимального среднего балла}
for i:=1 to m do
if klass[i].sb>=sbmax then sbmax:=klass[i].sb;
for i:=1 to m do {печать результатов}
if klass[i].sb=sbmax
then with klass[i] do writeln(fam:20,’ - ‘, sb:6:3);
end.
Пример. Определите дату завтрашнего дня.
Чтобы определить дату завтрашнего дня, надо знать не только дату сегодняшнего дня, но и
количество дней в данном месяце (так как если это последний день месяца, то завтра будет первый день
следующего), кроме того, надо знать, какой год - високосный или нет.
Пусть дата вводится в формате число - месяц - год следующим образом:
1 2 1997
Опишем запись для хранения даты таким образом:
Type year=1500..2000;
month=1..12;
day=1..31;
data = Record
y : year;
m : month;
d : day;
end;
Заметим, что :
 если дата соответствует не последнему дню месяца, то год и месяц не изменяются, а число
увеличивается на 1;
 если дата соответствует последнему дню месяца, то :
а) если месяц не декабрь, то год не изменяется, месяц увеличивается на 1, а число устанавливается в
1;
б) если месяц - декабрь, то год увеличивается на 1, а месяц и число устанавливаются в 1.
Program datanext;
Type year=1500..2000;
month=1..12;
day=1..31;
data = Record
Лекции по Turbo Pascal
86
-
y : year;
m : month;
d : day;
end;
Var dat, next : data;
Function leap(yy:year):boolean; {функция определяет
високосный ли год}
begin
leap:=(yy Mod 4=0) And (yy Mod 400 <>0);
end;
Function Dmonth(mm:month; yy : year) : day; {функция определения
количества дней данного месяца в данном году}
begin
case mm of
1,3,5,7,8,10,12: Dmonth:=31;
4,6,9,11 : Dmonth:=30;
2 : if leap(yy) then Dmonth:=29 else Dmonth:=28;
end;
end;
procedure Tomorrow(td : data; var nd : data); {опр-ние завтрашней даты}
begin {если это не последний день месяца}
if td.d<> Dmonth(td.m, td.y) then
with nd do
begin
d:=td.d+1;
m:=td.m;
y:=td.y;
end;
else {если это последний день месяца}
if td.m=12 then {если это декабрь}
with nd do
begin
d:=1;
m:=1;
y:=td.y+1;
end;
else { если это не декабрь}
with nd do
begin
d:=1;
m:=td.m+1;
y:=td.y;
end;
end;
BEGIN
writeln(‘Введите сегодняшнее число, месяц и год’);
readln(dat.d, dat.m, dat.y);
Tomorrow(dat,next);
writeln(‘завтра будет’);
writeln(next.d, ‘.’, next.m, ‘.’, next.y);
END.
Задачи:
Лекции по Turbo Pascal
87
-
Фамилии и имена 25 учеников класса записаны в двух различных таблицах. Напечатать фамилию
и имя каждого ученика на отдельной строке.
13.2 Названия 20 футбольных клубов и городов, которые они представляют, записаны в двух
различных таблицах. Напечатать название и город каждого клуба на отдельной строке.
13.3 Даны названия 26 городов и стран, в которых они находятся. Среди них есть города, находящиеся
в Италии. Напечатать их названия.
13.4 Известны данные о 16 сотрудниках фирмы: фамилия и отношение к воинской службе
(военнообязанный или нет). Напечатать фамилии всех военнообязанных сотрудников.
13.5 Известны данные о мощности двигателя (в л.с.) и стоимость 30 легковых автомобилей.
Определить общую стоимость автомобилей, у которых мощность двигателя превышает 100 л.с.
13.6 Известны данные о цене и тираже каждого из 15 журналов. Найти среднюю стоимость журналов,
тираж которых меньше 10000 экземпл.
13.7 Известны данные о массе и объеме 30 чел, изготовленных из различных материалов. Определить
максимальную плотность материала тел.
13.8 Известны вес, пол, рост каждого из 22 человек. Найти общую массу и средний рост мужчин.
13.9 Известно количество очков, набранных каждой из 20 команд - участниц первенства по футболу.
Ни одна пара команд не набрала одинакового количества очков.
а) Определить название команды, ставшей чемпионом.
б) Определить названия команд, занявших второе и третье места.
в) Определить названия команд, занявших первое и второе места, не используя при этом двух
операторов цикла (два прохода по массиву).
г) Вывести названия команд в соответствии с занятыми ими местами в чемпионате.
13.10 Известны оценки каждого из 25 учеников класса по десяти предметам. Найти фамилию одного из
учеников :
а) имеющих наибольшую сумму оценок;
б) имеющих наименьшую сумму оценок.
13.11 Известны баллы, набранные каждым из 20 спортсменов-пятиборцев в каждом из пяти видов
спорта. Определить фамилию спортсмена - победителя соревнований.
13.12 Известны данные о 20 учениках класса: фамилии, имена, отчества, даты рождения (год, номер
месяца и число). Определить, есть ли в классе ученики, у которых сегодня день рождения, и если
да, то напечатать имя и фамилию каждого.
13.1
10 класс
Повторение: Решить следующую задачу: Существует фирма, которая организует работу на
контрактной основе, то есть если для какого-либо специалиста есть работа он нанимается, по окончания
работы он увольняется, причем буквально на следующий день его могут нанять снова. Дан файл в
котором хранится вся информация по рабочим за год, причем общее количество рабочих неизвестно.
Она выглядит следующим образом: в первой строке записана фамилия рабочего, на следующей строке
день и месяц его найма, на третьей – день и месяц окончания работы. Необходимо:
а) вывести на экран список рабочих напротив каждой фамилии каждого указано количество дней его
работы, причем если рабочий был нанят несколько раз, то и в списке его фамилия фигурирует
несколько раз.
б) вывести на экран список рабочих и у каждого указать общее количество рабочих дней за год.
в) сформированный в предыдущем пункте список отсортировать по убыванию количества рабочих
дней.
Двоичный и к-ичный перебор.
Метод двоичного перебора применяется в тех случаях, когда требуется организовать перебор
всевозможных подмножеств данного множества (множество в Паскале представляет собой набор
различных элементов одного типа). То есть если есть набор каких-либо элементов, то из него мы можем
выбирать элементы в любых сочетаниях, и в любых количествах (например, группа людей в количестве
ну для определенности пяти человек, собирается на прогулку, при этом они в итоге могут пойти все, а
если вдруг испортилась погода, то может не пойти вообще никто, а могут собраться двое, трое и т.д.).
Очевидно, что каждый элемент из рассматриваемого множества может иметь только два состояния
Лекции по Turbo Pascal
88
-
(включен или не включен, активен или не активен, есть или нет). Получаем, что каждый элемент может
иметь только два значения именно поэтому данный метод, и является двоичным.
В качестве модели рассмотрим массив из n элементов, каждый из которых может принимать только
два значения (каждый элемент массива соответствует какому-то одному объекту множества),
следовательно, получаем, что элемент массива может принимать только два значения: 0 – не выбран
или 1 - выбран, то есть данный объект множества включен в подмножество.
Задача сводится к тому, чтобы перебрать все возможные комбинации 0 и 1, в результате чего
учитываются все варианты, при этом они не должны повторяться. Для определенности рассмотрим
множество, состоящее из пяти элементов. Вначале в массив запишем пять нулей: (0, 0, 0, 0, 0). Эти нули
соответствуют начальному состоянию множества, заключающееся в том, что выбранных объектов нет
(то есть пустое множество).
На первом шаге обработки массива, увеличим на единицу последний элемент массива, то есть,
получаем следующее подмножество (0, 0, 0, 0, 1). Тем самым мы получили новый возможный вариант
комплектации массива, в котором выбран последний пятый элемент.
На втором шаге снова увеличиваем последний элемент массива на единицу, при этом получаем что
он равняется двойке, что невозможно по условию формирования массива, следовательно последний
элемент необходимо занулить, а на единицу увеличиваем предыдущий элемент, то есть четвертый,
получаем (0, 0, 0, 1, 0). Этот вариант соответствует тому, что выбран только четвертый объект
множества.
На третьем шаге снова увеличиваем последний элемент массива на единицу, получаем (0, 0, 0, 1, 1).
Что соответствует тому, что выбраны уже четвертый и пятый объект некоторого множества.
На четвертом шаге снова увеличиваем последний элемент массива на единицу, и он у нас в итоге
равняется двойке, что невозможно, поэтому мы его зануляем, а на единицу увеличиваем предыдущий
разряд, при этом он так же обращается в двойку, необходимо и его занулить, а на единицу увеличить
третий элемент массива, в результате получаем такой вариант (0, 0, 1, 0, 0). Следовательно, во
множестве выбран только третий объект.
И таким образом происходит перебор всех возможных вариантов формирования множества
состоящего из нулей и единиц. Последний возможный вариант для нашего множества, это все единицы
(1, 1, 1, 1, 1). Что соответствует выбору всех объектов рассматриваемого множества. Предположим, что
мы не остановились на этом этапе и продолжили увеличивать наш массив, то есть на единицу
увеличиваем последний элемент массива, при этом он обращается в двойку, мы его зануляем и
переносим единицу в предыдущий разряд, и в нем получаем двойку, снова зануляем и переносим, и это
продолжается до тех пор, пока мы не оказываемся в позиции первого элемента, который также
обращается в двойку, которую необходимо занулить а единицу перенести в предыдущий разряд, то есть
в нулевой, который в обычном используемом нами массиве не фигурирует. Следовательно, в данном
случае нам необходимо определить позицию нулевого элемента массива для определения окончания
перебора всех возможных вариантов формирования массива из нулей и единиц. То есть в начале мы
формирует массив из всех нулей, в том числе ноль находится и в нулевом разряде, после того как нами
перебраны все варианты, и единицы находятся во всех позициях кроме нулевой мы делаем следующий
шаг и получаем нули во всех позициях кроме нулевой, там находится единица, вот именно эта единица
и будет служить для нас окончанием перебора всевозможных вариантов. В результате перебора мы
должны получить 2n вариантов, где n – количество элементов массива. Для успешной работы
программы n не может быть бесконечно, при n>20 на обработку данных программе требуется уже очень
много времени.
Алгоритм решения задачи с использованием двоичного перебора:
1. Ввести исходные данные (если в этом есть необходимость).
2. Сформировать нулевой вектор с номерами элементов от 0 до n.
3. Обработать этот вектор.
4. Сформировать новый вектор.
5. Если нулевой разряд вектора равен 0, то повторить третий пункт, иначе закончить.
Задача 1: Вывести на экран всевозможные наборы 0 и 1 и их порядковые номера.
program primer;
uses crt;
Лекции по Turbo Pascal
89
-
var p: array [0..30] of byte;
n, i, k: integer;
procedure vector;
begin
i:=n;
while p[i]=1 do begin
p[i]:=0;
dec(i);
end;
p[i]:=1;
end;
procedure work;
begin
inc(k);
write (k:3,’: ‘);
for i:=1 to n do
write (p[i]);
writeln;
end;
begin
clrscr;
writeln (‘Введите n’);
readln (n);
k:=0;
for i:=0 to n do p[i]:=0;
repeat
work;
vector;
until p[0]=1;
readln;
end.
Задачи:
1. Даны n различных цифр, получить из них всевозможные числа, при условии, что в числе
цифры не повторяются.
2. Даны n различных букв, получить все возможные слова из них при условии что буквы в
словах не повторяются.
3. Имеется n монет разного достоинства, определить, можно ли получить задуманную сумму
денег, данными монетами. Если вариантов несколько, то вывести их все на экран, а если их
нет, то сообщить об этом.
4. Имеется n камней (известна их масса), разложить эти камни на две кучки так, чтобы массы
этих кучек отличались друг от друга как можно меньше (в идеале совпадали).
5. Даны две строки, определить может ли первая строка быть получена путем зачеркивания
элементов второй.
6. Известны массы n гирек. определить, можно ли заданный груз взвесить этими гирьками. Если
можно, то указать наилучший (по числу используемых гирек) способ взвешивания. Задачу
решить для двух случаев: а) груз на одной чаше весов, гирьки на другой; б) гирьки могут
находиться на обеих чашках весов.
Контрольная работа:
1. Дан ряд цифр 1, 2, 3, 4, 5, 6, 7, 8, 9. Можно ли получить данное число s, расставляя между
цифрами знаки + и -. Если можно то указать способ расстановки знаков. ( Тесты: s=45
Лекции по Turbo Pascal
90
-
1+2+3+4+5+6+7+8+9; s=2 нельзя (любое четное нельзя); s=1 1-2-3-4+5-6-7+8+9 (12
вариантов); s=47 нельзя; s=31 1+2+3+4+5+6-7+8+9 (3 варианта).
2. Известно количество страниц в каждом из n произведений. определить можно ли
распределить эти произведения на 3 тома так, чтобы все тома оказались одинаковыми. Если
можно, то вывести один из вариантов распределения. (Тесты: n=6 (7, 10, 4, 8, 2, 5) можно
(7+5, 8+4, 10+2); n=5 (5, 4, 6, 3, 8) нельзя; n=3 (5, 5, 5) можно (5, 5, 5); n=8 (5, 4, 3, 4, 2, 1, 6, 5)
можно (по 10); n=6 (3, 3, 3, 3, 3, 5) нельзя).
3. Известны массы n камней. Распределить камни на три кучки так, чтобы массы самой легкой и
самой тяжелой кучки отличались минимально. в идеале совпадали.
Генерация перестановок.
Предположим, что нам дана такая задача: Вывести на экран все перестановки чисел 1..n (то есть
последовательности длины n, в каждую из которых каждое из чисел 1..n входит по одному разу).
Для определенности рассмотрим пример при n=5.
Изначально имеем такую расстановку чисел 1 2 3 4 5.
На первом шаге поменяем местами два последних элемента, получим 1 2 3 5 4.
Дальше начнем искать первый с конца элемент, который будет меньше следующего за ним (5>4, а
вот 3<5). Следовательно, таким элементом будет тройка, стоящая на третьей позиции. Теперь
необходимо найти самый правый элемент больший, чем этот ( 5>3, но правее стоит 4, и она тоже
больше тройки), следовательно таким элементом будет четверка стоящая на пятой позиции. Меняем их
местами. Получили такую перестановку: 1 2 4 5 3. при этом хвост массива, то есть элементы, стоящие
на двух последних местах оказались упорядоченными по убыванию, поэтому если мы ничего не
изменим, то они так и останутся навсегда на своих местах, и тем самым мы потеряем некоторые
варианты, для того чтобы этого не произошло, переставим их в порядке возрастания, и только после
этого будем считать, что мы нашли новый, третий по счету вариант перестановки: 1 2 4 3 5.
Теперь опять начинаем просматривать массив с конца в поисках первой пары элементов, из которых
левый меньше правого, а также самый правый элемент больший этого левого (3<5, и при этом 5 самый
правый), следовательно, необходимо поменять их местами
{Этот алгоритм хорошо известен и достаточно подробно изложен. Опишем его (при N=5), от чего
рассуждения не утратят общности. Алгоритм составлен так, что в процессе его исполнения
перестановки N чисел располагаются лексикографически (в словарном порядке). Это значит, что
перестановки сравниваются слева направо поэлементно. Больше та, у которой раньше встретился
элемент, больше соответствующего ему элемента во второй перестановке. (Например, если
S=(3,5,4,6,7), а L=(3,5,6,4,7), то S<L).
Принцип работы алгоритма разъясним на примере. Допустим, необходимо воспроизвести все
перестановки цифр 3,4,5,6,7. Первой перестановкой считаем перестановку (3,4,5,6,7). Последней
воспроизводимой перестановкой будет (7,6,5,4,3). Предположим, что на некотором шаге работы
алгоритма получена перестановка
P=(5,6,7,4,3).
Для того чтобы определить непосредственно следующую за ней перестановку, необходимо,
пересматривая данную перестановку справа налево, следить за тем, чтобы каждое следующее число
было больше предыдущего, и остановиться сразу же, как только это правило нарушится. Место
останова указано стрелкой:
(5,6,7,4,3).

Затем вновь просматриваем пройденный путь ( справа налево ) до тех пор, пока не дойдем до
первого числа, которое уже больше отмеченного. Ниже место второго останова отмечено двойной
стрелкой.
(5,6,7,4,3).

Поменяем местами, отмеченные числа:
(5,7,6,4,3).

Лекции по Turbo Pascal
91
-
Теперь в зоне, расположенной справа от двойной стрелки, упорядочим все числа в порядке
возрастания. Так как до сих пор они были упорядочены по убыванию, то это легко сделать, перевернув
указанный отрезок. Получим: Q=(5,7,3,4,6).
Q и есть та перестановка, которая должна воспроизводиться непосредственно после P.
Действительно, P<Q, так как, пересматривая эти перестановки слева направо, (P(2)=6,Q(2)=7). Пусть
существует такая перестановка R, что P<R<Q. Тогда P(1)=R(1)=Q(1). По построению же Q(2) – это
наименьшее во множестве Q\Q(1)={3,4,6,7} число, такое, что Q(2)>P(2). Поэтому для R(2) верно одно из
двух равенств: R(2)=Q(2) или R(2)=P(2). Но так как в P элементы, начиная с P(3), убывают, то из P<R
следует, что если P(2)=R(2), то и P=R. Аналогично, так как в Q элементы, начиная с Q(3), возрастают, то
из R<Q следует, что если R(2)=Q(2), то и R=Q.}
Алгоритм генерации перестановок:
1. Просматриваем a1,.., an с кона до тех пор, пока не попадется ai<ai+1. если таковых нет, значит,
генерация закончена.
2. Рассматриваем ai+1, …, an. Находим первый с конца am>ai и меняем их местами.
3. ai+1, ai+2, …, an переставим в порядке возрастания.
4. Выводим найденную перестановку.
5. Возвращаемся к первому пункту.
В результате всех перестановок, всевозможных вариантов должно получиться n!, где n – количество
элементов рассматриваемого массива.
Первой должна быть перестановка 1 2 3 …n, а последней n n-1…2 1.
program perest;
uses crt;
var
a: array [1..20] of byte;
i, j, k, n, kol, z: integer;
procedure form;
begin
i:=n-1;
while (i>0) and (a[i]>a[i+1]) do dec(i);
if i>0 then begin
j:=n;
while a[j]<a[i] do dec(j);
z:=a[i]; a[i]:=a[j]: a[j]:=z;
for k:=i+1 to (i+1+n) div 2 do begin
z:=a[k];
a[k]:=a[n-k+i+1];
a[n-k+i+1]:=z;
end;
end;
end;
procedure obr;
begin
for i:=1 to n do
write (a[i], ‘ ‘ );
writeln;
inc(i);
end;
begin
clrscr;
writeln(‘Введите количество элементов');
readln(n);
for i:=1 to n do
a[i]:=i;
Лекции по Turbo Pascal
92
-
repeat
obr;
form;
until i=0;
writeln(‘Количство вариантов’, kol);
readln;
end.
Задачи:
1. Вывести на экран все перестановки последовательности n различных букв: абвгд…
2. Письма на удачу вкладываются в подписанные конверты. Определить количество раскладок,
когда ни одно из n писем не попадает к своему адресату.
3. Вывести на экран все перестановки из n различных букв при условии, что гласные буквы не
могут стоять рядом. Определить количество таких перестановок.
4. В ряд выкладываются b белых шаров, s синих шаров и k красных шаров. Определить
количество расстоновок шаров, если шары одинакового цвета не могут стоять рядом. вывести
эти расстановки на экран.
5. Расстаивть n ладей на поле размером nn так, чтобы они не били друг друга. Определить
количество таких расстановок.
6. Расставить n ферзей на шахматной доске размером nn так, чтобы они не били друг друга.
Определить количество таких расстановок.
7. Имеется n юношей и n девушек. Некоторые юноши знакомы с некотрыми девушками.
Определить максимальное число возможных браков между ними, если известно, что браки
могут заключаться только между знакомыми людьми, а многоженство и многомужество
запрещены.
Поиск в графе.
Определим граф как конечное множество вершин V и набор E неупорядоченных и упорядоченных
пар вершин и обозначим G=(V,E). Мощности множеств V и E будем обозначать буквами N и M.
Неупорядоченная пара вершин называется ребром, а упорядоченная пара - дугой. Граф, содержащий
только ребра, называется неориентированным; граф, содержащий только дуги, - ориентированным, или
орграфом. Вершины, соединенные ребром, называются смежными. Ребра, имеющие общую вершину,
также называются смежными. Ребро и любая из его двух вершин называются инцидентными. Говорят,
что ребро (u, v) соединяет вершины u и v. Каждый граф можно представить на плоскости множеством
точек, соответствующих вершинам, которые соединены линиями, соответствующими ребрам. В
трехмерном пространстве любой граф можно представить таким образом, что линии (ребра) не будут
пересекаться.
Способы описания. Выбор соответствующей структуры данных для представления графа имеет
принципиальное значение при разработке эффективных алгоритмов. При решении задач используются
следующие четыре основных способа описания графа: матрица инциденций; матрица смежности;
списки связи и перечни ребер. Мы будем использовать только два: матрицу смежности и перечень
ребер.
Матрица смежности - это двумерный массив размерности N*N.
 1, ве ршина с номе ром i смежна с ве ршиной с номе ром j
A[i,j]= 
0, ве ршина с номе ром i не смежна с ве ршиной с номе ром j
Для хранения перечня ребер необходим двумерный массив R
размерности M*2. Строка массива описывает ребро.
Множество алгоритмов на графах требует просмотра вершин графа. Рассмотрим их.
Поиск в глубину
Идея метода. Поиск начинается с некоторой фиксированной вершины v. Рассматривается вершина
u, смежная с v. Она выбирается. Процесс повторяется с вершиной u. Если на очередном шаге мы
работаем с вершиной q и нет вершин, смежных с q и не рассмотренных ранее (новых), то возвращаемся
Лекции по Turbo Pascal
93
-
из вершины q к вершине, которая была до нее. В том случае, когда это вершина v, процесс просмотра
закончен. Очевидно, что для фиксации признака, просмотрена вершина графа или нет, требуется
структура данных типа:
Nnew : array[1..N] of boolean.
Пример.
Пусть граф
описан матрицей смежности A.
Поиск начинается с первой
вершины. На левом рисунке
приведен исходный граф, а на
правом рисунке у вершин в
скобках указана та очередность, в
которой вершины графа
просматривались в процессе
поиска в глубину.
Логика.
procedure Pg(v:integer);{Массивы
Nnew и A глобальные}
var j:integer;
begin
Nnew[v]:=false; write(v:3);
for j:=1 to N do if (A[v,j]<>0) and Nnew[j] then Pg(j);
end;
Фрагмент основной логики.
...
FillChar(Nnew,SizeOf(Nnew),true);
for i:=1 to N do if Nnew[i] then Pg(i);
...
В силу важности данного алгоритма рассмотрим его нерекурсивную реализацию. Глобальные
структуры данных прежние: A - матрица смежностей; Nnew - массив признаков. Номера
просмотренных вершин графа запоминаются в стеке St, указатель стека - переменная yk.
procedure PG1(v:integer);
var St:array[1..N] of integer;yk:integer;t,j:integer;pp:boolean;
begin
FillChar(St,SizeOf(St),0); yk:=0;
Inc(yk);St[yk]:=v;Nnew[v]:=false;
while yk<>0 do begin {пока стек не пуст}
t:=St[yk];
{выбор “самой верхней“ вершины из стека}
j:=0;pp:=false;
repeat
if (A[t,j+1] <>0) and Nnew[j+1] then pp:=true
else Inc(j);
until pp or (j>=N); {найдена новая вершина или все вершины, связанные с данной вершиной,
просмотрены}
if pp then begin
Inc(yk);St[yk]:=j+1;Nnew[j+1]:=false;{добавляем в стек}
end
else Dec(yk); {“убираем” вершину из стека}
end;
end;
Поиск в ширину
Лекции по Turbo Pascal
94
-
Идея метода. Суть (в сжатой формулировке) заключается в том, чтобы рассмотреть все
вершины, связанные с текущей. Принцип выбора следующей вершины - выбирается та, которая была
раньше рассмотрена. Для реализации данного принципа необходима структура данных “очередь”.
Пример. Исходный граф на
левом рисунке. На правом рисунке
рядом с вершинами в скобках
указана очередность просмотра
вершин графа.
Приведем процедуру
реализации данного метода обхода
вершин графа.
Логика просмотра вершин.
procedure PW(v:integer);
var Og:array[1..N] of 0..N;
{очередь}
yk1,yk2:integer;
{указатели очереди, yk1 - запись; yk2 - чтение}
j:integer;
begin
FillChar(Og,SizeOf(Og),0);yk1:=0;yk2:=0;{начальная инициализация}
Inc(yk1);Og[yk1]:=v;Nnew[v]:=false;{в очередь - вершину v}
while yk2<yk1 do begin
{пока очередь не пуста}
Inc(yk2);v:=Og[yk2];write(v:3);{“берем” элемент из очереди}
for j:=1 to N do {просмотр всех вершин, связанных с вершиной v}
if (A[v,j]<>0) and Nnew[j] then begin{если вершина ранее не просмотрена}
Inc(yk1);Og[yk1]:=j;Nnew[j]:=false;{заносим ее в очередь}
end;
end;
end;
Решение комбинаторных задач.
Задачи дискретной математики, к которым относится большинство олимпиадных задач по
информатике, часто сводятся к перебору различных комбинаторных конфигураций объектов и выбору
среди них наилучшего, с точки зрения условия той или иной задачи. Поэтому знание алгоритмов
генерации наиболее распространенных комбинаторных конфигураций является необходимым условием
успешного решения олимпиадных задач в целом. Важно также знать количество различных вариантов
для каждого типа комбинаторных конфигураций, так как это позволяет реально оценить
вычислительную трудоемкость выбранного алгоритма решения той или иной задачи на перебор
вариантов и, соответственно, его приемлемость для решения рассматриваемой задачи, с учетом ее
размерности. Кроме того, при решении задач полезным оказывается умение для каждой из
комбинаторных конфигураций выполнять следующие операции: по имеющейся конфигурации получать
следующую за ней в лексикографическом порядке; определять номер данной конфигурации в
лексикографической нумерации всех конфигураций; и, наоборот, по порядковому номеру выписывать
соответствующую ему конфигурацию.
Перечисленные подзадачи в программировании обычно рассматривают для следующих
комбинаторных конфигураций: перестановки элементов множества, подмножества множества,
сочетания из n элементов множества по k элементов (k-элементные подмножества множества,
состоящего из nk элементов), размещения (упорядоченные подмножества множества, то есть
отличающиеся не только составом элементов, но и порядком элементов в них), разбиения множества
(множество разбивается на подмножества произвольного размера так, что каждый элемент исходного
множества содержится ровно в одном подмножестве), разбиения натуральных чисел на слагаемые,
правильные скобочные последовательности (различные правильные взаимные расположения n пар
открывающихся и закрывающихся скобок).
Лекции по Turbo Pascal
95
-
Большинство указанных конфигураций были подробно рассмотрены в [1-3]. Однако при генерации
различных конфигураций использовались в основном нерекурсивные алгоритмы. Опытные же
участники олимпиад в подобных случаях при программировании используют в основном именно
рекурсию, с помощью которой решение рассматриваемых задач зачастую можно записать более кратко
и прозрачно. Поэтому для полноты изложения данной темы приведем ряд рекурсивных комбинаторных
алгоритмов и рассмотрим особенности применения рекурсии в комбинаторике.
Генерация k-элементных подмножеств
В комбинаторике такие подмножества называют сочетаниями из n элементов по k элементов и
обозначают Cnk . Их количество выражается следующей формулой:
n!
n(n  1) (n  k  1) n(n  1) (k  1)


, 0  k  n.
(1)
k!(n  k )!
1 2  k
1  2    (n  k )
Однако при программировании гораздо удобнее использовать следующие рекуррентные соотношения:
n
C nk  С nk11  C nk1 , 0  k  n; C nk  С nk11 , 0  k  n.
(2)
k
Объясняется это тем, что в формуле (1) числитель и знаменатель растут очень быстро, поэтому в силу
особенностей компьютерной арифметики не всегда возможно точно вычислить значение Cnk, даже когда
последнее не превосходит максимально представимое целое число.
При фиксированном значении n максимального значения число сочетаний достигает при k = n/2
(вернее, для четного n максимум один и он указан, а для нечетного — максимум достигается на двух
соседних значениях k: [n/2] и [n/2]+1). Поэтому особенно полезной оказывается следующая оценка для
четных n [4] (очевидно, что при нечетных n отличия будут минимальными), основанная на формуле
Стирлинга:
C nk 
С nn / 2 
2n
n / 2
(1  O(1 / n)).
(3)
Если допустить, что за время, отведенное для решения задачи, мы можем перебрать около 106
вариантов, то из формулы (3) следует, что генерацию всех сочетаний из n элементов для любого
фиксированного k можно проводить для n  24.
Обычно генерацию всех k-элементных подмножеств проводят в лексикографическом порядке, тем
более что в данном случае это не приводит ни к усложнению алгоритма, ни к увеличению его
вычислительной трудоемкости. Напомним, что порядок подмножеств называется лексикографическим,
если для любых двух подмножеств справедливо, что раннее должно быть сгенерировано то из них, из
индексов элементов которого можно составить меньшее k-значное число в n-ричной системе счисления
(или в десятичной, для n < 10). Так, для n = 6 и k = 3 сочетание из третьего, первого и пятого элемента
должно быть сгенерировано раньше, чем из второго, третьего и четвертого, так как 135 < 234.
Рассмотрим рекурсивный алгоритм решения данной задачи. Идея сведения данной задачи к задаче
меньшей размерности следующая. Первым элементом подмножества может быть любой элемент,
начиная с первого и заканчивая (n – k + 1)-м элементом. После того, как индекс первого элемента
подмножества зафиксирован, осталось выбрать k – 1 элемент из элементов с индексами, большими, чем
у первого. Далее поступаем аналогично. Когда выбран последний элемент, то мы достигли конечного
уровня рекурсии и выбранное подмножество можно обработать (проанализировать или распечатать). В
предлагаемой ниже программе массив a содержит значения элементов исходного множества и может
быть заполнен произвольным образом. В массиве p будем формировать очередное сочетание из k
элементов.
const nmax = 24;
type list = array[1..nmax] of integer;
var k,i,j,n,q : integer;
a,p : list;
procedure print(k : integer);
var i:integer;
begin
for j:=1 to k do
Лекции по Turbo Pascal
96
-
write(p[j]:4);
writeln
end;{print}
procedure cnk(n,k : integer);
procedure gen(m,L : integer);
var i:integer;
begin
if m=0 then print(k) else
for i:=L to n-m+1 do
begin
p[k-m+1]:=a[i];
gen(m-1,i+1)
end
end;{gen}
begin {cnk}
gen(k,1)
end;{cnk}
begin {main}
readln(n,k);
for i:=1 to n do
a[i]:=i;{заполнить массив можно и по-другому}
cnk(n,k)
end.
Заметим, что собственно генерация сочетаний производится в рекурсивной подпрограмме gen. Она
имеет следующие параметры: m - сколько элементов из множества нам еще осталось выбрать и L начиная с какого элемента исходного множества, следует выбирать эти m элементов. Обратите
внимание, что именно вложенная структура описания процедур cnk и gen позволяет не передавать
при рекурсивных вызовах значения n и k, а из основной программы обращаться к процедуре cnk с
параметрами, соответствующими постановке задачи, не вдаваясь в подробности ее решения. Такой
способ будем применять и в дальнейшем.
Генерация всех подмножеств данного множества
При решении олимпиадных задач чаще всего заранее неизвестно, сколько именно элементов
исходного множества должно входить в искомое подмножество, то есть необходим перебор всех
подмножеств. Однако, если требуется найти минимальное подмножество, то есть состоящее как можно
из меньшего числа элементов (или максимальное подмножество), то эффективнее всего организовать
перебор так, чтобы сначала проверялись все подмножества, состоящие из одного элемента, затем из
двух, трех и т. д. элементов (для максимального подмножества — в обратном порядке). В этом случае,
первое же подмножество, удовлетворяющее условию задачи и будет искомым и дальнейший перебор
следует прекратить. Для реализации такого перебора можно воспользоваться, например, процедурой
cnk, описанной в предыдущем разделе. Введем в нее еще один параметр: логическую переменную
flag, которая будет обозначать, удовлетворяет текущее сочетание элементов условию задачи или нет.
При получении очередного сочетания вместо его печати обратимся к процедуре его проверки check,
которая и будет определять значение флага. Тогда начало процедуры gen следует переписать так:
procedure gen(m,L:integer);
var i:integer;
begin
if m=0 then
begin
check(p,k,flag);
if flag then exit
end
else ...
Лекции по Turbo Pascal
97
-
Далее процедура дословно совпадает с предыдущей версией. В основной же программе
единственное обращение к данной процедуре следует заменить следующим фрагментом:
k:=0;
flag:=false;
repeat
k:=k+1;
cnk(n,1,flag)
until flag or (k=n);
if flag then print(k)
else writeln('no solution');
Очевидно также, что в основной программе запрос значения переменной k теперь не производится.
Существует также альтернативный подход к перебору всех подмножеств того или иного множества.
Каждое подмножество можно охарактеризовать, указав относительно каждого элемента исходного
множества, принадлежит оно данному подмножеству или нет. Сделать это можно, поставив в
соответствие каждому элементу множества 0 или 1. То есть каждому подмножеству соответствует nзначное число в двоичной системе счисления (строго говоря, так как числа могут начинаться с
произвольного количества нулей, которые значащими цифрами не считаются, то следует заметить, что в
соответствие ставятся n- или менее -значные числа). Отсюда следует, что полный перебор всех
подмножеств данного множества соответствует перебору всех чисел в двоичной системе счисления от
0
01 до 1
1.
n 1
n
Теперь легко подсчитать и количество различных подмножеств данного множества. Оно равно 2 n – 1
(или 2n, с учетом пустого множества). Таким образом, сопоставляя два способа перебора всех
подмножеств данного множества, мы получили следующую формулу:
С n0  С n1    С nn  2 n.
(4)
То есть, в рамках сделанной выше оценки на количество допустимых вариантов в переборе, мы можем
рассмотреть все подмножества исходного множества только при n  20.
Прежде, чем перейти к рассмотрению программ, соответствующих второму способу перебора,
укажем, когда применение этих программ целесообразно. Во-первых, данные программы легко
использовать, когда необходимо в любом случае перебрать все подмножества данного множества
(например, требуется найти все решения удовлетворяющие тому или иному условию). Во-вторых, когда
с точки зрения условия задачи не имеет значения, сколько именно элементов должно входить в искомое
подмножество. На примере такой задачи мы и напишем программу генерации всех подмножеств
исходного множества в лексикографическом порядке. Задача взята из книги [5].
Условие. Дан целочисленный массив a[1..N] (N  20) и число M. Найти подмножество элементов массива
a[i1], a[i2], ...a[ik] такое, что 1  i1 < i2 < i3 < ... < ik  N и a[i1] + a[i2] + ...
+ a[ik] = M.
Решение. В качестве решения приведем процедуру генерации всех подмножеств, которые можно
составить из элементов массива и функцию проверки конкретного подмножества на соответствие
условию задачи.
function check(j:longint):boolean;
var k:integer; s:longint;
begin
s:=0;
for k:=1 to n do
if ((j shr (k-1))and 1)=1 {данное условие означает, что в
k-й справа позиции числа j, в 2-й системе, стоит 1}
then s:=s+a[k];
if s=m then
begin
for k:=1 to n do
if ((j shr (k-1))and 1)=1 then write(a[k]:4);
writeln
end
Лекции по Turbo Pascal
98
-
end;
procedure subsets(n:integer);
var q,j:longint;
begin
q:=1 shl n; {таким образом мы помещаем в q число 2^n}
for j:=1 to q-1 do {цикл по всем подмножествам}
if check(j) then exit
end;
Заметим, что если все элементы в массиве положительные, то, изменив порядок рассмотрения
подмножеств, решение приведенной выше задачи можно сделать более эффективным. Так, если сумма
элементов какого-либо подмножества уже больше, чем M, то рассматривать подмножества,
включающие его в себя уже не имеет смысла. Пересчет же сумм можно оптимизировать, если каждое
следующее сгенерированное подмножество будет отличаться от предыдущего не более, чем на один
элемент (такой способ перечисления подмножеств показан в [2]). Приведенная же программа
черезвычайно проста, но обладает одним недостатком: мы не можем ни в каком случае с ее помощью
перебирать все подмножества множеств, состоящих из более, чем 30 элементов, что обусловлено
максимальным числом битов, отводимых на представление целых чисел в Турбо Паскале (32 бита). Но,
как уже было сказано выше, на самом деле, перебор всех подмножеств у множеств большей
размерности вряд ли возможен за время, отведенное для решения той или иной задачи.
Генерация всех перестановок n-элементного множества
Количество различных перестановок множества, состоящего из n элементов равно n!. В этом
нетрудно убедиться: на первом месте в перестановке может стоять любой из n элементов множества,
после того, как мы на первом месте зафиксировали какой-либо элемент, на втором месте может стоять
любой из n – 1 оставшегося элемента и т.д. Таким образом, общее количество вариантов равно n(n – 1)(n
– 2)...321 = n!. То есть рассматривать абсолютно все перестановки мы можем только у множеств,
состоящих из не более, чем 10 элементов.
Рассмотрим рекурсивный алгоритм, реализующий генерацию всех перестановок в лексикографическом
порядке. Такой порядок зачастую наиболее удобен при решении олимпиадных задач, так как упрощает
применение метода ветвей и границ, который будет описан ниже. Обозначим массив индексов
элементов — p. Первоначально он заполнен числами 1, 2, ..., n, которые в дальнейшем будут меняться
местами. Параметром i рекурсивной процедуры Perm служит место в массиве p, начиная с которого
должны быть получены все перестановки правой части этого массива. Идея рекурсии в данном случае
следующая: на i-ом месте должны побывать все элементы массива p с i-го по n-й и для каждого из этих
элементов должны быть получены все перестановки остальных элементов, начиная с (i+1)-го места, в
лексикографическом порядке. После получения последней из перестановок, начиная с (i+1)-го места,
исходный порядок элементов должен быть восстановлен.
{описание переменных совпадает с приведенным выше}
procedure Permutations(n:integer);
procedure Perm(i:integer);
var j,k:integer;
begin
if i=n then
begin for j:=1 to n do write(a[p[j]],' '); writeln end
else
begin
for j:=i+1 to n do
begin
Perm(i+1);
k:=p[i]; p[i]:=p[j]; p[j]:=k
end;
Perm(i+1);
{циклический сдвиг элементов i..n влево}
k:=p[i];
Лекции по Turbo Pascal
99
-
for j:=i to n-1 do p[j]:=p[j+1];
p[n]:=k
end
end;{Perm}
begin {Permutations}
Perm(1)
end;
begin {Main}
readln(n);
for i:=1 to n do p[i]:=i;
a:=p; {массив a может быть заполнен произвольно}
Permutations(n)
end.
Заметим, что в данной программе массив p можно было и не использовать, а переставлять
непосредственно элементы массива a.
Разбиения множества
Число разбиений n-элементного множества на k блоков произвольного размера но таких, что каждый
элемент множества оказывается “приписан” к одному из блоков, выражается числом Стирлинга второго
рода S(n,k) [6,7]. Очевидно, что S(n,k) = 0 для k > n. Если согласиться, что существует только один
способ разбиения пустого множества на нулевое число непустых частей, то S(0,0) = 1 (именно такая
договоренность, как и в случае с факториалом, приводит в дальнейшем к универсальным формулам).
Так как при разбиении непустого множества нужна по крайней мере одна часть, S(n,0) = 0 при n > 0.
Отдельно интересно также рассмотреть случай k = 2. Если непустое множество разделили на две
непустые части, то в первой части может оказаться любое подмножество исходного множества, за
исключением подмножеств, включающих в себя последний элемент множества, а оставшиеся элементы
автоматически попадают во вторую часть. Такие подмножества можно выбрать 2n-1 – 1 способами, что и
соответствует S(n,2) при n > 0.
Для произвольного k можно рассуждать так. Последний элемент либо будет представлять из себя
отдельный блок в разбиении и тогда оставшиеся элементы можно разбить уже на k – 1 частей S(n – 1,k –
1) способами, либо помещаем его в непустой блок. В последнем случае имеется kS(n – 1,k) возможных
вариантов, поскольку последний элемент мы можем добавлять в каждый блок разбиения первых n - 1
элементов на k частей. Таким образом
S(n,k) = S(n – 1, k – 1) + kS(n – 1, k), n > 0.
(5)
Полезными могут оказаться также формулы, связывающие числа Стирлинга с биномиальными
коэффициентами, определяющими число сочетаний:
n 1
1 k i n
C k i (1) k i .
(6)

k
!
i  k 1
i 1
Если же значение k теперь не фиксировать и рассмотреть все разбиения n-элементного множества, то
их количество выражается числом Белла
S (n, k ) 
 C ni 1 S (i, k  1); S (n, k ) 
n
n
k 0
i 0
Bn   S (n, k ); Bn 1   C ni Bi .
(7 )
По формулам (7) можно подсчитать, что в рамках принятых выше допущений можно построить все
разбиения множества, состоящего не более чем из 15 элементов (B15=1382958545).
Перейдем теперь к рассмотрению способа генерации всех разбиений исходного множества. Прежде
всего следует договориться о том, как обозначать текущее разбиение. Так как в каждом из разбиений
участвуют все элементы исходного множества, будем в массиве индексов p записывать в какой блок
попадает каждый из элементов в текущем разбиении. Параметр i в рекурсивной процедуре part
означает, что на текущем шаге мы именно i-ый элемент будет размещать в каждом из допустимых для
него блоков, а j как раз и определяет максимальный номер допустимого блока. После того, как i-ый
Лекции по Turbo Pascal
100
-
элемент помещен в один из блоков, рекурсивно решается такая же задача уже для следующего элемента
(в данном случае фактически работает универсальная схема перебора с возвратом [8]).
procedure partition(n : integer; var p:list);
procedure part(i, j: integer);
var l: integer;
begin
if i > n then print(n, p) else
for l := 1 to j do
begin
p[i] := l;
if l = j then part(i+1, j+1)
else part(i+1, j)
end
end; {part}
begin {partition}
part(1,1)
end;
Как ни странно, в данном случае процедура print оказывается совсем не тривиальной, если
требуется печатать (или анализировать) элементы каждого из блоков разбиения в отдельности. Поэтому
приведем возможный вариант ее реализации (как и ранее, распределяли по блокам мы индексы, а
печатаем или анализуруем сами элементы исходного массива a):
procedure print(n:integer; var p:list);
var i,j,imax:integer;
begin
imax:=1;{определяем количество блоков в разбиении}
for i:=2 to n do
if p[i]>imax then imax:=p[i];
for i:=1 to imax do {цикл по блокам}
begin
for j:=1 to n do
if p[j]=i then write(a[j]:4);
write('
|') {блок напечатан}
end;
writeln {разбиение напечатано}
end;
Вложенного цикла можно избежать, если требуется, например, подсчитать сумму элементов в
каждом из блоков. Тогда, используя дополнительный массив, мы, просматривая элементы массива a
последовательно, будем увеличивать значения суммы для блока, соответствующего рассматриваемому
элементу (аналогично операции, осуществляемой в алгоритме сортировки подсчетом).
Если при этом рассматривать массив p как n-значное число n-ричной системе счисления, то можно
ввести понятие лексикографического порядка для разбиений множества и ставить задачи определения
номера разбиения и обратную ей. Как и ранее (см. [1-3]), они решаются методом динамического
программирования и не используют непосредственную генерацию всех разбиений.
Для полноты рассмотрения данной темы самостоятельно измените процедуру partition так, чтобы
она генерировала все разбиения, состоящие не более, чем из k блоков. После этого напишите процедуру
разбиения множества уже на ровно k непустых частей.
Олимпиадные задачи, использующие комбинаторные конфигурации
Пример 1. На одном острове Новой Демократии каждый из его жителей организовал партию, которую сам и
возглавил. Отметим, что ко всеобщему удивлению даже в самой малочисленной партии оказалось не менее двух
человек. К сожалению, финансовые трудности не позволили создать парламент, куда вошли бы, как
предпологалось по Конституции острова, президенты всех партий. Посовещавшись, Островитяне решили, что
будет достаточно, если в парламенте будет хотя бы один член каждой партии. Помогите Островитянам
организовать такой, как можно более малочисленный парламент, в котором будут представлены члены всех
партий.
Исходные данные: каждая партия и, соответственно, ее президент имеют одинаковый порядковый номер от 1 до
Лекции по Turbo Pascal
101
-
N (4  N  150). Вам даны списки всех N партий Острова Новой Демократии. Выведите предлагаемый Вами
парламент в виде списка номеров его членов. (Олимпиада стран СНГ, г. Могилев, 1992 г.)
Решение: с теоретической точки зрения, данная задача совпадает с задачей генерации всех подмножеств
из множества жителей острова новой демократии. Причем наиболее подходящим кажется первый
подход к решению данной задачи, связанный с генераций различных сочетаний, начиная с одного
жителя. Для полноты изложения этого подхода, опишем функцию сheck, которую следует применить
в данной задаче. Исходные данные следует записать в массив s:array[1..150] of set of
1..150, заполнив каждый из n первых элементов этого массива множеством тех партий, в которых
состоит тот или иной житель. Тогда функция проверки сочетания из элементов этого массива примет
следующий вид:
function check(var p:list;k:integer): boolean;
var i:integer; ss:set of 1..150;
begin
ss:=[];
for i:=1 to k do ss:=ss+s[p[i]];
check:=(ss=[1..n])
end;
Как видно из описания функции, использование типа “множество”, позволяет не только упростить
данную программу, но и существенно ускорить ее выполнение, по сравнению с работой с массивами.
Однако большая размерность данной задачи не позволяет считать приведенное решение
удовлетворительным во всех случаях. Так, уже для n = 100, перебор всех сочетаний из 4-х и менее
жителей приводит к рассмотрению около 4-х миллионов вариантов. Для построения кода, пригодного
для решения данной задачи при любых входных данных, несколько изменим описание массива s:
s: array[1..150] of
record name,number:integer;
partys: set of 1..150
end;
Здесь поле partys совпадает по смыслу с первоначальным описанием массива s, поле name
cоответствует номеру (то есть фактически имени) жителя и первоначально данное поле следует
заполнить числами от 1 до n cогласно индексу элемента в массиве записей, и поле number
соответствует количеству элементов во множестве из поля partys, то есть имеет смысл сразу
подсчитать, в каком количестве партий состоит тот или иной житель. Теперь следует отсортировать
массив s по убыванию значений поля number. Верхнюю оценку для числа членов парламента (kmax)
подсчитаем, построив приближенное решение данной задачи следующим образом: во-первых, включим
в парламент жителя, состоящего в максимальном количестве партий, затем исключим эти партии из
остальных множеств и заново найдем в оставшемся массиве элемент с максимальным значением поля
number (уже пересчитанного) и включим его в парламент, и так далее, до тех пор пока сумма значений
пересчитанных полей number у жителей, включенных в парламент, не будет равна n. Найденное
количество членов парламента и будет kmax.
Теперь следует рассматривать сочетания из (kmax – 1) элемента, затем из (kmax – 2) и т. д. элементов.
Если для сочетаний из какого-то рассматриваемого количества элементов k, решение найдено не будет,
то это означает, что точным является решение с количеством членов парламента k+1. Так как массив s
упорядочен, то, если решение для того или иного значения k существует, то, скорее всего, оно будет
найдено при рассмотрении в лексикографическом порядке первых же сочетаний по k элементов.
Поэтому временная трудоемкость в переборе возникает, только если решения c данным значением k не
существует. В такой ситуации можно воспользоваться следующим “ненаучным” приемом: на поиск
решения для каждого k, меньшего, чем kmax отведем фиксированное количество времени, скажем 2-3
секунды (точнее данное время стоит определить экспериментальным путем). Если за отведенное время
решение не найдено, то следует считать полный перебор невозможным и закончить выполнение
программы. В любом случае, мы будем иметь какое-либо решение исходной задачи: точное или
приближенное, то есть, возможно содержащее больше членов парламента, чем минимально возможно.
Однако, на практике такой подход почти всегда приводит к точному решению, в силу перебора “с
предпочтением”, проводимого для каждого k (невозможность проведения полного перебора для какоголибо k на практике соответствует отсутствию решения для данного k).
Лекции по Turbo Pascal
102
-
Пример 2. Дан автобусный билет с номером, состоящим из N цифр. Расставить между цифрами знаки
арифметических операций '+', '-', '*', '/' (целочисленное деление) и скобки таким образом, чтобы значение
полученного выражения было равно 100. Можно образовывать многозначные числа из стоящих рядом цифр.
Выражение должно быть корректным с точки зрения арифметики. Допустимы лишние скобки, не нарушающие
корректности выражения. При вычислениях используется стандартный приоритет операций, число цифр N в
номере билета не больше 6. (5-ая Всероссийская олимпиада по информатике, г.Троицк, 1993 г.)
Решение. для построения универсального алгоритма решения данной задачи будем считать слияние
двух соседних цифр одной из операций. Тогда между каждой парой соседних цифр может стоять одна
из 5 операций. Для N цифр получаем 5N-1 различных вариантов расстановки операций. Перебирать все
варианты расстановки операций удобнее всего с помощью рассмотрения всех чисел в 5-ричной системе
счисления, состоящих не более чем из N – 1 цифры, то есть для N = 6 от 00000 до 44444. Для перебора
таких чисел необходимо написать процедуру прибавления 1 в 5-ричной системе счисления. Для
каждого из вариантов расстановки операций перейдем от исходного массива из N цифр билета, к
массиву из К чисел, где K = (N – количество операций слияния цифр в рассматриваемом варианте).
Теперь мы должны рассмотреть все перестановки из K – 1 арифметической операции в данном
варианте. Каждая перестановка соответствует одному из порядков выполнения арифметических
операций. Так, для 4-х чисел, перестановка номеров операций 3, 1, 2 означает, что сначала нужно
выполнить арифметическое действие между 3-м и 4-м числом, затем между 1-м и 2-м и затем
оставшееся. Если результат выполнения действий данного варианта в порядке, соответствующем
текущей перестановке, равен искомому числу 100, то задача решена и можно перейти к печати
результата. Для данной задачи возможны и более эффективные решения, но в силу ее небольшой
размерности, комбинаторный перебор оказывается вполне приемлемым.
Пример 3. Губернатор одной из областей заключил с фирмой "HerNet" контракт на подключение всех городов
области к компьютерной сети. Сеть создается следующим образом: в области устанавливается несколько станций
спутниковой связи, и затем от каждого города прокладывается кабель до одной из станций. Технология,
используемая компанией требует при увеличении расстояния увеличения толщины кабеля. Таким образом,
стоимость кабеля, соединяющего город со станцией, при используемой компанией технологии будет равна kL2,
где L - расстояние от города до станции, а k - некий коэффициент. Вам требуется написать программу,
определяющую минимальные затраты компании на установку сети.
Входные данные. Во входном файле записано число n (1 ≤ n ≤ 10) - количество городов в области. Затем идут
положительные вещественные числа: k - коэффициент стоимости кабеля и P - стоимость постройки одной
станции. Далее следует n пар вещественных чисел, задающих координаты городов на плоскости.
Выходные данные. В первую строку выходного файла нужно вывести минимальные затраты на установку сети (с
тремя знаками после десятичной точки), во вторую - количество устанавливаемых станций. Далее вывести
координаты станций (с тремя знаками после десятичной точки), а затем - список из n целых чисел, в котором i-ое
число задает номер станции, к которой будет подключен i-ый город. (Кировский командный турнир по
программированию, 2000 г.)
Решение. В силу небольшой размерности мы можем рассмотреть все возможные варианты разбиения
городов на группы, подразумевая что для каждой группы будет установлена своя станция, причем
оптимальным образом (найти оптимальное местонахождение станции для одной группы городов можно
по формуле, аналогичной формуле нахождения центра масс). Затем нужно из всех разбиений выбрать
то, для которого общая сумма затрат на установку сети будет минимальной.
Решение геометрических задач.
Пусть даны две точки А (х1,у1) и В (х2,у2), как известно на плоскости они однозначно определяют
одну единственную прямую. Давайте вспомним, как выглядит общее уравнение прямой: Ах+Ву+С=0.
Тогда если считаем что наша прямая задана точками А и В, то уравнение прямой проходящей через эти
x  x1
y  y1

две точки выглядит так:
. Если пользоваться данной формулой, то нам придется
x2  x1 y2  y1
постоянно делать проверку на деление на ноль, что не очень удобно, чтобы это избежать, лучше
использовать такое равенство: (х-х1)(у2-у1)=(у-у1)(х2-х1).
Иногда бывает удобнее пользоваться уравнением прямой заданной в параметрическом виде:
 x  x1  t ( x2  x1 )
, где t некий параметр, а (х1,у1) и (х2,у2) – координаты точек расположенных на

y

y

t
(
y

y
)
1
2
1

Лекции по Turbo Pascal
103
-
рассматриваемой прямой.
Полезно будет так же вспомнить и как вычисляется расстояние между двумя точками:
d  ( x2  x1 ) 2  ( y2  y1 ) 2 .
Задача: Вычислить расстояние которое пройдет путник двигаясь из точки А в точку В (при этом
необходимо вычислить кратчайшее расстояние), если известно, что от точки (-1,0) до (1,0) вырыт
непроходимый ров, пересечь который нельзя, можно лишь проходить по его краю.
(Пояснение: )
Решение задачи будет несколько проще, если мы введем функцию, которая позволяет определять
взаимное положение трех точек. Итак, значит, у нас есть три точки: А (х 1,у1), В (х2,у2) и С (х3,у3). Две из
них однозначно определяют одну прямую и следовательно расположены на ней, весь вопрос состоит в
том, а будет ли на этой же прямой располагаться и третья точка. Пусть прямую у нас определяют точки
А и В, для того чтобы определить лежит на этой прямой точка С, составим следующую
x x y y
функцию: F  3 1 3 1 . Или F=((х3-х1)(у2-у1)-(у3-у1)(х2-х1)). Если F=0, то все три точки лежат на
x2  x1 y2  y1
одной прямой, если же F>0 или же F<0, то третья точка лежит по одну из сторон от исходной прямой.
Тогда наша рассмотренная ранее задача будет сводиться к следующему: необходимо определить
будут ли лежать точки по разные стороны ото рва, то есть вычислить произведение функций FА* FВ и
если оно отрицательно, то точки расположены по разные стороны ото рва, но при этом необходимо еще
проверить, а будут ли они пересекаться.
(Тесты: А(-3,1), В(5,4) – расстояние 8,54; А(-1,4), В(4,-4) – расстояние 9,43; А(-2,-3), В(2,5) –
расстояние 8,99; А(0,0), В(4,-1) – расстояние 4,12; А(0,5), В(0,-2) – расстояние 7,34).
Рассмотрим теперь, в зависимости от того, по какую сторону от прямой будет лежать точка, какой
знак будет иметь функция F? Для этого рассмотрим вполне определенный пример, а именно, пусть
А(-1,0), В(1,0), а С(0,1). Вычислим F=(0-(-1))(0-0)-(1—0)(1-(-1))=0-2=-2<0, следовательно, получили, что
если точка лежит слева от прямой, то функция имеет отрицательное значение, а если справа, то
соответственно положительный.
Задачи:
1. В городе Глупове транспорт может делать повороты и развороты только на площадях,
причем левые повороты мэр запретил. И поэтому за каждый левый поворот установлен
штраф в размере 50$. Определить количество левых поворотов и размер штрафа, если
известны координаты площадей, через которые проезжает автомобилист.
2. В городе Глупове транспорт может делать повороты и развороты только на площадях,
причем левые повороты мэр запретил. При этом он установил такую систему штрафов, за
первый левый поворот штраф 50$, за каждый последующий на 10% больше предыдущего, но
любой разворот на 180 или проезд через площадь без поворота сбрасывает размер штрафа
опять до 50$.
3. Известны координаты вершин многоугольника в порядке их обхода. Определить является ли
данный многоугольник выпуклым.
4. Известны координаты вершин многоугольника в порядке их обхода. Определить является ли
данный многоугольник выпуклым. При этом если многоугольник является не выпуклым, то
проверить можно ли выбросить одну точка, такую чтобы многоугольник стал выпуклым.
Указать порядковый номер этой точки, ее координаты, а также изобразить исходный и
полученный многоугольники на экране.
Помимо того, что рассмотренная нами с вами функция F позволяет определить взаимное
расположение трех точек, а так же в случае, когда эти точки не лежат на одной прямой, определить
по какую сторону третья точка расположена от прямой, она удобна еще и тем, что модуль значения
этой функции (в случае, когда она не равна нулю) равен двум площадям треугольника, вершины
которого расположены в исходных трех точках, то есть S=1/2|F|.
Задачи:
1. Вычислить площадь произвольного четырехугольника.
2. Вычислить площадь произвольного n-угольника.
Контрольная работа.
Лекции по Turbo Pascal
104
-
Задача: Заданы координаты концов двух отрезков, определить взаимное расположение этих отрезков
(определить лежат они параллельных, совпадающих или пересекающихся прямых, в случае совпадения
прямых определить имеют отрезки общую точку, общую часть или не имеют общих точек, в случае
пересечения прямых определить имеют отрезки общую точку или нет).
Приближенные методы вычислений.
Задача 1. Вычислить приближенное значение суммы
1 + x/1! + x2/2! + x3/3! + …
Считаем, что нужное приближение получено, если вычислена сумма нескольких слагаемых, и
очередное слагаемое оказалось по модулю меньше, чем данное малое положительное число .
Для решения задачи мы должны выполнить следующие действия:
2) получить очередное слагаемое (назовем его а);
3) сравнить абсолютную величину слагаемого а с  и, в зависимости от результата сравнения, либо
продолжить, либо прекратить вычисления.
Program p;
var a: real;
x : real;
 : real;
i : integer;
S : integer;
begin
readln(x, );
i:=1;
a:=1;
S:=0;
WHILE a> DO
begin
S:=S+a; i:=i+1; a:=a*x/i;
end;
writeln(‘приближенное значение суммы=’,S:4:2)
end.
Задача 2. Рассмотрим часто встречающуюся задачу приближенного решения уравнения f(x)=0, где
f(x) – заданная функция. Решить уравнение – значит найти такое значение х*, при котором f(x*)=0.
Поиск решения осуществляется на интервале [a;b], причем f(a)<0, а f(b)>0. Используем метод деления
пополам. Находим точку с=(а+b)/2 – середина отрезка. Если f(c)>0, то границу b изменяем на значение
с, а если f(с)<0, то изменяем а. Процесс продолжаем, пока длина интервала не будет меньше заданной
точности.
Пусть f(x)=x2-2, т.е. мы
попытаемся
найти
значение
Y
квадратного корня из 2.
Program popolam;
f(x)
const eps=1.0E-3;
var a,b,c:real;
Function
eg(x,y:real):boolean;
begin
Eg:=Abs(x-y)<eps
0
a
c
b X
end;
Function F(x:real):real;
begin
F:=Sgr(x)-2
end;
BEGIN
Лекции по Turbo Pascal
105
-
Writeln(‘введите интервал’); readln(a,b);
if F(a)*F(b)>0 then writeln(‘на этом интервале мы не можем
найти решение уравнения’)
else begin
while Not Eg(a,b) do
begin c:=(a+b)/2;
if F(c)>0 then b:=c else a:=c
end;
writeln(‘Результат ’,a)
end;
readln
end.
Можно с помощью этой программы решить уравнения :
x2-6x+5=0 x-cosx=0 x-lnx-2=0 2x3-9x2-60x+1=0
Метод итераций
Пусть нужно решить уравнение f(х)=0, из которого мы получаем уравнение следующего вида:
х=u(х), для решения этого уравнения методом итераций необхдимо составить последовательность
приближений, причем надо учитывать что далеко не каждая последовательность приведет нас к
нахождению корня, необходимым и достаточным условием для использования метода итераций
является u’(x)<1. Итак, для нахождения последовательности выбираем произвольно х0, вплоть до
случайного числа, вычисляем х1=U(х0), х2=U(х1) х3=U(х2) и т.д. опка не будет выполнено неравенство
|хi-xi+1|<e.
Задача 3. Пусть непрерывная положительная на отрезке [a,b] (a<b) функция. Вычислим площадь
фигуры, ограниченную графиком функции f(x), осью х и прямыми х=а и х=b. Для этого разобьем
отрезок [a,b] на n равных отрезков одинаковой длины x=(b-a)/n
Y
a=x0<x1<…<xi<xi+1<….<xn=b
На каждом из отрезков [xi,xi+1] как на основании, построим
прямоугольник с высотой f(xi).
Площадь прямоугольников мы умеем находить. Сумма
площадей всех прямоугольников даст приближенное значение
площади фигуры:
Sприб=(b-a)/n*(f(x0)+….f(xn-1))
0
a x1 x2….....
xn-2
Естественно, что чем мельче будет разбиение, тем точнее мы
xn
X
подсчитаем площадь фигуры.
Для отладки программы возьмем функцию f(x2) на отрезке
[1,2]. Площадь фигуры равна 2,333….
program trapez;
const eps=1.0E-3;
var a,b,s,dx :real;
i,n : integer;
Function eg(x,y:real):boolean;
begin
Eg:=Abs(x-y)<eps
end;
Function F(x:real):real;
begin
F:=Sgr(x)
end;
BEGIN
Writeln(‘введите интервал и число частей для разбивки’); readln(a,b,n);
Лекции по Turbo Pascal
106
-
x:=a; dx:=(b-a)/n; s:=0;
For i:=1 to n-1 do
begin
s:=s+F(x);
x:=x+dx;
end;
writeln(‘Результат = ’,(b-a)/n*s);
readln;
end.
Вычислить площадь криволинейных трапеций для следующих функций:
f(x)=1/(1+x) [0,1]
f(x)=1/x [1,3]
f(x)=sinx [0,/2]
Для вычисления длины дуги воспользуемся тем же разбиением на прямоугольники, с тем лишь
отличием что будем брать сумму длин гипотенуз прямоугольных треугольников… до тех пор пока
разница между предыдущим и текущим значением не будет меньше заданной точности.
Задача 4. Для вычисления элементарных функций в математике широко распространено
представление этих функций в виде некоторых бесконечных сумм. Не вдаваясь в обоснование таких
представлений, приведем некоторые их них :
ex=1 + x + x2/2! + x3/3! + … + xn/n! + …
sinx=x – x3/3! + x5/5! – x7/7! +…+ (-1)nx2n-1/(2n+1)! +….
cosx= 1 – x2/2! + x4/4! – x6/6! +…+ (-1)nx2n/(2n)! +….
ln(1+x)=x – x2/2 + x3/3 – x4/4 + …+ (-1)n+1xn/n + ….. (-1<x<=1)
В каждом из разложений точность представления функции будет, вообще говоря, тем выше, чем
больше взято слагаемых в сумме. Причем значения самих слагаемых с ростом n стремятся к нулю. Для
вычисления значений функции с некоторой заданной точностью  поступают следующим образом.
Вычисляют и суммируют слагаемые до тех тор, пока очередное слагаемое не станет по абсолютной
величине меньше  или абсолютное значение разности между соседними слагаемыми не станет меньше
. Полученную сумму и принимают за приближенное значение функции.
Вычисли функцию sinx.
Program rad;
const eps=1.0E-3;
var x,sn,ss : real;
p, n : integer;
{p – используется для чередования знака слагаемого}
Function Eg(x,y;real):boolean;
begin
Eg:=Abs(x-y)<eps
end;
Function F(n:integer;var x:real):real;
var i:integer;
s:longint;
begin
s:=1;
for i:=2 to n do s:=s*i;
x:=x*sqr(x); F:=x/s
end;
BEGIN
writeln(‘Введите значение х’);
readln(x);
ss:=0; sn:=x; n:=1; p:=1;
Repeat
ss:=sn; {предыдущее значение слагаемого}
Лекции по Turbo Pascal
107
-
{ новое значение слагаемого}
n:=n+2; p:=-1*p; sn:=ss+p*F(n,x)
Until Eq(ss,sn) or (n>=12);
Writeln(‘Результат=’,sn); readln
end.
Задача 5. Метод Монте-Карло для приближенного вычисления площади.
Пусть есть какая-нибудь фигура на плоскости, расположенная внутри стандартного квадрата со
сторонами параллельными координатным осям.
Пусть про любую точку квадрата мы можем быстро узнать, попадает ли эта точка внутрь фигуры или
нет.
Для выбора точек используют случайные числа Random(x)
Если вызвать функцию много раз подряд, то множество полученных чисел будет равномерно
распределено по отрезку [0,a]
Program ss;
var n: integer; {количество точек}
a : integer; {длина стороны квадрата}
m, i : integer;
x,y : real;
begin
writeln(‘введите кол-во точек и сторону квадрата’);
readln(n,a);
m:=0;
for i:=1 to n do
begin
x:=Rondom(a); y:=Random(a);
if точка(x,y) внутри квадрата then m:=m+1
end;
S:=(m/n)*a*a
writeln(‘Результат ’,s);
end.
11 класс.
Множества.
Множество в Паскале представляет собой набор различных элементов одного (базового) типа.
Базовый тип – это совокупность всех возможных элементов множества. Всего в базовом типе должно
быть не более 256 различных элементов. Значение переменной множественного типа может содержать
любое количество различных элементов базового типа – от нуля элементов (пустое множество) до всех
возможных значений базового типа
Множества, используемые в программе, могут быть описаны либо в разделе Type:
Type <имя типа> = Set Of <тип элементов>;
Var <имя множества> : <имя типа>;
Либо непосредственно в разделе описания переменных Var:
Var <имя множества> : Set Of <тип элементов>;
Пример.
Type mnog_Char=Set Of Char;
Var mn1 : Set Of Char;
mn2 : mnog_Char;
mn3 : Set Of ‘A’..’Z’;
s1 : Set Of Byte;
Лекции по Turbo Pascal
108
-
s2 : Set Of 1000..1200;
Здесь mn1 и mn2 – это множества символов; так как различных символов всего 256, то тип Char
можно использовать в качестве базового;
mn3 – множество больших латинских букв;
s1 – множество целых чисел (от 0 до 255); так как тип Byte содержит только целые числа от 0 до 255,
его тоже можно использовать в качестве базового типа элементов;
s2 – множество целых чисел от 1000 до 1200.
Формирование (конструирование) множеств. В программе элементы множества задаются в
квадратных скобках, через запятую. Если элементы идут подряд друг за другом, то можно использовать
диапазон.
Пример Type digit = Set Of 1..5;
Var s : digit;
Переменная s может принимать значения, состоящие из любой совокупности целых чисел от 1 до 5;
[ ] - пустое множество;
[1], [2], [3], [4], [5] – одноэлементные множества;
[1,2], [1,3], …., [2,4], [4,5] – двухэлементные множества (пара любых элементов);
[1,2,3], [1,2,4], … , [3,4,5] - трехэлементные (тройка элементов);
[1,2,3,4], [1,2,3,5], [1,2,4,5], [1,3,4,5], [2,3,4,5] - четырехэлементные;
[1,2,3,4,5] – полное множество (взяты все элементы базового типа).
Операции над множествами
Объединение двух данных множеств называется множество элементов, принадлежащих хотя бы
одному из этих множеств. Знак операции объединения множеств - «+».
A
B
A+B
Примеры
1) [‘A’, ‘F’] + [‘B’, ‘D’] = [‘A’, ‘F’, ‘B’, ‘D’];
2) [1..3, 5, 7, 11] + [3..8, 10, 12, 15..20] = [1..8, 10..12, 15..20]
Пусть S1:=[1..5, 9], a S2:=[3..7, 12]. Тогда если S:=S1 + S2,
то S=[1..7, 9, 12].
Пусть А1:=[‘a’..’z’]; A1:=A1 = [‘A’]. Тогда A1=[‘A’, ‘a’..’z’].
Пересечением двух множеств называется множество элементов, принадлежащих одновременно и
первому, и второму множеству. Знак операции пересечения - «*».
А
B
A*B
Примеры.
3. [‘A’, ‘F’] * [‘B’, ‘D’] = [ ] , так как общих элементов нет;
2) [1..3, 5, 7, 11] * [3..8, 10, 12, 15..20] = [3, 5, 7];
3) если S1:=[1..5, 9] и S2:=[3..7, 12], a S:=S1 * S2, то S=[3..5].
Разностью двух множеств называется множество, состоящее из тех элементов первого множества,
которые не являются элементами второго. Знак операций вычитания множеств - «»
A
B
A-B
Примеры.
[‘A’, ‘F’] – [‘B’, ‘D’] = [‘A’, ’F’ ] , так как общих элементов нет;
[1..3, 5, 7, 11] – [3..8, 10, 12, 15..20] = [1, 2, 11];
если S1:=[1..5, 9] и S2:=[3..7, 12], a S:=S1 – S2, то S=[1, 2, 9];
A1:=[‘A’..’Z’]; A1:=A1 – [‘A’]. Тогда А1=[‘B’..’Z’].
Лекции по Turbo Pascal
109
-
Операция определения принадлежности
элемента множеству
Эта логическая операция обозначается служебным словом in. Результат операции имеет значение
true, если элемент входит в множество, и false в противном случае.
Примеры.
4. Выражение 5 in [3..7] имеет значение true, так как 5  [3;7]
Выражение ‘a’ in [‘A’..’Z’] имеет значение false, так как маленькой латинской буквы «а» нет среди
больших латинских букв.
Сравнение множеств
Для сравнения множеств используются операции отношения:
= - проверка на равенство (совпадение) двух множеств;
<> - проверка на неравенство двух множеств;
<=, < - проверка на вхождение первого множества во второе множество;
>=, > - проверка на вхождение второго множества в первое множество.
Первое множество меньше или равно второму (AB)
B
A
B
A
B
true
false
Первое множество меньше второго (A<B)
A
true
B
B
A
B
A
A
true
false
false
Пример. Составить программу выделения следующих множеств из множества целых чисел от 1 до 30
:
- множества чисел, кратных 2;
- множества чисел, кратных 3;
- множества чисел, кратных 6;
- множества чисел, кратных 2 или 3;
Вопросы для обсуждения :
1. Сколько множеств надо описать? (Каков тип их элементов? (четыре множества с элементами типа
Byte).
2. Каково начальное значение множеств ? (начальное значение множеств – пустое множество).
3. Как формируются множества? (Первые два формируются перебором всех чисел данного
промежутка и отбором подходящих, а третье и четвертое получаются из первых двух путем применения
операции пересечения или объединения).
4. Как осуществить вывод сформированных множеств? (Вывод множеств производится ТОЛЬКО
поэлементно, поэтому удобно составить процедуру и передавать в нее множество, элементы которого и
будут выводить на экран. Для этого в разделе типов надо создать соответствующий тип и использовать
его в дальнейшем).
Program mnog;
const n=30;
type mn=Set Of 1..n;
var n2, n3, n6, n23 : mn;
k : integer;
procedure print(m: mn);
var i: integer;
begin
for i:=1 to n do if i In m then write(i:3);
Лекции по Turbo Pascal
110
-
writeln;
end;
BEGIN
n2=[ ]; n3=[ ];
for k:=1 to n do
begin
{если число делится на 2, то заносим его в n2 }
if k Mod 2 = 0 Then n2:=n2+[k];
{если число делится на 3, то заносим его в n3 }
if k Mod 3 = 0 Then n3:=n3+[k];
end;
{числа, кратные 6, - это те, которые кратны и 2 и 3, поэтому это пересечение двух множеств, а числа,
кратные 2 или 3, - это объединение этих же множеств}
n6:=n2*n3; n23:=n2+n3;
writeln(‘числа, кратные 2’); print(n2);
writeln(‘числа, кратные 3’); print(n3);
writeln(‘числа, кратные 6’); print(n6);
writeln(‘числа, кратные 2 или 3’); print(n23);
END.
Пример 2. Если взять то общее, что есть у боба с ложкой, добавить кота и поместить в тепло, то
получится муравей. Так ли это ?
program bob;
var y1, y2, y3, y4, x : Set Of Char;
s : Char;
BEGIN
y1:=[‘б’, ‘о’, ‘б’]; y2:=[‘л’, ‘о’, ‘ж’, ‘к’, ‘а’];
y3:=[‘к’, ‘о’, ‘т’]; y4:=[‘т’, ‘е’, ‘п’, ‘л’, ‘о’];
x:=(y1*y2) + y3 – y4;
writeln(‘множество х’);
for s:=’a’ to ‘я’ do if s In x then write(s); writeln;
{проверка: состоит ли муравей из кота}
if y3<=x then write(‘муравей состоит из кота’)
else write(‘муравей не состоит из кота’);
END.
Пример 3. Дан ребус
МУХА + МУХА = СЛОН
Каждой букве соответствует некоторая цифра, разным буквам соответствуют разные цифры.
Необходимо заменить буквы цифрами так, чтобы получить верное равенство.
Для решения этой задачи применим метод перебора с возвратом. Используем множество S1 для
хранения цифр слова МУХА, причем будем заносить в него цифры последовательно, учитывая уже
внесенные цифры. Начальное значение S1 – пустое множество. После выбора всех цифр первого слова
формируем соответствующее число и находим число, соответствующее слову СЛОН. Выделяем цифры
СЛОНа (множество S2), и если слова состоят из различных цифр (то есть пересечение S1 и S2 пустое) и
все цифры СЛОНа разные, то выводим решение на экран. Далее удаляем из множества S1 последнюю
внесенную цифру и пытаемся выбрать еще одно ее значение. Таким образом, мы перебираем все
возможные варианты и выводим на экран только те, которые удовлетворяют равенству.
Заметим, что букве «М» в слове МУХА может соответствовать цифра от 1 до 4, а букве «А» в этом
же слове не может соответствовать 0.
Program myxa;
type mn=Set Of 0..9;
var m, y, x, a : 0..9; {цифры числа МУХА}
n1, n2 : integer; {числа МУХА и СЛОН}
Лекции по Turbo Pascal
111
-
a1, a2, a3, a4 : 0..9; {цифры числа СЛОН}
S1, S2 :mn;
procedure Print(x,y:integer); {вывод решения в виде ребуса }
begin
writeln(x:5);
writeln(‘+’);
writeln(x:5);
writeln(‘____’);
writeln(y:5);
end;
BEGIN
s1:=[ ]; s2:= [ ];
for m:=1 to 4 do
begin
s1:=s1+[m]; { заносим первую использованную цифру}
for y:=0 to 9 do {если это цифра не была еще взята, то добавляем ее во множество цифр числа
МУХА и выбираем цифру для следующей буквы }
if Not (y In s1)
then begin s1:=s1+[y];
for x:=0 to 9 do
if Not (x In s1)
then begin s1:=s1+x;
for a:=1 to 9 do
if Not (a In s1)
then begin s1:=s1+[a];
n1:=1000*m+100*y+10*x+a;
n2:=2*n1;
a1:=n2 div 1000;
a2:=n2 div 100 mod 10;
a3:=n2 div 10 mod 10;
a4:=n2 mod 10;
s2:=[a1,a2,a3,a4];
if (s1*s2=[]) and ([a1]*[a2]*[a3]*a[4]=[])
then Print(n1,n2);
s1:=s1-[a];
end;
s1:=s1-[x];
end;
s1:=s1-[y];
end;
s1:=s1-[m];
end;
END.
Задачи:
14.1 Дана непустая последовательность символов. Построить и напечатать множества, элементами
которых являются встречающиеся в тексте:
 цифры от ‘0’ до ‘9’ и знаки арифметических операций;
 буквы от ‘A’ до ‘F’ и от ‘X’ до ‘Z’;
 знаки препинания и буквы от ‘E’ до ‘N’.
14.2 Вывести в алфавитном порядке элементы множества, составленного из произвольных букв от ‘A’
….’Z’.
14.3 Составить программу печати в возрастающем порядке всех цифр, входящих в десятичную запись
данного числа..
Лекции по Turbo Pascal
112
-
Дан текст. Вывести в алфавитном порядке все буквы текста, входящих в него : а) не менее двух
раз; б)не более двух раз; в) более двух раз.
14.5 Дан текст. Подсчитать количество строчных и прописных букв.
14.6 Составить программу подсчета общего количества цифр и знаков ‘+’, ‘-‘, ‘*’ в строке s, введенной
с клавиатуры.
14.7 Задано множество вычислительных машин. Известен набор машин, имеющих в каждом из 10
техникумов. Построить и распечатать множества, включающие в себя вычислительные машины :
а) которыми обеспечены все техникумы;
б) которые имеет хотя бы один техникум;
в) которых нет ни в одном техникуме.
14.8 Составить программу формирования множества строчных латинских букв, входящих в строку,
введенную с клавиатуры, и подсчета количества знаков препинания в ней.
14.9 Написать программы решения ребусов :
а) ЛОБ + ТРИ = САМ,
б) ИСК + ИСК = КСИ,
в) ТОЧКА + КРУГ = КОНУС
г) VOLVO + FIAT = MOTOR,
д) АВ + ВС + СА = АВС.
14.10 Дана не пустая последовательность символов. Напечатать количество вхождений в данную
последовательность заглавных латинских букв ‘A’, ‘B’, ‘C’.
14.11 Вывести на экран все простые числа от 11 до 101.
14.4
Создание меню.
Меню бывает линейное и вложенное, горизонтальное и вертикальное, причем вложенное меню
создают горизонтальным. Для организации линейного меню необходимо вывести имена каждого меню
на экран, причем первое выделив каким нибудь образом. При нажатии стрелок влево или вправо
происходит смещение выделения с одного раздела меню на другое, то есть с того которое было
выделено снимается подсветка, а следующее (предыдущее) подсвечивается, если стрелка была нажата
на конечном меню, то необходимо с него снять а подсветить либо первое, либо последнее. При нажатии
клавиши Home – подсвечивается первый раздел меню, End – последний, при нажатии Esc – происходит
выход из программы. При нажатии клавиши Enter происходит выполнение действия которое указано в
меню.
Задача: Составить программу для организации функционирования следующего меню:
1 число
2 число
сложение
вычитание
умножение
деление
результат
При выборе первых двух пунктов появляется экран на котором запрашивается значения
соответсвенно первого или второго чисел, при выборе 3, 4, 5 или 6 пунктов выдается сообщение что
соответсвующее дейсвтие выполнено, но полученное значение не выводится. При этом необходимо
отслеживать введены ли оба числа, если не хватает хотя бы одног нужно выдать сообщения вида: «Не
хватает данных». При выборе меню результат нужно вывести результат выполнения последнего
действия, если действий не было совершено то нужно об этом сказать.
Для организации линейного меню необходимо пользоваться одномерным массивом.
При организации вложенного меню необходимо использовать двухмерный массив, но и учесть еще
следующие моменты, во-первых, при выборе одного из пунктов основного меню открывается панель
подменю и уже выбор одного из подпунктов будет приводить к выполнению орпеделнного действия.
При нажатии стрелочки в сторону при открытом подменю, оно закрывается, а открывается то в сторону
которого была нажата стрелка.
Работа с мышью
Для того чтобы добавить в прорамму курсор мыши и организовать с ним работу, необходимо
подключить модуль mouse. При этом в текстовом режиме курсор будет выглядеть в виде
прямоугольника (размерами 8х8, при этом указывается координаты верхнего левого угла), а в
графическом в виде стрелки.
Для того чтобы на экране появился курсор мыши необходимо запустить процедуру mouseshow. Для
отключения изображения курсора выполняется процедура mousehide. Это необходимо делать из-за того,
Лекции по Turbo Pascal
113
-
что при выводе на экран в точку, где изображен курсор, может происходить несколько не приятные
искажения игуры или числа (т.к. в графическом режиме точки закрытые курсором закрашены не будут).
Для организации действий по желчку мыши необходимо использовать процедуру mouseread(x,y,b);
где х и у – это координаты указателя (в графическом режиме размер 640х200), а b – информация о
нажатой клавише мыши, все три параметра должны иметь тип word. Варианты значений параметра b: 0
– клавиша не была нажата; 1 – была нажата левая клавиша мыши; 2 – была нажата правая клавиша
мыши; 3 – были нажаты одновременно левая и правая клавиши мыши (либо средняя).
Приведем фрагмент программы выполнение которой приведет к тому что по щелчку левой клавиши
мыши на экране в левом верхнем углу будут отображаться сведения о координатах нахождения курсора
мыши.
Для графического режима:
mouseshow;
repeat
mouseread(x,y,b);
if b=1 then begin
delay(100);
setfillstile(1,0);
bar(0,0,60,10);
str(x,xg); str(y,yg);
outtextxy(1,1,xg);
outtextxy(30,1,yg);
end;
until b=2;
Ниже приведен фрагмент программы который отображает в верхнем левом углу сведения о
координатах курсора мыши соответсвующие его местоположению на экране.
Для текстового режима:
mouseshow;
repeat
mouseread(x,y,b);
gotoxy(1,1);
write(x:3,y:5);
xt:=x div 8+1;
yt:=y div 8+1;
gotoxy(1,2);
write(xt:3,yt:5);
until b=2;
Задачи:
1. Изображение звездочки в точке нажатия клавиши мыши.
2. Создать модель пианино. Изображение клавиш при щелчке, по которым происходит звук
соотвествующий нажатой ноте.
3. Дана панель содержащая буквы алфавита, а также кнопку очистки экрана. при щелчке по
букве происходит ее выделение, при двойном щелчке выделение снимается, при щелчке по
другой букве с предыдущей выделение снимается а выделяется та по которой произвели
щелчок. При выделенной букве и при щелчке в любом месте экрана кроме панели появляется
изображение этой буквы на экране там где произвели щелчок. Щелчок по кнопке очистка
приводит к тому, что очищается весь экран за исключением панели.
4. Аналогично третьей задаче только происходит перетаскивание букв на экран.
Самостоятельная работа.
Создать модель мозаики.
Работа с графическими файлами.
Паскаль позволяет осуществлять работу с графическими файлами созданными в других программах,
например в CPENе (размер полученого файла 640х350), при этом нужно следить чтобы созданные
файлы были сохранены в формате .pcx.
Лекции по Turbo Pascal
114
-
Для работы с файлами формата .pcx необходимо подключить модуль pcxfile.
Для работы с графическими файлами используют следующие функции: функция считывания
изображения из файла pcxread(x,y,name,page):word. x,y – координаты верхнего левого угла файла с
которых начинается считывание (в основном 0,0), name – имя файла с рисунком, page – номер страницы
на которую будем считывать данный файл (при низком разрешении экрана можно создавать четыре
страницы: 0, 1, 2, 3; при среднем разрешении экрана таких старниц уже только две: 0, 1; ну а при
высоком разрешении экрана только одна 0).
Если необходимо сохранить файл созданный средствами паскаля в файл с расширением .pcx, то это
можно сделать с помощью функции pcxwrite(x1,y1,x2,y2,name,page):word.
Лекции по Turbo Pascal
Download