Как работать с книгой
Внимательно прочитайте соответствующий раздел теории (одну главу), разберите все примеры, чтобы вам все было понятно, при этом, если у вас есть компьютер, наберите программы и запустите их на выполнение. Убедитесь в правильности полученных результатов. Для того чтобы изучить действие того или иного оператора в программе или фрагмента программы, можно "удалить" фрагмент, заключив его в комментарные скобки { фрагмент .... }. можно, наоборот, добавить в программу операторы writeln, readln
для того, чтобы посмотреть промежуточные результаты. Экспериментируйте – это поможет вам в усвоении материала.
Если у вас нет компьютера, будьте сами "компьютером" и "выполняйте" операторы, записывая на листе бумаги результаты. Это поможет понять вам их работу.
Изучив материал, определите свой вариант и напишите соответствующую программу, проверьте ее на компьютере (или без него). Оформите отчет, сдайте на проверку преподавателю.
Если вы будете внимательно разбирать тексты программ, затем, заучив текст, попробуете его написать по памяти, проверить, исправить ошибки, запустить на компьютере, получить результаты, то вы научитесь программировать!
Помните: "не боги горшки обжигают!
"
Удачи вам!
Автор.
1. Предварительные сведения
Смысл программирования состоит в том, что программист должен объяснить ЭВМ, какие действия машина должна выполнить, чтобы решить нужную задачу. Это объяснение должно быть сформулировано на доступном для ЭВМ языке и содержать указания, какие величины будут исходными для решения задачи, какие операции и в какой последовательности необходимо выполнить над входными величинами, чтобы получить результат и, наконец, в каком виде выдать результат. Алгоритм, записанный в терминах языка, понятного ЭВМ, называется программой.
Программа на языке Паскаль состоит из "заголовка" и "тела" программы, называемым блоком. В "заголовке" программы даётся имя и перечисляются её параметры (если это необходимо). Блок состоит из шести разделов, причем любой из них, кроме последнего, может быть пустым (т.е. отсутствовать). В определении блока разделы должны следовать в таком порядке: описание меток, определение констант, определение типов, описание переменных, описание процедур и функций, операторы.
1.1. Алфавит
Для написания программ на языке Паскаль можно применять следующие символы: буквы латинского алфавита a b c d...z
(прописные), a b c d...z
(строчные), знак подчеркивания. Прописные и строчные буквы взаимозаменяемы (эквивалентны) и используются для более рельефного написания программ;
– цифры 0 1 2 3 4 5 6 7 8 9
;
– специальные знаки: + – * / = < > [ ] . , ( ) : ; ^ { } $ # @
;
– составные знаки :< = > = .. ( * * ) ( .. )
.
Используя символы алфавита, мы можем записать алгоритм решения задачи на языке Паскаль. Следует отметить, что кроме приведенных выше символов в программе можно применять и буквы кириллицы, т.е. русский алфавит, однако в конструкциях языка эти буквы не могут быть использованы, они используются только для написания текстовых констант, соответствующих данным строкового типа, например: 'табл. 1'.
1.2. Решение задач
В первом приближении решение задачи на ЭВМ сводится: к вводу некоторых исходных данных в память машины и обработке их по заданному алгоритму; получению и выдаче пользователю результатов решения задачи в виде чисел, текстов, графиков таблиц и т.п. Алгоритм является перечнем тех действий, которые должна выполнять ЭВМ для получения результата. Ввод данных может производиться с различных устройств: с клавиатуры, канала связи, сканера (ввод текстов и рисунков),манипулятора типа "мышь”, “джойстик" и т.д.
Вывод осуществляется на устройства отображения – экран монитора, печатающее устройство, графопостроитель и т.д.
Вначале в ЭВМ вводится программа, содержащая описания исходных данных, перечня операторов, которые определяют порядок обработки этих данных и их преобразование в результаты (алгоритм).
Порядок решения задач:
1. Осмысливание природы задачи, определение исходных и выходных данных, а также формы выходных данных (чисел, текстов, рисунков, графиков, таблиц). Подбор или разработка математических методов преобразования исходных данных в выходные результаты.
2. Разработка алгоритма решения задачи. Здесь возможно описание алгоритма в любой удобной форме: либо в виде словесного описания с включением формул, либо в виде блок-схем, что особенно наглядно и удобно. например, блок-схема алгоритма, исследующего квадратное уравнение ax2
+bx+c=0, показана на рис. 2.1.
3. Запись алгоритма с помощью средств алгоритмического языка Паскаль (написание программы).
4. Ввод программы в ЭВМ.
5. Компиляция программы, т.е. перевод алгоритма из терминов языка Паскаль во внутренний язык ЭВМ, поскольку алгоритмических языков – множество, а внутренний язык ЭВМ – один.
6. выполнение программы на ЭВМ: если она написана без ошибок, то на этом этапе ЭВМ, встретив оператор ввода исходных данных, запросит конкретные исходные данные для решения задачи, пользователь введет эти данные, машина их обработает и выдаст результат.
Не всегда решение получается с первого раза. Программа может содержать ошибки (неправильная запись операторов – синтаксические ошибки; не тот тип выделенных ячеек памяти, что вводимые данные, путаница в алгоритме; полученные данные не совпадают с результатами контрольного просчета и т.д.). В этом случае необходим процесс отладки программ и поиск ошибок. В Паскале имеется мощный отладчик, и ЭВМ может значительно помочь пользователю в поиске ошибок.
2. Простейшие программы
2.1. Оператор присваивания
Идентификатор: = выражение
. Здесь идентификатор – имя переменной, переменная хранится в ячейке памяти с именем – идентификатор. тип ячейки памяти определен в разделе описаний. Выражение может быть арифметическим, логическим или каким-либо другим, в котором уже известны (определены) все входящие в его состав идентификаторы.
Замечание 1.
Тип значения выражения и тип идентификатора должны совпадать, иначе error - ошибка.
Замечание 2.
При наличии хотя бы одной ошибки программа не выполняется.
Пример.
Пусть имеются ячейки памяти с именами a, b, c; ячейки таковы, что в них могут быть помещены величины только целого типа. достигается это описанием: Var a, d, c: integer,
где Var
- начало раздела описания переменных, a, b, c
- идентификаторы. Integer
означает целый, т.е. в разделе Var идентификаторы (имена) переменных определены как целые.
Работа описания: встретив такое описание, ЭВМ выдаёт три ячейки памяти с именами a
, b
, c
, причем такие, чтобы туда могли быть помещены целые числа. Запишем оператор присваивания:
a
: =
c
+
b
;
Работа оператора: машина должна иметь описание идентификаторов a, b, c
.
кроме того, как сказано выше, в правой части оператора стоят величины, которым уже присвоены начальные значения. В этом случае машина извлечет из ячейки с
её содержимое и из ячейки b
содержимое, произведет операцию сложения и значение результата занесёт (присвоит) в ячейку a
.
2.2. комментарии
Введем понятие комментария. Комментарий – это всё, что заключено между скобками { }. Символы, заключенные между этими скобками, не воспринимаются машиной, но выдаются пользователю. Комментарии используются пользователем для объяснения алгоритма.
2.3. Программа
Напишем программу вычисления a = c+b
. Программа начинается с заголовка Program
– имя программы; затем идут разделы описаний (до 5) и раздел операторов, который начинается словом Begin
и заканчивается END.
(end с точкой, точка – конец программы). Каждое описание и оператор заканчиваются символом ';'
Program Prim1; {заголовок программы}
Var a,b,c:integer; {раздел описания переменных, выделение}
{ячеек памяти для хранения целых величин}
BEGIN {начало раздела операторов}
c:=547; b:=42; {занесение в ячейки c и b начальных значений}
a:=c+b; {вычисление значения и выдача на}
writeln(a); {экран (write - писать) значения a}
END. {конец программы}.
Напоминаем, что тексты, заключённые в скобки { }, являются комментариями, не являются частью программы и могут быть опущены, таким образом, программа для ЭВМ имеет следующий вид:
Program Prim1;
Var
a,b,c:integer;
BEGIN
c:=547; b:=42;
a:=c+b;
writeln
(
a
);
readln
;
END.
Программа записывается в виде строк. Максимальная длина строки 255 символов, но не стоит делать строки длиннее строки экрана – 80 символов, иначе строки будут "прятаться" за пределами окна экрана , хотя строки и можно просмотреть, передвигая "окно" (рис. 2.2).
"Хорошее" расположение строк "Плохое" расположение строк
рис. 2.2
Каждую строку можно начинать не с первой позиции, чтобы программа была более читаемой.
2.4. Простейший ввод-вывод
В программе Prim1
мы задавали исходные данные с помощью оператора присваивания, что не всегда удобно, если одну и ту же программу нужно просчитывать с различными исходными данными. Для присвоения начальных значений можно использовать оператор readln
(идентификатор, идентификатор,...,идентификатор); например, readln (c,b)
. встретив такой оператор, машина остановится и будет ждать, пока пользователь не наберет на клавиатуре значение с,
нажмет клавишу "пробел”, наберет значение b
и нажмет клавишу ENTER
(ввод).значения величин c
и b
отобразятся на экране и после нажатия клавиши ENTER
занесутся в ячейки памяти машины с именами с
и b
соответственно. тогда программа Prim1
примет вид:
Program Prim1a;
Var a, b, c : integer;
BEGIN readln (c,b);
a : = c+b;
writeln (a);
readln ;
END.
Замечание
1.
Напомним, что машине безразлично, строчные или прописные буквы одинаковых слов end
, end
и end
(но не для вас).
Замечание 2
. Удобно ставить Readln
перед END,
так как после выполнения программы машина выдаёт на экран окно текста программы, а результат "прячется" за этим окном и, чтобы его посмотреть, необходимо убрать окно с программой с помощью нажатия клавиш. Если перед END
имеется Readln
, то программа не завершит работу, пока вы не нажмете клавишу ENTER
, т.е. в данном случае на экран будет выведено значение а
. Вы посмотрите результат и нажмете ENTER
для входа в редактор языка Паскаль.
2.5. Арифметические выражения
Арифметическое выражение строится из объектов: арифметических (числовых) констант; идентификаторов переменных, описанных как числовые; функций, которые возвращают в результате их вычисления; арифметических значений этих объектов, соединённых между собой знаками арифметических операций и круглыми скобками. В качестве констант могут применяться арифметические константы, заданные в явном виде: 5; 5.35, -7.374 Е + 01 и т.п., а также имена констант, определённые в разделе const
.
В качестве переменных используются переменные, определённые в разделе Var
как byte
, integer, real,
и их разновидности, например, longinteger,
и т.д., если им уже присвоены начальные значения.
В качестве функций могут применяться стандартные функции языка Паскаль, библиотечные функции и функции, написанные самим пользователем. Библиотечные функции доступны после подключения модулей библиотек. функции пользователя должны быть описаны в разделе function
.
Основные стандартные функции Паскаля:
Обозначения: I
– целочисленный тип; B
– байтовый тип; R
– вещественный тип; IBR
– целочисленный, или байтовый, или вещественный типы.
ABS (IBR)
– определение абсолютной величины аргумента типа i,b,r
.
ARCTAN (IBR)
– вычисление угла (в радианах), тангенс которого равен IBR
.
Cos
(
IBR
) ,
Sin
(
IBR
)
.
Exp (IBR)
– вычисление значения eIBR
.
Ln (IBR)
– натуральный логарифм IBR.Sgr (IBR)
– возведение в квадрат IBR
.
Sgrt (IBR)
– вычисление корня квадратного из IBR
.
Возведение в степень выполняется по формуле ar= exp (r *ln(a))
для положительных a
либо организуется последовательное умножение на а
r раз.Для отрицательных а
возможен только второй способ.
Арифметические операции: +
, –
, *
– умножить; /
– разделить; mod –
нахождение остатка от деления: 11 mod 5, результат1
; div
– целочисленное деление (дробная часть отбрасывается) 11 div 5, результат 2
. Арифметические "и" – аnd
и "или" – or
производят поразрядное булевское умножение или сложение целых значений операндов согласно таблицам:
A аnd B A or B
0 аnd 0 = 0 0 or 0 = 0
1 аnd 0 = 0 1 or 0 = 1
0 аnd 1 = 0 0 or 1 = 1
1 аnd 1 = 1 1 or 1 = 1
Пример: a: = 12 ; b: = 27.
Во внутреннем коде машины, в двоично-десятичной системе, цифры представляются в десятичной системе:
0000 = ноль
0001 = один
0010 = два
0011 = три
0100 = четыре
0101 = пять
0110 = шесть
0111 = семь
1000 = восемь
1001 = девять
Тогда 12 в десятичной системе эквивалентно 0001 0010 двоично-десятичной системы. напомним, что в двоично-десятичной системе каждая десятичная цифра представлена 4-значным двоичным кодом этой цифры. В этом случае 27 - 0010 0111.
А аnd B А or B
0001 0010 0001 0010
0010 0111 0010 0111
результат: 0000 0010 результат: 0011 0111
Результат преобразуется в десятичную форму 2 и 37 соответственно.
ХOR, исключающее "или", производит операцию согласно таблице
A xor B
1 xor 1 = 0
1 xor 0 = 0
0 xor 1 = 1
0 xor 0 = 0
Результат преобразуется в десятичную форму.
Циклический сдвиг: k shl N - сдвиг числа к влево на N позиций,
k shr N - сдвиг числа к вправо на N позиций,
k и N - целые.
Пример: 2 shl 7 = 256
0000 0000 0000 0010
0000 0001 0000 0000
0 единиц
0 двоек
0 четверок
0 восьмерок
0 шестнадцать
0 тридцать два
0 шестьдесят четыре
0 сто двадцать восемь
1 двести пятьдесят шесть
Пояснение: в любой позиционной системе счисления на первом месте справа в числе стоит количество оснований системы счисения в степени 0, на втором месте справа – количество оснований в степени 1, на третьем месте справа – количество оснований в степени 2 и т.д. так, для десятичной системы имеем:
3 2 4
количество единиц 100 * 4 = 4
количество десятков 101 * 2 = 20
количество сотен 102 * 3 = 300
сложим = 324
Для двоичной системы:
1 0 1 1 0 0 1
количество единиц 20 * 1 = 1
количество двоек 21 * 0 = 0
количество четверок 22 * 0 = 0
количество восьмерок 23 * 1 = 8
количество шестнадцаток 24 * 1 = 16
количество тридцать вторых 25 * 1 = 0
количество шестьдесят четверок 26 * 1 = 64
сложим = 89
т.е. десятичное 89 имеет изображение 1011001 в двоичной системе.
Для правильного написания арифметических выражений необходимо соблюдать следующие правила:
1. Запрещено последовательное появление знаков двух операций, т.е.
A + - B – неверно, A + (-B) – верно.
2. Порядок выполнения операций: /,,div, mod, and, or, shl, shr, –, +
. Порядок может быть нарушен круглыми скобками, так как часть выражения, заключённая в круглые скобки, выполняется в первую очередь.
3. Если операции имеют одинаковый приоритет, то они выполняются последовательно.
4. Унарная операция имеет самый низкий приоритет, поэтому –A
*
b
интерпретируется как –(A
*
b)
.
5. Не следует записывать выражения, не имеющие арифметического смысла, например, деление на выражение, равное 0.
6. Следует помнить, что операции /
и *
имеют одинаковый приоритет, например, 18/2
*
3=27
, а не 3. чтобы было 3, необходимо записать 18/(2
*
3)
.
2.6. Описания переменных.
Описания переменных зависят от типа данных, которые будут храниться в ячейках памяти, названных именами этих переменных.
Данные в Паскале могут быть следующих типов:
Данные
Скалярные Структурированные
массивы записи
Стандартные Определённые
пользователем строки файлы
целые логические интервальные множества
вещественные перечисляемые указатели
байтовые символьные
Каждому типу данных могут соответствовать константы. Количество элементов констант (цифр, букв) сильно зависит от конкретной конфигурации машины. Однако можно сказать, что для целого типа числа максимальное значение 32767, для вещественных, как минимум, – до 7 цифр мантиссы, для строковых – 255 символов и т.д.
Константы байтового типа – целые числа в диапазоне 0 – 255. Целые константы – набор цифр, возможно, со знаком ¢+¢ или ¢–¢. Вещественные константы могут записываться в двух формах – с фиксированной точкой: 57.34;
-256.758 и с плавающей точкой: 5.734е+01 (эквивалент 57.34) и -2.56758е+02
(эквивалент -256.758).
Логических (булевских) констант всего две: TRUE и FALSE. принято, что в машинном коде TRUE=1, FALSE=0. знаковые константы представляют все символы алфавита плюс символы кириллицы, но не для того, чтобы символ стал константой, его нужно заключить в апострофы: ¢А¢, ¢1¢, ¢+¢, ¢?¢ и т.д. Константы могут храниться в ячейках памяти, определенных какими-либо именами (идентификаторами).
Идентификатор – набор букв и цифр, первая из них – всегда буква, например А, ALP1, B2, GAMMA. Идентификаторы могут быть длиной до 255 символов, однако большинство компиляторов накладывает ограничение, т.е. длина имени не должна превышать восьми символов. Идентификатор в своем составе может содержать знак ¢_¢ (подчерк).
Переменные могут быть описаны в разделе описания переменных Var
. разделов описания может быть до пяти, лучше их располагать в следующем порядке: Label
,
Const
,
Type
,
Var
,
functuon
иprocedure
.
Если данное будет изменяться (по величине) в процессе выполнения программы, то имя этого данного описывается в разделе Var
с соответствующим атрибутом:
Байтовый тип – byte
;
Целый тип – integer
;
Вещественный тип – real
;
Булевский тип – boolean
;
Символьный тип – char
и т.д.
Пример:
Var
k n:integer;
S,T,Z: char;
a,b,c: real;
L25,L3: boolean;
FAZA: byte;
В этом случае все описанные идентификаторы можно применять в программе. Работа этого раздела будет заключаться в том, что машина выделит две ячейки памяти с именами k и n. В ячейках могут храниться только целые числа: в ячейках с именами S,T,Z – по одному символу; в ячейках a,b,c – только величины типа вещественных чисел; в L25 и L3 –величины true и FALSE, а в ячейке с именем FAZA – только числа от 0 до 255. Если попытаться, например, в ячейку S поместить не символ, а число, то это приведет к ошибке, т.е. правильно S:= ¢A¢; или S:= ¢$¢; или S:= ¢1¢; однако неверно S:= 1 (1 – число в отличие от ¢1¢ – символа). Если в процессе выполнения программы данное не меняется, то его можно описать в разделе "Описания констант":
Const
A=36.74; B=true;
С
=
¢
а
¢
;
Здесь тоже выделяются ячейки памяти с именами А,В,С
для хранения заданных величин, которые не подлежат изменению.
Допустимо описание констант-выражений:
C
o
nst
М = (32.5 + 0.64) / 3.14;
Кроме того, машина "знает", чему равны константы е
и π
.
Пример. Составить программу для вычисления выражения
,
где величины R, а, S, L, K вводятся с клавиатуры.
Пусть k, l - целые числа, остальные – вещественные.
Program Prim2,
Var k,L:integer;
Y,R,
a
,S : real; {здесь для хранения результата y тоже}
{нужна ячейка памяти}
Begin writeln ('введите це', {выдача на экран текста, указанного в}
'лое k,L, действительные' {кавычках; обратите внимание на прави-}
'R,а,S'); {ло переноса текста в операторе writeln:}
{если нужно перенести текст, то ставится} {закрывающий апостроф, затем запятая,}
{новая строка вновь начинается с апострофа}
readln (k,L,R,a,S);
Y: = 1-l(l+sqr(r
*
a/k))/(exp(2)/sqr(s)
*
sqr(l+r
*
a/l));
writeln
(
Y
);
readln
;
END
.
То же самое будет, если записать программу:
Program Prim2a;
Var k,L: integer, R,a,S:real;
Begin writeln ('
введите
целые
k,L'); readln (k,L);
writeln ('
введите
вещественные
r,S,a'); readln (R,S,a);
writeln(l-l/(l+sqr(r
*
a/k))/(exp(2)/sqr(s)
*
sqr(l+r
*
a/l)),
readln
;
END
.
Последний оператор writeln вначале вычислит арифметическое выражение, а затем выведет на экран его значение в виде числа. Если мы хотим, чтобы результат был в виде 'результат Y = число', то необходимо последний writeln написать в следующем виде:
writeln ('результат Y =',1-l/(l+sqr(r*a/k))/exp(2)/sqr(s) *sqr(l+r*a/l)); тогда машина вначале выведет текст, взятый в апостроф, т.е. "результат Yi", а затем его значение.
2.7. Раздел описания типов
Помимо вышеперечисленных стандартных типов в Паскале могут быть применены типы, определенные пользователем, т.е. перечисляемые и интервальные типы. Перечисляемые типы задаются непосредственным перечислением всех значений, которые может принимать переменная данного типа. Описать типы, определенные пользователем, можно в разделе Var
или предварительно в разделе Туре
, а затем – в Var
. рассмотрим оба варианта.
Пусть нам нужна переменная с именем season
(сезон года). она может принимать значения winter
(зима), spring
(весна), summer
(лето), autumn
(осень), другие значения она принимать не может. Тогда нужно сделать следующее описание:
Var
season
: (
winter
,
spring
,
summer
,
autumn
).
Здесь тип season
задан перечислением всех констант, которые могут быть занесены в ячейку памяти season
. Попытка занести в ячейку season
любое другое значение приведет к ошибке – "несоответствие типа".
Если переменных данного типа будет несколько, удобнее и нагляднее вначале определить тип в разделе Туре
(описание типа), а затем в разделе Var
сослаться на этот тип, и машина в Var
выделит конкретные ячейки памяти для хранения данных указанного типа.
Например, необходимо определить, что Gi
, G2
, G3
, G4
будут ячейками памяти, в которых могут храниться наименования газов Со
, О
, N
, F
, а в ячейках памяти Metall1
, Metall2
, Metall3
– наименования металлов Fе
, Со
, Na
, Cu
, Zn
, тогда можно применить описание:
VAR GI, G2, G3, G4: (CO,O,N,F);
Metall1, Metall2, Metall3: (Fe,Co,Na,Cu,Zn).
Можно использовать и другое, более наглядное описание. вначале определить тип Gaz
, Met
, а затем на них сослаться:
Туре
Gaz
=(
Co
, О,
N
,
F
);
Met = (F
е
,
Со
, Na, Cu, Zn);
Var GI, G2, G3, G4 : GAZ;
Metall
1,
Metall
2,
Metall
3,
Met
;
Особенно удобно применение раздела Туре
, если он находится во внешнем блоке, а ссылки на него идут во внутренних блоках (см. раздел "Блоки"). Тогда значительно экономится память, поскольку она может быть практически одной и той же в разных блоках.
При описании переменных перечисляемого типа данные внутри скобок являются константами, которые может принимать описываемая переменная. Над данными такого типа допустимо выполнять операции отношения и логические операции (см. далее). Например, для приведенного выше описания данного season
будет истинным высказывание: "winter < spring
".
При работе с данными перечисляемого типа можно применять стандартные функции Succ, Рred, Ord
.
Succ
(аргумент) возвращает значение, следующее за элементом, указанным как аргумент. Если следующего элемента нет (закончились), то это приводит к программному прерыванию (ошибке).
Рred
(аргумент) возвращает предыдущее значение из перечня констант, из которых состоит данный тип.
Ord
(аргумент) возвращает порядковый номер аргумента в списке констант, перечисленных в описании в виде целого числа. Элементы пронумерованы в порядке 0,1,2,..., т.е. первый элемент имеет номер 0.
Пример:
Туре month = ('jan','fab','mar','apr','may','
jun
','
jul
','aug','sep','ocf','nov','dec');
Var a,b,c,d,c,mes: month; f,h,g: integer;
Begin mes: =jul;
a: = Pred (mes); {
в
a
находится
'jun'}
b: = Succ (mes); {
в
b
находится
'aug'}
с: =
Pred
(
pred
(
mes
)); {в с находится '
m
ау'}
d
: =
Succ
(
succ
(
mes
)); {в
d
находится '
sep
'}
e: = Succ (pred(mes)); {
в
е
находится
'jul'}
f
: =
Ord
(
mes
); {в
f
находится 6}
h: = Ord (pred(mes)); {
в
h
находится
5}
g: = Ord (succ(mes)); {
в
g
находится
7}
END
Интервальный тип задается диапазоном изменения констант внутри какого-либо уже имеющегося перечисляемого или стандартного типа, кроме вещественного (integer, byte, booban, char). Значение первой константы должно быть меньше значения второй константы диапазона.
Туре
Dni = 1...31;
Litera = 'a',...,'z',
Var Rabdni,bolndni, vuhod: dni; {
могут
принимать
значения
1-31}
im
,
ident
:
litera
; {могут принимать значения '
A
'-'
Z
'}
Выход за пределы диапазона вызывает программное прерывание.
Допускается задание диапазона именами констант:
Const min = 1; max = 31;
Туре
Dni = min…max;
Var rabdni,boldni,vuhoddni:dni;
Для интервального типа также возможно применять функции S
uc
c,
P
red, Ord.
3. Разветвляющиеся программы
3.1. Общие положения
До сих пор мы рассматривали линейные программы, алгоритм которых можно было представить в виде блок-схемы (рис. 3.1)
Возможны случаи, когда программа ветвится в зависимости от какого-либо условия (см. рис. 3.2). Ветвление может быть двух направлений: по принципу условие верно – идти по одной ветви, условие ложно – по другой. В этом случае применяется оператор if
. возможно ветвление сразу нескольких направлений: если k=l – идти по одной ветви, если k=2 – по другой, k=3 – по третьей и т.д. в этом случае удобнее применять оператор Case
.
3.2. Оператор goto
, раздел описания меток
Последовательное выполнение операторов в программе может быть нарушено оператором перехода. Общий вид оператора: goto метка
; где метка – буква, либо цифра, либо набор букв и цифр, из которых первая – всегда буква, Например, М1, LI, NK
. Метка, стоящая после goto
, указывает, куда нужно пойти. Достигается это тем, что если в программе находится оператор goto метка
; то в этой же программе обязательно имеется какой-либо оператор вида метка: оператор
; который считается помеченным, и машина, встретив goto метка
; не будет выполнять оператор, записанный после оператора goto метка
; а перейдет к выполнению оператора метка: оператор
;
Иллюстрация:
а: =
b
+с;
с: =
sgrt
(
a
+
exp
(
b
));
goto M1;
z: = x+y;
writeln (z);
M
1:
S
: =
P
;
В случае, если бы не было оператора goto М1
; все операторы выполнялись бы последовательно один за другим. здесь же после оператора с: =...
стоит goto М1
; следовательно, машина не будет выполнять z:=...
и writeln...
, а сразу после с: =...
перейдет к выполнению оператора М:
S
: = Р
;
Метки, применяемые в программе, должны быть описаны в разделе описания меток, который желательно ставить первым среди описаний. Выглядит раздел так: Label М1, М2, L, NK
; т.е. после слова Label
перечисляются через запятую все метки, которые будут применяться в данном блоке (программе). Заканчивается описание символом ';'
.
Пример: составить программу, вычисляющую значения функции cos х
, где начальное х = 0
, следующее х = 0.01
и т.д.
Program Prim3; Label M; Var x:real; BEGIN x:=0; M: writeln('x=',x,'cos x = ',cos(x)); x:=x+0.01;
goto
M
;
readln
;
END
.
Программа будет работать следующим образом: х
присвоится значение 0
; writeln
выведет на экран текст, который указан в первых кавычках х =
, далее извлечет из ячейки х
значение и выведет его на экран; затем снова выведет текст cos х =
, затем вычислит значение cos х
и выдаст его на экран, т.е. машина выведет первую строку в виде
x = 0.0000000000Е + 00 cos х = 9.9999999999Е - 01.
После этого возьмется то х
, которое было извлечено из ячейки памяти х
(прежнее значение х
), т.е. 0.0
, к нему прибавляется величина 0.01
и результат снова занесется в ячейку памяти х
так, что в х
будет 0.01
, после этого оператор goto m
; передаст управление оператору, помеченному меткой м
, т.е. оператору writeln,
и машина выдаст новую строку:
x = 1.0000000000Е - 02 cos х = 9.9995000041Е - 01;
– выполнит оператор
х: =x + 0.01, получит х = 0.02;
– выведет строку
x = 2.0000000000Е - 02 cos х = 9.9980000666Е – 01;
– сделает х = 0.03
и т.д., до бесконечности, так как в данном алгоритме окончание работы не предусмотрено. Для завершения работы следует применить оператор if
.
3.3. Оператор if
Общий вид: If булевское выражение then оператор else оператор;
Работа оператора: вначале вычисляется булевское выражение, значение которого в конечном итоге может быть только TRUE или FALSE. Если булевское выражение TRUE, то выполняется оператор, следующий за словом then
, а затем происходит переход к оператору, следующему за if
. Если булевское выражение false
, то выполняется оператор, следующий за словом else
, затем происходит переход к оператору, следующему за оператором if
.
Замечание
: после оператора, следующего за then,
перед else
символ ';'
не ставится, так как оператор if
еще здесь не закончен, а ';'
ставится после окончания оператора. Возможно применение сокращенного оператора if
:
If булевское выражение then оператор;
Здесь, если булевское выражение true,
выполняется оператор, следующий за словом then
, и происходит переход к оператору, следующему за оператором if
. Если булевское выражение false
, то оператор if
игнорируется (вообще не выполняется), а выполняется оператор, следующий за if
.
Переделаем "бесконечную" программу п. 3.2. в такую, которая остановится тогда, когда х
станет равным 0.1
.
Program Prim4; Label M; Var x:real;
BEGIN x:=0;
M: writeln('x=',x,' cos x = ',cos(x));
x:=x+0.01;
if x<=0.1 then goto M; readln;
END.
Программа выдает результаты вычислений cos(x)
для х = 0.01, 0.02, 0.03
и т.д., до 0.01
.
В последней программе булевское выражение х < = 0.1
. Какие бывают булевские выражения? Вообще говоря, булевское выражение после вычисления всегда истинно или ложно, т.е. TRUE или FALSE. Действительно, выражение х < = 0.1
может быть истинно, если х
меньше или равно 0.1,
и ложно – в противном случае. Вообще булевское выражение может строиться из булевских констант TRUE и FALSE; переменных булевского типа (в которых могут храниться TRUE или FALSE); обращений к функциям, которые возвращают TRUE или FALSE и отношений, соединенных между собой булевскими операциями и круглыми скобками.
Здесь следует расшифровать, что такое отношения и булевские операции. Примером отношения может быть приведенное выше х < = 0.01
, т.е. в общем случае отношение – это два арифметических выражения, соединенных между собой операциями отношения. Операции отношения: = (равно), < > (неравно), > (больше), > = (больше или равно), < (меньше), < = (меньше или равно).
Пример отношений: а + b < = sin(c)
exp(p) > (cos(i) - a)/sgr(b).
Как мы уже говорили, эти отношения могут быть истинны или ложны в зависимости от конкретного значения величин, в них входящих, на момент вычисления.
Логические операции – это нам уже известные. Напомним, как они работают: or
(или), and
(и).
Имеется описание Var A,B: boobean
;
Or – логическое сложение, читается как "или". Результат операций – истина, если или А, или В – истина, и ложь, если А и B ложны.
Например: А В А ог В
true true true
true false true
false true true
false false false
Замечание:
данная операция аналогична арифметической OR, если TRUE заменить 1, а FALSE – 0.
АND - логическое умножение, читается "и". Результат операции – истина только тогда, когда и А, и В – истина, в остальных случаях результат – ложь.
АВ A and B
true true true
true false false
false true false
falsefalsefalse
Кроме того, удобно применять однокомпонентную операцию Not, которая вводится следующим образом: если А есть TRUE, то Not А есть FALSE и если А есть FALSE, то Not А есть TRUE.
С помощью этих операций можно построить условия любой сложности. Например, пусть необходимо решить задачу:
Напишемпрограмму:
Program Prim5;
Var a,x:real;
BEGIN
writeln('
введите
а
,х'); readln(a,x);
if (a>0) and (x>0) and (x<=0.5) then
writeln('z=',a*sqr(x)/sin(x)) else
if (a>0) and (x>=0.5) and (x<3) then
writeln('z=',exp(x)) else
if (a<=0) or (x<=0) then
writeln('z=',sqrt(a)*sqrt(x)/sin(x)) else
writeln('z=0');
readln; END.
Замечание
: в последнем примере мы видим, что операторы if
могут быть вложены друг в друга. Вкладывать их можно неограниченное количество раз, причем новый if
может начинаться как после слова then
, так и после слова else
.
Еще один пример: пусть дана область (заштрихованная на рис. 3.3). Мы вводим с клавиатуры координаты точки. Машина должна определить, принадлежит ли данная точка этой области или нет.
Разобьем область рис. 3.3 на несколько простых:
1. Внутренняя часть сектора, ограниченного отрицательной частью оси OX, положительной OY и окружностью с центром в начале координат и радиусом, равным 2.
|
2. Прямоугольник, ограниченный осями OX, OY и прямыми x=4, y=2.
3. Прямоугольник, ограниченный осями OX, ОУ и прямыми x=-2, y=-4.
4. Внутренняя часть сектора, ограниченного положительной частью оси OX, отрицательной OY и окружностью с центром в начале координат и радиусом, равным 3.
5. Внутренняя часть квадрата, ограниченного прямыми линиями x=2, x=3, y=-3, y=-4.
6. Область, лежащая внутри окружности с центром x=5, y=-3 и
радиусом= 1,5.
Программа:
Program Prim6;
Label N,K,L;
Var x,y:real; f:char;
BEGIN N: writeln('введите координаты точки');
readln(x); writeln('x=',x);
readln(y); writeln('y=',y);
if (x<=0) and (y>=0) and (sqr(x)+sqr(y)<=4) {1-
я
область
}
or (x>=0) and (x<4) and (y>=0) and (y<=2) {2-
я
область
}
or (x<=0) and (x>=-2) and (y<=0) and (y>=-4) {3-
я
область
}
or (x>=0) and (y<=0) and (sqr(x)+sqr(y)<=9) {4-
я
область
}
or (x>=2) and (x<=3) and (y<=-3) and (y>=-4) {5-
я
область
}
or (sqr(x-5)+sqr(y+3)<=2.25) {6- я область}
then writeln('точка с координатами х=',x,' y=',y, 'принадлежит области')
else writeln('точка с координатами х=',x,' y=',y, 'не принадлежит оласти);
L: writeln('будем ли ещё вводить координаты точки?,
Y
,
N
'); readln(f);
if (f='Y') or (f='y') then goto N else
if (f='N') or (f='n') then goto K else
writeln('неправильно нажали клавишу, попробуйте ещё раз'); goto L;
K
:
readln
;
End
.
Замечание:
для того, чтобы построить область, необходим здравый смысл и элементарные знания аналитической геометрии. Так, х>=0
определяет область (рис. 3.4)
x>=0 andx<=4 определяет полосу (рис. 3.5)
Вспомнив, что уравнение окружности с центром в начале координат x2
+y2
=r2
, имеем x2
+y2
£4 (рис. 3.6),
x£0 является полуплоскостью (рис. 3.7),
y³0 определяет полуплоскость (рис. 3.8),
x£0 andy³0 есть квадрант (рис. 3.9)
и, наконец,
x£0 andy³0 andsqr(x)+sqr(y)£4 есть сегмент (рис. 3.10)
3.4. Оператор case
(оператор выбора)
Общий вид:
Case
выражение - селектор of
Список констант выбора 1: оператор 1;
Список констант выбора 2: оператор 2 ;
– – – – – – – – – – – – – – – – – – – – – – – – – –
Список констант выбора n оператор n;
else оператор end;
Здесь выражение-селектор есть выражение, которое после выполнения имеет любое скалярное значение, кроме вещественного (типы данных; разд. 2.6.), т.е. выражение-селектор может быть байтового, целого, логического, символьного, перечисляемого и интервального типов.
Список констант выбора состоит из перечня констант, разделенных запятыми, либо из констант, заданных интервалом, либо из комбинаций перечня констант и интервалов. Тип констант в списках Case
должен соответствовать типу выражения селектор. Значения констант в списках не должны повторяться.
Работа оператора. вначале вычисляется выражение-селектор, затем полученное значение сравнивается с константами выбора, и, если значение выражения-селектора совпадает с какой-либо константой выбора, то выполняется оператор, стоящий после списка констант, в котором есть константа, совпадающая со значением выражения-селектора. если значение выражения-селектора не совпадает ни с одной из констант выбора, то выполняется оператор, следующий за else. Else
может в Case
отсутствовать, тогда в случае несовпадения констант оператор Case
игнорируется.
Примеры:
1. Селектор целого типа, список констант представлены перечнем констант:
Program Prim7;Var i,z:integer;BEGIN writeln('
введите
целое
i'); readln(i);
Case i of
1,2,5: writeln('i=',i,' z=',i+10);
12,16: writeln('i=',i,' z=',i+100);
31,35,46: writeln('i=',i,' z=',i+1000);
else
writeln
('неправильно задано
i
');
end
;
readln
;
END
.
2. Селектор целого типа – список констант представлен диапазоном.
вводится целое i, определить, находится ли оно в диапазоне 1-10 или 11-100, или 101-1000, либо вне этих диапазонов.
Program Prim8;Var i:integer;BEGIN writeln('
введите
целое
i'); readln(i); Case i of
1..10: writeln(' число в диапазоне
1-10');
11..100: writeln(' число в диапазоне
11-100');
101..1000: writeln(' число в диапазоне
101-1000');
else writeln('
число
вне
диапазона
1-1000'); end;
readln; END.
3. Селектор целого типа, список констант представлены перечнем констант и диапазоном:
Program Prim9; Var i:integer; x,m,a,b,c,d:real; BEGIN writeln('
введите
значение
i'); readln(i); writeln('
введите
значения
x,m,a,b,c,d');
readln(x,m,a,b,c,d);
Case i of
1,2,4,8,11..20,24,28,30: writeln('y=',(x+1)/(sqr(x)+2)-ln(m)+2
*
a/b);
31,45..55: writeln('y=',(sqr(a)+m)/sqrt(b+m)-3
*
a
*
b/c+d);
58,60,63..76,78,93,100: writeln('y=',sqr(x)-a
*
x+sqr(sin(a
*
x)-exp(x))
/(1-ln(sqr(x)-exp(х/2))));
else
writeln
('неправильно задано
i
');
end
;
readln
;
END
.
4. Селектор знакового типа:
Program Prim10; Var name:char;
BEGIN writeln('
введите
шифр
'); readln(name);
Case
name
of
'
S
','
s
':
writeln
('
факультет самолето- и вертолетостроения');
'
D
','
d
':
writeln
(' факультет авиадвигателестороения');
'Y','y': writeln(' факультет систем управления');
'L','l': writeln(' факультет летательных аппаратов');
'R','r': writeln(' факультет радиотехнический ');
'M','m': writeln(' факультет инженерно - менеджерский'); 'Z','z': writeln(' факультет заочного обучения');
else writeln('введенный шифр не соответствует ни одному ',
'из факультетов ХАИ'); end; readln; END.
5. Селектор перечисляемого типа:
Program Prim11; Var season:(winter,spring,summer,autumn); rez:integer;BEGIN season:=spring; Writeln('
результат
ord(season)=',ord(season)); case season of winter: writeln('winter');
spring: writeln('spring');
summer: writeln('summer');
autumn: writeln('autumn');
end; readln;
END
.
4. Циклические программы
Наиболее часто в практике программирования встречаются циклические программы. В циклических программах какой-либо алгоритм повторяется многократно, при этом один из параметров изменяется. Например, описанная в п. 3.3 программа Рrim 4 является классическим примером циклического алгоритма. Операторов цикла в Паскале три: for, repeat, while
.
4.1. Оператор for
Оператор состоит из заголовка, в котором определяется порядок изменения переменной параметра цикла и тела цикла, являющегося многократно повторяющимся алгоритмом. Общий вид оператора:
for
– параметр цикла: = начальное значение to,
конечное значение do
{заголовок}; оператор; {тело цикла}. Этот оператор применяется, если начальное значение < конечного значения;
for
– параметр цикла:=начальное значение downto,
конечное значение do
; оператор; применяется, если начальное значение > конечного значения.
Пример: найти сумму квадратов целых чисел от 8 до 1.24.
Program Prim12; Var i,s:integer; BEGIN s:=0; for i:= 8 to 124 do s:=s+sqr(i); writeln('s=',s); readln;
END.
Работа программы
. В разделе Var
выделяется ячейка памяти с именем i и s для хранения величин. Поскольку в S мы должны накапливать сумму, то вначале занесем в S ноль. Затем заголовок цикла присваивает i=8. далее выполняется тело цикла: извлекается содержимое ячейки S (а там у нас 0) и к этому содержимому прибавляется sgr(i), т.е. i2
=82
. Результат присваивается ячейке S, т.е. в S теперь 82
.
Проверяется, не стал ли параметр цикла больше конечного значения параметра 128. Это не произошло, поэтому i присваивается следующее значение равное 9 и вновь выполняется тело цикла, т.е. S:=82
+92
. Можно сказать так: S присвоить тому S, которое было раньше, + следующее i2
. Так как цикл еще не закончился, то i станет равным 10, а S присвоится тому S, которое было раньше, т.е. 82
+92
, и к нему прибавится еще текущее i2
, т.е. 102
. Этот процесс повторяется до тех пор, пока параметр цикла не станет равным 124. Тогда в последний раз 1242
прибавляется к накапливаемой сумме.
Итак: выполнение цикла значения i значения S
1 8 82
2 9 82
+92
3 10 82
+92
+102
– – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
116 117 82
+92
+102
+…+1232
117 124 82
+92
+102
+…+1232
+1242
При i=125 происходит выход из цикла и переход к оператору writeln
('S=' ,S);
Эта, казалось бы, правильно написанная программа дает результат S=-12250. Как может получиться отрицательный результат при суммировании квадратов – заведомо положительных чисел? Такой результат мы получаем путем суммирования и занесения результатов в ячейку S типа integer
, а в integer
могут быть помещены числа в диапазоне -32768 +32767, поэтому после переполнения ячейки памяти в знаковый разряд переносится 1, которая интерпретируется машиной как '-'. Чтобы этого избежать, можно описать S как longint. Тогда результат работы программы будет правильный и равен 643110.
Program
Prim
12
a
;
Var
i
,
s
:
longint
;
BEGIN s:=0;
for i:= 8 to 124 do
s:=s+sqr(i);
writeln('s=',s);
readln; END.
Можно также описать S как real
.Program Prim12b; Var i:integer; s:real;
BEGIN s:=0;
for i:= 8 to 124 do
s:=s+sqr(i);
writeln('s=',s);
readln;
END.
Результат работы этой программы будет равен 6.4311000000E+05, что то же самое, что и 643110, если считать, что запись 6.4311000000E+05 равносильна математической записи 6,4311*10+5
.
Правила применения оператора цикла for
1.Тело цикла - всегда один оператор. Если нужно, чтобы тело цикла состояло из нескольких операторов, то их объединяют в один с помощью операторных скобок begin, end.
for i:=l to n do
Begin S:=S+sin(x)/cos(x);
x=x+0.01;
writeln('S=' ,S)
end.
Операторы, взятые в операторные скобки begin, end
, считаются одним составным оператором.
2. Начальное и конечное значения параметра цикла в общем случае являются выражениями. Тип этих выражений и тип параметра цикла должны совпадать. Здесь допускается применение любых типов, которые упорядочены с каким-либо фиксированным шагом, это может быть любой скалярный тип, кроме вещественного, т.е. байтовый, целый, символьный, перечисляемый, интервальный, булевский. на практике чаще всего применяют целочисленный тип.
3. В теле цикла параметр цикла не должен изменяться.
4. Нельзя с помощью оператора перехода goto
войти в тело цикла, минуя заголовок.
5. Выйти из тела цикла в программу можно по if
..goto
, не дожидаясь полного перебора параметров цикла.
Пример: написать программу, выводящую буквы латинского алфавита в одну сторону, с пробелом между ними.
Применяем здесь в качестве параметра цикла символьную переменную, в качестве начального значения параметра – константу 'A', конечного – 'Z'.
Program Prim13;
Var
i:char;
BEGIN
for i:='a' to 'z' do
write(' ',i);
readln; END.
Пример: вычислить значение определенного интеграла на участке a,b для функции cos х, т.е. определить площадь, заштрихованную на рис. 4.1.
Применим метод трапеций, суть которого заключается в том, что область делится на ряд трапеций, площади которых вычисляются и суммируются. Чем на большее количество трапеций мы разделим область, тем точнее получим результат (см.рис.4.2).
Program Prim14;
Var i,n:integer; a,b,x,h,s:real;
BEGIN writeln('
введите к-во точек разбиения
n
и величины а,
b');
readln(n,a,b);
h:=(b-a)/n; s:=0; x:=a;
for i:=1 to n do
Begin s:=s+(abs(cos(x))+abs(cos(x+h)))/2*h;
x:=x+h; end;
writeln('s=',s);
readln; END.
Замечание:
при вычислении S (так как функция пересекает ось OX) часть площадей может иметь отрицательное значение, поэтому мы берем abs(f(x))
.
Усложним задачу: пусть нужно найти площадь криволинейной трапеции (интеграл), где функция от точки а
до b sin(x)
, а после b
до с
cos(x)
.
Program Prim15;
Var i,n:integer; a,b,c,x,h,s,fxpred,fxposl:real;
BEGIN writeln('введите к-во точек разбиения
n
и величины а,
b, c');
readln(n,a,b,c);
h:=(c-a)/n; s:=0; x:=a;
for i:=1 to n do
Begin
{ определимся, по какой из функций считать стороны трапеций }
if (x>=a) and (x<=b) then fxpred:= abs(sin(x)) else
fxpred:=abs(cos(x));
if (x+h>=a) and (x+h<=b) then fxposl:= abs(sin(x+h)) else
fxposl:=abs(cos(x+h));
s:=s+(fxpred+fxposl)/2*h;
x:=x+h; end;
writeln('s=',s);
readln; END.
В последних двух программах мы заменяем площадь криволинейной трапеции (интеграл) суммой трапеций. При этом нам неизвестно, какую ошибку мы допустим; знаем, что чем больше точек разбиения, тем точнее будет результат. Поставим задачу: совершенно точно знать, что мы посчитаем интеграл с точностью не менее заданной, например, что разность между площадью криволинейной трапеции и суммой прямоугольных трапеций будет не больше Е = 0.01. Для этого нам нужно посчитать результат для количества точек, например 10, затем – 100. Сравнить величины площадей, и, если их разность будет меньше Е, то можно с уверенностью сказать, что площадь для разбиения на 100 интервалов будет найдена с точностью не менее Е. Если разность между расчетами на 10 и 100 интервалов больше Е, то следует разбить область интегрирования на 1000 интервалов и сравнить сумму для 100 интервалов с суммой для 1000 интервалов, и если их разница будет меньше Е, то за результат принять площадь, посчитанную для 1000 разбиений и т.д. рано или поздно мы получим искомый результат. Сравнения сумм площадей трапеций будем производить с помощью оператора if
.
Пусть функция будет cos(x). Напишемпрограмму:
Program Prim16;
Label NAH,KON;
Var i,n:integer; a,b,x,h,spred,spos,e:real;
BEGIN writeln('введите точность е и границы a, b');
readln(e,a,b); spred:=9.9e+10; h:=0; n:=10;
NAH: spos:=0; h:=(b-a)/n; x:=a;
for i:=1 to n do
Begin spos:=spos+(abs(cos(x))+abs(cos(x+h)))/2*h;
x:=x+h; end;
if abs(spos-spred)<=e then Begin
writeln('s=',spos,' n=',n); goto KON; end
else spred:=spos; n:=n*10; x:=a; goto nah;
KON
:
readln
;
END
.
Работа программы: for i: = i to n do
, в первый раз оператор
Sp
о
s: = spos+(abs(cos(x))+abs(cos(x+h)))/2
*
h
посчитает значение интеграла для 10 точек разбиения. Затем if
сравнит полученное значение spos с 9.9Е+10. Конечно, разница между этими величинами не будет меньше е, тогда мы забудем число 9.9Е+10, так как присвоим spred: = spоs
, чтобы при следующем выполнении if
сравнивать предыдущее и последующее значения интеграла. После этого увеличим количество точек разбиения n: = n*10 и вернемся на начало вычисления sp
o
s
, т.е. интеграла для 100 интервалов goto nach
. После нового вычисления sp
o
s
сравним 100 интервалов для 10 интервалов spred
. Если разность между ними не меньше Е, то забудем значение s
для 10 интервалов и занесем в spred
значение для 100 интервалов. Затем вычислим значение интеграла для разбиения 1000 и результат занесем в spos,
сравним spred
и spos
и т.д.
4.2. Оператор repeat
. Общий вид
В отличие от for
, оператор repeat
(а также while
) применяют тогда, когда неизвестно точно, сколько раз будет выполняться тело цикла. Общий вид оператора
repeat
оператор;
оператор;
– – – – – – – –
оператор until
булевское выражение;
Работа оператора. Сначала выполняются операторы, составляющие тело цикла, затем выполняется булевское выражение, и если оно ложно, вновь выполняется тело цикла. Выход из цикла происходит, когда булевское выражение станет истинным.
Явного перебора параметров в repeat
не предусмотрено, поэтому изменение параметров осуществляется в теле цикла. Здесь же мы должны позаботиться , чтобы рано или поздно булевское выражение стало истиной.
Замечания:
1.Тело оператора repeat
выполняется по меньшей мере один раз. Оператор repeat
еще называют циклом с послеусловием.
2. Перед until ';'
не ставится.
Пример: найти сумму четных чисел в интервале от 0 до 100.
Program Prim17;
Var i,s:integer;
BEGIN i:=0; s:=0;
repeat
i:=i+2; s:=s+i
until i>100;
writeln('s=',s);
readln; END.
Пример: найти ток в цепи переменного тока в зависимости от частоты тока. Известно, что при последовательном соединении активной, емкостной и индукционной нагрузок сила тока может быть вычислена по формуле
Пусть U = 220, R = 100, L = 0.57, С = 3.2*10-3
, Fначальное
=10; F будем менять с шагом 0.5. Печатать все результаты. Результаты, когда i>3, нас не интересуют.
Program
Prim
18;
Var i,r,f,l,c,u:real;
BEGIN writeln(' введите значения u r l c');
readln(u,r,l,c);
f:=50;
repeat i:=u/sqrt(sqr(r)+sqr(2*pi*f*l-1/(2*pi*f*c)));
f:=f-1;
writeln('f=',f,' i=',i)
until i>3;
readln; END.
4.3. ОператорWhile
Оператор While
цикла с предусловием.
While –
булевское выражение; do –
тело цикла.
Работа оператора. Вначале вычисляется булевское выражение, и если оно истинно, то выполняется тело цикла; если оно ложно, то происходит выход из цикла.
Тело цикла – один оператор, как правило, составной. Мы должны позаботиться о том, чтобы булевское выражение в теле цикла на каком-то этапе стало ложным, иначе цикл никогда не закончится. Цикл можно сделать умышленно бесконечным, написав: while true do оператор
;
Мы будем применять эту конфигурацию при написании программ обработки файлов.
Пример: найти сумму четных чисел в интервале от 0 до 100.
Program Prim19;
Var i,s:integer;
BEGIN i:=0; s:=0;
while i<100 do
Begin i:=i+2; s:=s+i; end;
writeln('s=',s);
readln; END.
Пример: в цепи переменного тока найти ток в зависимости от его частоты.
Program Prim20;
Var i,r,f,l,c,u:real;
BEGIN writeln('введите значения u,r,l,c');
readln(u,r,l,c);
f:=50;
while i<3 do
Begin i:=u/sqrt(sqr(r)+sqr(2*pi*f*l-1/(2*pi*f*c)));
f:=f-1;
writeln('f=',f,' i=',i); end;
writeln('i>3, i=',i);
readln; END.
4.4. Вложенные циклы
Поскольку тело любого цикла состоит из операторов или составного оператора, то ничто не помешает в теле цикла располагать другие операторы цикла. Рассмотримработупрограммы:
Program Prim21;
Var
i,j:integer;
BEGIN
for i:=1 to 5 do
Begin writeln;
for j:=20 to 23 do
write('i=',i,' j=',j);
end;
readln; END.
Дляциклаfor i:=1 to 5 do
теломциклаявляется
begin for j:=20 to 23 do
write(' i= ', i, ' , j = ', j);
writeln;
end;
Назовем этот цикл внешним. Кроме того, имеется внутренний цикл
for
j
: = 20
to
23
do
с телом write
('
i
= ',
i
,
j
=',
j
)
;
Работа программы. Вначале машина встречает внешний цикл и начинает его выполнять: присваивает i=l, затем переходит к его телу, а здесь встречает внутренний цикл и присваивает j значение 20, после чего выполняет тело внутреннего цикла, т.е. выводит на экран i=l, j=20. Так как внутренний цикл еще не окончен, то машина продолжает его выполнять, т.е. присваивает j значение 21 и добавляет к уже выведенной строке i=l, j=21.
Заметим, что оператор write
отличается от оператора writeln
тем, что он не начинает вывод с новой строки, а продолжает писать в той же строке, т.е. после второго выполнения внутреннего цикла на экране появится
i= 1, j=20 i= 1, j=21.
Машина продолжит выполнение внутреннего цикла, и, когда он закончится (выполнится для j = 20.21.22.23), на экране будет строка
i = 1 j = 20 i =l j = 21 i = 1 j = 22 i = 1 j = 23.
Внутренний цикл закончится, однако тело внешнего цикла еще не закончилось, поэтому выполняется оператор writeln
, который переводит курсор на новую строку. После этого тело внешнего цикла закончится, но сам цикл отработал только для i = 1. Поэтому внешний цикл продолжит работу, присвоив i: =2 и вновь начав выполнение своего тела. Встретив внутренний цикл j:=1, на экран с новой строки выведется: i=2, j=20, затем j:=2 и к этой строке добавится i=2, j=21 и т.д., пока не закончится внутренний цикл.
Таким образом, внешний цикл, изменяя i от 1 до 5, заставит каждый раз выполняться полностью внутренний цикл, и в результате работы программы на экране появится:
i=l, j=20 i=1, j=21 i=1, j=22 i=1, j=23
i=2, j=20 i=2, j=21 i=2, j=22 i=2, j=23
i=3, j=20 i=3, j=21 i=3, j=22 i=3, j=23
i=4, j=20 i=4, j=21 i=4, j=22 i=4, j=23
i=5, j=20 i=5, j=21 i=5, j=22 i=5, j=23
Вкладывать циклы друг в друга можно любое количество раз, необходимо лишь помнить, что количество выполнений самого внутреннего тела цикла при этом будет расти в геометрической прогрессии. Так, например,
for i:=l to 100 do
for j:=l to 100 do
for k:=l to 100 do
writeln (i, j, k);
дает столбик цифр:
111
112
113
114
– – – – –
121
122
123
124
– – – – –
211
212
213
– – – – –
100100100,
что составляет 1000000 строчек.
Пример: найти rez = f (х1
) + f (х2
)+.. .+f (x6
),
где
f(x) считать с точностью не менее e=0.01;
х1
=0.1, затем xn
=xn-l
+0.2, пока х не станет равным 1.1.
Нам нужно вычислить rez. Поскольку это будет сумма, то вначале положим rez=0, затем вычислим f(х1
) с нужной точностью и добавим к rez, и т.д., то есть:
Rez : = 0 ; x:=0.l;
for i:=l to 6 do
Begin Rez:=Rez+f(x);
x
:=
x
+0.2;
end
;
Теперь в данную программу нужно "вставить" вычисленные f(x) с необходимой точностью. Для этого найдем сумму, составляющую f(x) для n элементов, затем – для n+l элемента, сравним их по модулю и, когда разность между ними будет меньше Е, сумму для n+l элемента ряда примем за более точную и добавим к Rez
. При вычислении f(x) количество членов ряда, которые нам придется суммировать, не известны, поэтому придется применять цикл типа repeat
или while
. Кроме того, в элементы ряда входит 2n! Факториал подсчитывается по схеме 1! = 1, 21 = 1*2; з! =1*2*3 и т.д., т.е. например, 8! = 1*2*3*4*5*6*7*8. Далее, при подсчете следующего значения ряда, можно величину 2n! найти по схеме: fak: = fak
*
(n-l)
*
n
. Ряд у нас знакопеременный, т.е. меняется '+', '–' перед каждым членом ряда. Меняем знак с помощью схемы znak: = znak
*
(-1)
. Если исходный знак = +l, то в ячейке znak
будет храниться то +l, то -1.
С учетом сказанного выше f(x) с нужной точностью вычисляется:
fxpred: = 0; fxpos: =l, n: = 2; znak: = 1; fak: = 1;
while Abs(fxpos – fxpred) > = 0.01 do
Begin fxpred: = fxpos: znak: = znak
*
(-1); fak: = fak
*
(n-l)
*
n;
fxpos: = fxpos+znak
*
exp(n
*
in (x))/fak;
n
: =
n
+2;
end
;
Соединив оба фрагмента программы и снабдив их описаниями, получим готовую программу:
Program Prim22;
Var n,fak,i,znak:longint;
rez,x,fxpred,fxpos:real;
BEGIN rez:=0; x:=0.1; writeln;
for i:= 1 to 6 do
Begin fxpred:=0; fxpos:=1; n:=2; znak:=1; fak:=1;
while abs(fxpos-fxpred)>=0.001 do
Begin znak:=znak*(-1); fak:=fak*(n-1)*n;
fxpred:=fxpos;
fxpos:=fxpos+znak*exp(n*ln(x))/fak; n:=n+2;
end; writeln('x=',x*180/pi,'(
ја
¤) cos(x)=',fxpos);
x:=x+0.2; rez:=rez+fxpos; end;
writeln('rez=',rez);
readln; END.
5. Ввод – вывод
5.1. Общие положения
Ввод-вывод выполняется с помощью операторов read, readln
– читать и write, writeln
– писать. Читать и писать определяется по отношению к оперативной памяти (ОП). Так, read, readln
– читать, т. е. вводить с внешнего устройства (файла) и заносить данные в ОП, write, writeln
– писать, т.е. выводить данные из ОП на внешний файл (устройство). Файл состоит из компонент, структура которых определяется при его создании.
Внешними устройствами (файлами) могут быть: экран монитора, клавиатура, память на гибких дисках, память на жестком или лазерном дисках, линии связи и т.п. В операторах ввода-вывода указывается имя файла, с которым будет производиться ввод-вывод, этот файл считается логическим. Кроме того, есть понятие физического файла. Физический файл – это устройство, Например, гибкий магнитный диск, жесткий диск и т. д. Логический файл имеет имя, которое можно указывать в операторах ввода-вывода.
5. 2. Ввод
Ввод производится с помощью операторов read
или readln
.
Формат операторов: read (FV, х1
, х2
, ..., хn
);
или readln (FV, х1
, х2
, ..., хn
);
где FV
- имя файла, с которого считывается информация, а х1
, х2
и т.д. – ячейки памяти, в которые заносится информация, считываемая с файла. Если FV
отсутствует, то чтение производится с клавиатуры. Файл представляет собой как бы ленту с компонентами (рис 5.1):
Компонента может быть данным любого типа (см. с.9). Оператор readln
начинает считывание с начала новой компоненты, а read
может начинать не с начала. Если прежнее чтение закончилось внутри компоненты, то следующий read
будет читать с того места, на котором закончилось предыдущее чтение (рис. 5.2).
В данном случае файл организован на каком-либо носителе (например на диске) и состоит из компонент, в каждой находится по три данных. Если для чтения из файлов применить операторы read
(a, b); read
(c, d); то в памяти будет а=3.2, b=8.6, c=0.2, d=7.01; если – операторы readln
(a, b); readln
(c, d), то в памяти а=3.2, b=8.6, c=7.01, d=8.3.
Замечание
. При чтении данных с клавиатуры необходимо всегда использовать операторы readln
(х1
, х2
, ..., хn
);
(без указания имени файла).
5. 3. Вывод
Вывод производится с помощью операторов write или writeln.
Формат операторов: write
(FV, x1, x2, ..., xn);
writeln
(FV, x1, x2, ..., xn);
Работа оператора: в файл с именем FV выводится информация из ячеек оперативной памяти x1, x2, ..., xn. Если FV отсутствует, вывод производится на экран монитора. При этом оператор write
начинает вывод в то место компоненты файла, где был закончен прежний вывод, а оператор writeln
начнет вывод с начала новой компоненты. Проиллюстрируем работу этих операторов на примере вывода данных на экран монитора.
Имеется фрагмент программы (напомним, что текст в скобках { } является комментарием и машиной не воспринимается);
Var a, b, c, d : integer;
Begin a: = 25; b: = 38; c: = 126; d: = 256;
writeln (a, b, c, d); {
результат
2538126256}
writeln (a, b); writeln (c, d); {
результат
2538 }
{126256 }
writeln (' a= ', a, ' b= ', b); {
результат
a=25 b=38}
{символы в апострофах выводятся как строковая константа}
write (a, b, c, d); {
результат
2538126256}
write (a, b); write (c, d); {
результат
2538126256}
write (' a= ', a, ' b= ', b);
write (' c= ', c, ' d= ',d); {
результат
a=25 b=38 c=126 d=256 }
5. 4. Некоторые возможности ввода-вывода
Оператор Readln
; (без скобок, имени файла и списка ячеек памяти) вызовет остановку машины. Продолжение выполнения программы произойдет после нажатия кнопки Enter
. Это очень удобно при просмотре каких-либо промежуточных результатов, например:
writeln
('a= ', a); Readln;
Машина выведет а=. . . и остановится, после нажатия кнопки Enter
выполнение программы продолжится.
Оператор writeln;
вызовет переход к новой компоненте, в случае вывода на экран – к новой строке экрана. Рассмотримфрагментпрограммы:
Var i, k; integer;
Begin i: = 126; k: = 1997;
writeln ('i= ', i, ' k= ', k); {
результат
i=126 k=1997}
writeln (i: 3, k: 6); {результат 126 1997}
{числа, указанные после : определяют поле вывода, при выводе }
{данное "прижимается" в поле к правому краю 1997}
writeln (i: 7, k: 8); {результат ....126 ....1997}
Пример:
Program Prim23;Var r,pl:real;BEGIN writeln('введите радиус шара'); readln(r); pl:=4*pi*sqr(r);writeln('____________________________________________________');writeln('! площадь шара рад.r=',r:14,' = ',pl:14,'!');writeln('____________________________________________________');
readln; END.
В результате на экран выведется информация:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
! площадь шара радиусом R=хххххххххххххх = ххххххххххххххх !
- - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - -
Здесь ххххххххххххх - изображения чисел.
С помощью такого приема строятся различные таблицы.
При выводе величины Real в операторах write и writeln отводится поле шириной 18 символов для вывода данных с "плавающей точкой" в следующем формате..х.ххххххххххЕ*хх; здесь х – цифры, * – знак, который может быть '+' или '-', '.' – десятичная точка, отделяющая целую часть от дробной. Перед целой частью, в случае отрицательного данного, может стоять знак минус.
Таким образом:
в памяти машины вид оператора результат
R = 715.432 writeln (R); 7.1543200000E+02
R = -1.919e+01 writeln (R); -1.9190000000E+01
R = -567.986 writeln (R); -5.6798600000E+02
Напоминаем: Е+02 означает 102
, а 7.1543200000Е+02 равносильно математической записи 7.15432*102
.
Ширину поля вывода можно указывать для данных любого типа, например:
в памяти машины вид оператора результат
R = 511.04 writeln (R: 22); ......5.1104000000E+02
ch = 'x' writeln (ch: 3); ..x
ch = '!' writeln (ch: 2, ch: 4,ch: 3); .!...!..!
strin = 'Day N' writeln (strin: 8); ...Dau.N
S = 'RDD' writeln (S: 5, S: 5); ..RDD..RDD
Для данных типа Real можно еще указывать кроме ширины поля также количество цифр после десятичной точки.
Вывод данных с "фиксированной точкой".
в памяти машины вид оператора результат
R = 511.04 writeln (R: 8: 4); 511.0400
R = -46.78 writeln (R: 7: 2); .-46.78
R = -46.78 writeln (R: 9: 4); .-46.7800
R = -46.78 writeln (R: 12: 3); .....-46.780
Program Prim24;
Var r1,r2:real;
BEGIN r1:=-46.78; r2:=-46.78;
writeln('r1=',r1:12:3,' r2=',r2:9:4);
writeln('_______________________________');
readln
;
END
.
6. Массивы
6. 1. Описание массивов
В языке Паскаль можно обрабатывать не только отдельные переменные, но и их совокупности. Одной из таких совокупностей (структурированных) данных является массив. Массив – это упорядоченная совокупность данных, состоящих из фиксированного количества элементов одного и того же типа. Тип элементов, из которых состоит массив, может быть как скалярным, так и структурированным. Этот тип называется базовым, им может быть целый, байтовый, логический, символьный, перечисляемый, интервальный, вещественный, множественный типы и т. д.
Массивы могут быть одномерные:
вектор a1
, a2
, a3
, a4
, a5
, ...an
, т. е. линейка величин - - - - - - - - - - - -
двумерные массивы представляют собой матрицы:
a11
a12
. . . a1n
, т. е. матрицу величин или прямоугольник величин
a21
a22
. . . a2n
---- ---- ----
- - - - - - - - - - ---- ---- ----
am1
am2
. . . amn
---- ---- ----
Трехмерный массив – трехмерная матрица или параллелепипед величин, состоящий из набора двухмерных матриц (рис.6.1).
Линейка трехмерных массивов составляет четырехмерный массив, матрица трехмерных массивов (параллелепипедов величин) – пятимерный массив и т. д. Количество размерностей не ограничено, однако следует помнить о том, что количество элементов в массиве растет в геометрической прогрессии от количества размерности.
Описание массивов может быть, как и других величин, прямое или через описание типов Тype
.
Прямое описание Var
– идентификатор, идентификатор, …, идентификатор:
array
– [границы индекса, границы индекса, …, границы индекса] of
– базовый тип.
Описание через TYPE
:
TYPE
– имя типа=array [границы индекса, границы индекса, . . ., границы индекса] of базовый тип;
Var
– идентификатор, идентификатор, . . . , идентификатор: имя типа;
Пример: описать двумерные массивы с количеством элементов 4 строки по 5 элементов в каждой строке (5 столбцов),
базовый тип real
, массивов три: а, b, c
.
Прямое описание:
Var a, b, c: array [1. . .
4, 1 . . . 5] of real;
черезTYPE
:
TYPE mas=array [1. . . 4, 1. . . 5] of real;
Var a, b, c : mas;
Для указания границ массива можно применять предварительно описанные константы:
Const a1=4; a2=6;
Var mas y1: array [1. . . a1, 1. . . a2] of integer;
Доступ к элементам массива производится через переменные с индексами. Индексы должны не выходить за пределы границ в описаниях массива.
Например, описана ma: array [1. . . 12] of integer;
выделено 12 ячеек памяти для хранения целых данных типа integer с именами
ma [1], ma [2], ma [3],
и
т
.
д
. , ma [12].
Пример:
TYPE klass = ( K1, K2, K3, K4);
znak = array
[1. . . 255] of
char
;
Var
m1: znak; {описан массив с именем M1 типа znak для хранения данных}
{типа char в количестве 255 шт. M1[1], M1[2], ... , M1[255]}
M2: array
[1...60] of integer
{прямое описание, описан массив с именем}
{M2 для хранения целых величин. всего }
{ячеек 60.M2[1], ... , M2[60] }
M3: array
[1 ... 8] of
klass; {описан массив М3, выделено 8 ячеек памяти М3[1], ... , M3[8],}
{в каждой из которых могут храниться только величины из}
{klass, т. е. туда могут быть занесены только K1, K2, K3, K4}
Пример:
Program Prim25;
Var i:integer; s:real;
a:array[1..10] of real;
BEGIN
for i:=1 to 10 do
Begin writeln('введите значение величины a[',i,']');
readln(a[i]); end; {
ввод
элементов
массива
}
s:=0;
for i:=1 to 10 do
s
:=
s
+
a
[
i
]; {
нахождение
суммы
элементов
а
[
i
]
}
writeln('s=',s); readln;
END.
Здесь мы проиллюстрировали работу с одномерным массивом. Конечно, данную программу легче представить в следующем виде:
Program Prim25a;
Var i:integer; s,a:real;
BEGIN
s:=0;
for i:=1 to 10 do
begin writeln('введите значение величины a[',i,']');
readln(a); { ввод по одному а (без массива)}
{ имитация ввода элементов массива }
s
:=
s
+
a
;
writeln('s=',s); end;
readln; END.
Никаких массивов здесь не применять. На примере prim25
мы четко проследим два момента: занесение данных в массив (первый цикл) и обработка данных в массиве (второй цикл).
Пример: дана квадратная матрица. Вывести на экран элементы ее главной диагонали (элементы главной диагонали перечеркнуты)
a11
a12
a13
a14
a21
a22
a23
a24
a31
a32
a33
a34
a41
a42
a43
a44
Если принять, что индекс строк i, а столбцов j, то на главной диагонали лежат элементы, у которых i = j.
Program Prim26;
Var i,j,k:integer;
a:array[1..4,1..4] of integer;
b:array[1..4] of integer;
BEGIN
for i:=1 to 4 do
for j:=1 to 4 do
Begin
writeln('
введите
a[',i,',',j,']');
readln
(
a
[
i
,
j
])
end
;
{ввод элементов массива а закончен }
k:=1; { устанавливаем индекс для занесения b[1] }
for i:=1 to 4 do
for j:=1 to 4 do
if i=j then Begin b[k]:=a[i,j]; k:=k+1; end;
{отыскиваем и заносим в b[1] a[1,1]}
{меняем k и заносим в b[2] a[2,2] и т.д.}
writeln('на главной диагонали лежат злементы:');
writeln('a[1,1]=',b[1],' a[2,2]=',b[2],' a[3,3]=',b[3],' a[4,4]=',b[4]);
readln;
END.
В этой программе машина запросит ввод 16 элементов матрицы А, найдет элементы главной диагонали, занесет их в массив B и напечатает результат в следующем виде:
на главной диагонали лежат элементы:
A[1,1] = число
A[2,2] = число
A[3,3] = число
A[4,4] = число
Program Prim26a; Var i,j,k:integer; a:array[1..4,1..4] of integer; b:array[1..4] of integer; BEGIN for i:=1 to 4 do
for j:=1 to 4 do
Begin writeln('
ввести
a[',i,',',j,']'
);
readln(a[i,j]); end; { ввести массив а }
{ вывести элементы массива а }
for i:=1 to 4 do Begin writeln; {
перевести
курсор
на
новую
строку
}
for j:=1 to 4 do
write(a[i,j],' '); { вывести элементы в одну строку }
end;
k:=1;
for i:=1 to 4 do
for j:=1 to 4 do
if i=j then Begin b[k]:=a[i,j]; k:=k+1; end;
{отыскиваем и заносим в b[1] a[1,1]}
{меняем k и заносим в b[2] a[2,2] и т.д.}
writeln(' на главной диагонали лежат элементы:');
writeln('a[1,1]=',b[1],' a[2,2]=',b[2],' a[3,3]=',b[3],' a[4,4]=',b[4]);
readln;
END.
Эта программа отличается от предыдущей тем, что она вначале вводит массив А, затем его распечатывает в виде
a11
a12
a13
a14
a21
a22
a23
a24
a31
a32
a33
a34
a41
a42
a43
a44
а после выводит результаты в том же виде, что и программа Prim26,
т.е.
Program Prim26b;
Var i,j,k,n:integer;
a:array[1..40,1..40] of integer;
b:array[1..40] of integer;
BEGIN writeln('введите размерность массива');
readln(n);
for i:=1 to n do
for j:=1 to n do
Begin writeln('
введите
a[',i,',',j,']');
readln(a[i,j]); end;
{
вывести элементы массива а }
for
i
:=1
to
n
do
Begin writeln; {перевести курсор на новую строку}
for j:=1 to n do
write(a [i , j],' '); {
вывести
элементы
в
одну
строку
}
end;
k:=1;
for i:=1 to n do
for j:=1 to n do
if i=j then Begin b[k]:=a[i , j]; k:=k+1; end;
{отыскиваем и заносим в b[1] a[1,1]}
{меняем k и заносим в b[2] a[2,2] и т.д.}
writeln(' на главной диагонали лежат элементы:');
for k:=1 to n do
write(' a[',k,',',k,']=',b[k]);
readln;
END.
Эта программа работает так же, как и предыдущая, но с массивами и с переменными измерениями.
Величина входного массива может быть до 40 строк и 40 столбцов. Чтобы это обеспечить, в разделе Var
описываем массив a: array [1..40,1..40] of integer;
а затем в программе вводим по запросу n
, которое будет определять, с матрицей какой величины мы будем работать конкретно (n
должно быть в диапазоне 1-40). Далее все циклы программы работают от 1 до n
, т.е. машина решит задачу для массива введенной размерности n
.
Program Prim27;
Var i,j,k,n:integer;
a:array[1..40,1..40] of integer;
b:array[1..40] of integer;
BEGIN writeln('
ввести
n'); readln(n);
for i:=1 to n do
for j:=1 to n do
Begin writeln('
ввести
a[',i,',',j,']');
readln(a[i,j]); end;
{ вывести элементы массива а }
for
i
:=1
to
n
do
Begin writeln; {перевести курсор на новую строку}
for j:=1 to n do
write(a[i,j],' '); {
вывести
элементы
в
одну
строку
}
end;
k:=1;
for i:=1 to n do
for j:=1 to n do
if i+j-1=n then Begin b[k]:=a[i,j]; k:=k+1; end;
{отыскиваем и заносим в b[1] a[1,1]}
{меняем k и заносим в b[2] a[2,2] и т.д.}
writeln;
writeln(' на дополнительной диагонали лежат элементы:');
for k:=1 to n do
write(b[k],' ');
readln;
END.
Программа Prim 27
работает аналогично программе Prim 26b
, однако выводит элементы, лежащие на дополнительной диагонали.
Program Prim28;
Var i,j,min,m,n,k:integer;
a:array[1..20,1..10] of integer;
b:array[1..10] of integer;
BEGIN writeln('
ввести
m,n'); readln(m,n);
for i:=1 to m do {m –
количество
строк
}
for j:=1 to n do {n –
количество
столбцов
}
Begin writeln('
ввести
a[', i ,', ', j,']');
readln(a[i , j]); end;
{ вывести элементы массива а }
for
i
:=1
to
m
do
Begin writeln;
for j:=1 to n do
write(a[i,j],' '); end;
min:=32767; {максимальное integer, чтобы в последующем сравнивать}
{и заносить в min все элементы a[i,j], которые меньше min}
for i:=1 to m do
for j:=1 to n do
if a[i , j]<min then Begin min:=a[i , j]; k:=i; end;
writeln(' строка, содержащая наименьший элемент');
for j:=1 to n do
write(' a[', k ,',', j ,']=',a[k , j]);
readln; END.
Программа Prim 28
находит в массиве строку размером до 20х10, содержащую наименьший элемент.
Program Prim29;
Var i,j:integer; a:array[1..5, 1..7] of integer;
b:array[1..7] of integer;
c:array[1..5] of integer;
BEGIN for i:=1 to 5 do
for j:=1 to 7 do
begin writeln('
введите
a[',i,',',j,']
элемент
матрицы
а
');
readln(a[i,j]); end;
for j:=1 to 7 do
begin writeln('
введите
b[',j,']
элемент
вектора
b');
readln(b[j]); end;
for i:=1 to 5 do {начало перемножения матрицы на вектор}
begin c[i]:=0;
for j:=1 to 7 do
c[i]:=c[i]+ a[i,j]*b[j]; end;
{конец перемножения матрицы на вектор}
writeln('
распечатка
массива
а
');
for i:=1 to 5 do
begin writeln; {начать новую строку}
for j:=1 to 7 do
write(' ',a[i,j]); end; writeln;
writeln('
распечатка
массива
b');
for j:=1 to 7 do
write(' ',b[j]); writeln;
writeln('
результирующий
массив
с
');
for i:=1 to 5 do
write(' ',c[i]);
readln; END.
Программа вводит матрицу А размером 5х7 и вектор размером 7 элементов, затем их перемножает по правилу Сi = Сi + a[i,j]*b[j] и выводит пять элементов массива С.
Заметим, что для вычисления каждого с необходимо каждый элемент строки массива a
умножить на соответствующий по индексу элемент массива b
, а затем все эти произведения сложить. таким образом, количество элементов массива с
будет равно количеству строк матрицы a
(и, соответственно, количеству элементов массива b)
.
Program Prim29a;
Var i,j,n,m:integer; a:array[1..50,1..70] of integer;
b:array[1..70] of integer;
c:array[1..50] of integer;
BEGIN writeln('ввести количество строк и столбцов');
readln(n,m);
for i:=1 to n do
for j:=1 to m do
begin writeln('
ввести
a[',i,',',j,']
элемент
матрицы
а
');
readln(a[i,j]); end;
for j:=1 to m do
begin writeln('
ввести
b[',j,']
элемент
вектора
b');
readln(b[j]); end;
for i:=1 to n do {начало перемножения матрицы на вектор}
begin c[i]:=0;
for j:=1 to m do
c[i]:=c[i]+ a[i,j]*b[j]; end;
{конец перемножения матрицы на вектор}
writeln('
распечатка
массива
а
');
for i:=1 to n do
Begin writeln; {начать новую строку}
for j:=1 to m do
write(' ',a[i,j]); end; writeln;
writeln('
распечатка
массива
b');
for j:=1 to m do
write(' ',b[j]); writeln;
writeln('
результирующий
массив
с
');
for i:=1 to n do
write(' ',c[i]);
readln; END.
Программа Prim 29a
тоже перемножает матрицу на вектор. Здесь матрица может иметь размеры до 50х70, соответственно вектор B может иметь размер до 70, а вектор С – размер до 50 элементов.
7. Подпрограммы
7.1. Общие положения
В практике программирования часто встречаются ситуации, когда одну и ту же группу операторов необходимо выполнить в различных местах программы, неважно, что при этом по-разному будут называться исходные данные и результаты работы этих операторов. Важно, что эти группы операторов выполняют одну и ту же работу. Например, в различных местах программы необходимо вычислить корни квадратного уравнения, причем в одном месте это будет уравнение ax2+bx+c=0, в другом – sz2+tz+p=0, в третьем – ky2+ly+n=0 и т.д. В этом случае алгоритм вычисления корней уравнения в программе можно писать один раз в виде подпрограммы, а использовать его многократно. Блок-схема такой программы без применения подпрограммы изображена на рис. 7.1.
Блок-схема алгоритма с использованием подпрограммы изображена на рис. 7.2.
Подпрограммой называется имеющая имя логически законченная группа операторов (возможно со своими описаниями), к которой по имени можно обратиться для выполнения неограниченное количество раз из различных мест основной программы, возможно, с различным, но фиксированным набором входных величин и результатов. Подпрограммы могут быть оформлены в виде функций и процедур.
Функции применяют тогда, когда результат работы подпрограммы один. Обращение к функции может записываться в выражениях, например: (а+b)/cos(x).
Здесь cos(x)
есть обращение к подпрограмме типа "функция", правда, стандартной, а не написанной пользователем. Встретив имя cos,
машина с входной величиной x
обращается к подпрограмме, вычисляет с помощью ряда функцию cos(x)
(см. программу в подразд. 4.4.), и результат этой работы в виде значения функции возвращается в арифметическое выражение. Функция может иметь несколько входных параметров, но всегда один результат. Процедура также может иметь несколько входных параметров, но несколько результатов. Несколько – это 0, или 1, или 2, или 3 и т.д. результатов. Обращение к процедуре состоит из отдельного оператора. Например, обращение к процедуре, вычисляющей корни квадратного уравнения, может иметь вид: root
(
a
,
b
,
c
,
x
1,
x
2);
Подпрограммы, как функции, так и процедуры могут быть стандартными, например sin(x), cos(x), sqrt(x), succ(y), ord(y)
и т.п.; библиотечными, которые становятся доступными при подключении модулей и библиотек (см. далее), а также определены пользователем, т.е. написаны программистом для решения своей задачи.
7.2. Подпрограммы-функции, определенные пользователем
Функции пользователя описываются в разделе описания функций и процедур основной программы. Описание функции строится как законченная программа, т.е. может состоять из заголовка и шести разделов: описания, меток, констант, типов, переменных, функций и процедур и раздела операторов. Заканчивается описание функции символом точка с запятой.
Написать программу, вычисляющую с помощью подпрограммы-функции, выражение:
f1(x)=x+256.4; f2(y)=y+256.4; f3(z)=z+256.4;
Program Prim30;
Var
x,y,z,f1,f2,f3:real;
function f(x:real):real; {
заголовок
функции
;}
{ f – имя функции, это же и имя}
{результата, х – формальный параметр}
Begin f:=(x+256.4); end; {тело функции}
BEGIN {начало основной программы}
writeln('ввести x,y,z'); readln(x,y,z);
f1:=f(x); {обращение к подпрограмме f с фактическим параметром x}
f2:=f(y); {обращение к подпрограмме f с фактическим параметром y}
f3:=f(z); {обращение к подпрограмме f с фактическим параметром z}
writeln(f1:20,f2:20,f3:20); readln; END.
Написать программу, вычисляющую G:
Оформим вычисления в виде подпрограммы-функции:
Program Prim31;
Var h,x,y,z,g:real;
function f(a,b:real):real; {
входные
формальные
параметры
a,b}
Begin
f:=sqr(ln(a)+sin(b))/(cos(a)*exp(b));
end;
BEGIN writeln ('введите положительные h,x,y,z');
readln(h,x,y,z);
if (x>=1) and (x<3) then writeln('g=',h+f(x,y)) else;
if (x>=3) and (x<5) then writeln('g=',sqrt(h)+f(z,x)) else;
if (x>=5) and (x<=9) then writeln('g=',sqr(h)+f(y,z)) else;
writeln('g=0');
readln; END.
В этой программе описание формулы начинается словом function,
имя функции f
, результат вычисления функции типа real
. Тело функции заключено в операторные скобки begin, end
; a, b
называются формальными параметрами
. В данной функции нам не понадобились разделы описаний.
При выполнении основной программы, которая начинается begin
, встречается выражение f(x, y)
. Встретив такое выражение, машина по имени f
определяет, что это обращение к функции. затем машина проверяет совпадение количества и типа фактических параметров (x, y)
с формальными (a, b)
. При их совпадении в тело функции вместо формальных параметров подставляются фактические и тело выполняется, полученный результат используется при вычислении выражения, стоящего в операторе writeln
.
Составить программу вычисления при условии, что а<
b
:
Если a и b не укладываются в заданные пределы, нужно сообщить об этом пользователю и спросить, будут ли другие диапазоны — ответ: "Y, N". Если заданы не те буквы (y, n), повторить вопрос.
Прежде чем писать программу, определимся с функциями:
оформим в виде функции f1;
– в виде f2;
sin(x)+f1 – в виде f3;
cos(x)+f1 – в виде f4;
cos(x)-f2 – в виде f5;
вычисления по методу трапеций с точностью 0.1 oформим в виде подпрограммы-функции f6.
Program Prim32; label NAH,P;
Var b,a,z:real;
lit:char;
function f1(x:real):real;
Begin f1:=exp(x/10)+sqrt(x/(x+3)); end;
function f2(x:real):real;
Begin f2:=sqrt(sqr(x)/(3*x+10)); end;
function f3(x:real):real;
Begin f3:=sin(x)+f1(x); end;
function f4(x:real):real;
Begin f4:=cos(x)+f1(x); end;
function f5(x:real):real;
Begin f5:=cos(x)-f2(x); end;
function f6(a,b:real):real;
label K,N1,K1,KC,T;
Var h,s1,s,x:real; i,n:integer;
Begin
s1:=9.999e+10; n:=10;
N1: h:=(b-a)/n; s:=0; x:=a;
for i:=1 to n do
Begin if a>b then goto t else
if (0<=a)and(b<5) then Begin s:=s+(f3(x)+f3(x+h))/2*h;
goto kc; end else
if (5<=a)and(b<10) then Begin s:=s+(f4(x)+f4(x+h))/2*h;
goto kc; end else
if (10<=a)and(b<=16) then Begin s:=s+(f5(x)+f5(x+h))/2*h;
goto kc; end else goto t;
KC: x:=x+h; end;
if abs(s-s1)<0.1 then goto k
else Begin s1:=s; n:=n*10; goto n1; end;
K
:
f
6:=
s
;
goto
k
1;
T: writeln('пределы интегрирования не соответствуют условию');
f6:=-9999999999.;
K1: end;
BEGIN
NAH: writeln('
введите
значения
a,b');
readln(a,b); z:=f6(a,b);
if z=-9999999999. then goto p;
writeln('z=',z);
P: readln;
writeln(' будем еще вычислять z ? , если "да" ',
'то нажмите клавишу "y" , если нет, то любую клавишу ');
readln(lit);
if (lit='Y') or (lit='y') then goto NAH;
END.
7.3. Подпрограммы-процедуры
Описание процедуры:
Procedure
имя (входные формальные параметры: тип;
Var
выходные формальные параметры: тип);
описания (если они есть)
begin
операторы
end;
Пусть необходимо найти корни квадратных уравнений
ax2+bx+c=0,
ky2+my+d=0,
sz2+tz+p=0,
где коэффициенты a, b, c вводятся по запросу. количество уравнений не ограничено. результаты вычислений выводить на экран (в основную программу не возвращать), см. рис. 2.1.
Program Prim33;
label K,NAH;
Var let:char; a,b,c:real;
procedure root(a,b,c:real); {процедура не имеет выходных параметров}
label K;
Var d,x1d,x1m,x2d,x2m:real;
Begin
if
a
=0
then
Begin
writeln('уравнение первой степени, корень один');
x1d:=-c/b; writeln('x=',x1d); goto K; end
else d:=b*b-4*a*c;
if d>=0 then Begin
writeln('уравнение второй степени, корни действительные');
x1d:=(-b-sqrt(d))/(2*a);
x2d:=(-b+sqrt(d))/(2*a);
writeln('x1d=',x1d,' x2d=',x2d); goto K; end
else writeln('уравнение второй степени, корни комплексные');
x1d:=-b/(2*a); x2d:=x1d;
x1m:=-sqrt(-d)/(2*a); x2m:=-x1m;
writeln('z1=',x1d,' ',x1m,' i;');
writeln('z2=',x2d,' ',x2m,' i;');
K: end;
BEGIN NAH: writeln('
введите
a,b,c'); readln(a,b,c); root(a,b,c);
writeln('будет еще уравнение? если "да", нажмите клавишу"Y"',
'если "нет", нажмите любую клавишу');
read(let);
if (let='Y') or (let='y') then goto nah else goto K;
K: END.
Найти x, y, z — корни системы уравнений:
Как известно из линейной алгебры ,
где
Раскрытие определителя
|
|
производится по схеме: т.е.
в процедуре a
,
b
,
c
,
d
– входные данные, x
,
y
,
z
– результаты.
Program Prim34;
label N,K;
Type w=array[1..3] of integer;
Var a,b,c,d:w; x,y,z:real; let:char;
function det(a:w;b:w;c:w):real;
Begin det:=a[1]*b[2]*c[3]+b[1]*c[2]*a[3]+c[1]*a[2]*b[3]
-c[1]*b[2]*a[3]-a[1]*c[2]*b[3]-b[1]*a[2]*c[3]; end;
procedure ur(a,b,c,d:w; Var x,y,z:real);
Var d0:real;
Begin d0:=det(a,b,c);
if d0=0 then Begin writeln('det=0
решения
нет
');
let:='0'; Exit; end else
{EXIT – выход из процедуры}
x:=det(d,b,c)/d0;
y:=det(a,d,c)/d0;
z:=det(a,b,d)/d0; let:='1'; end;
BEGIN N: writeln('
введите
a1,b1,c1,d1'); readln(a[1],b[1],c[1],d[1]);
writeln('
введите
a2,b2,c2,d2'); readln(a[2],b[2],c[2],d[2]);
writeln('
введите
a3,b3,c3,d3'); readln(a[3],b[3],c[3],d[3]);
ur(a,b,c,d,x,y,z);
if let='0' then goto K else
writeln(' / ',a[1],'x+',b[1],'y+',c[1],'z=',d[1]);
writeln('
система
i ',a[2],'x+',b[2],'y+',c[2],'z=',d[2]);
writeln(' ',a[3],'x+',b[3],'y+',c[3],'z=',d[3]);
writeln('имеет решение: x=',x,' y=',y,' z=',z);
K: writeln('Будет ещё ур-е? да - "Y" , нет – любая клавиша ');
read(let);
if (let='Y') or (let='y') then goto N;
END.
Имеется одномерный массив. Необходимо определить сумму положительных элементов, номер последнего отрицательного элемента, количество отрицательных элементов массива.
Задача 1. Массив один и состоит из 7 элементов.
Задача 2. Массивов два, размерность первого – 7 элементов, второго – 5.
Задача 3. Количество массивов не ограничено, количество элементов в массивах произвольное, но не более 70.
Program Prim35; {
массив
1
и
состоит
из
7
элементов
} label j; Type mas=array[1..7] of real; Var n,k,i,no:integer;
a:mas;
s:real; ch:char;
procedure prmas(a:mas;n:integer; Var s:real; Var k,no:integer);
Var i:integer;
Begin s:=0; k:=0; no:=0;
for i:=1 to n do Begin
if a[i]>=0 then s:=s+a[i] else Begin k:=i; no:=no+1;
end; end; end;
BEGIN
for i:=1 to 7 do Begin
writeln('ввести значение
a[',i,']');
readln(a[i]); end;
prmas(a,7,s,k,no);
j: writeln('сумма положительных элементов =',s);
writeln('последний отрицательный элемент имеет
N=' no);
writeln('количество отрицательных элементов =', k);
readln;
END.
Program Prim36; {
массива
2,
размерность
первого
массива
7,
второго
– 5} label j; Type mas=array[1..7] of real; Var k,no,y:integer; s:real; ch:char; procedure prmas(n:integer; var s:real; var k,no:integer);
Var i:integer; a:mas;
Begin for i:=1 to n do Begin
writeln('введите ',i,' значение элемента массива');
readln(a[i]); end;
s:=0; k:=0; no:=0;
for i:=1 to n do begin
if a[i]>=0 then s:=s+a[i] else begin k:=i; no:=no+1;
end; end; end;
BEGIN prmas(7,s,k,no); y:=0;
j: writeln('сумма положительных элементов =',s);
writeln('последний отрицательный элемент имеет
N=', no);
writeln('количество отрицательных элементов =', k); y:=y+1;
if y=1 then Begin prmas(5,s,k,no); goto j; end
else readln;
END.
Program Prim37; {
массивы
с
переменными
измерениями
,
количество
массивов
не
ограничено
} Type mas=array[1..70] of real; Var n,k,i,no,kol,r,j:integer; a,b:mas; s:real; ch:char; procedure prmas(n:integer; var s:real; var k,no:integer); var i:integer; a:mas;
begin for i:=1 to n do begin
writeln('введите ',i,' значение элемента массива ', j);
readln(a[i]); end;
s:=0; k:=0; no:=0;
for i:=1 to n do Begin
if a[i]>=0 then s:=s+a[i] else Begin k:=i; no:=no+1;
end; end; end;
BEGIN
writeln('
задайте
количество
массивов
'); readln(kol);
for j:=1 to kol do Begin
writeln(' задайте размерность массива', j); readln(r);
prmas(r,s,k,no);
writeln(' сумма положительных элементов =',s);
writeln(' последний отрицательный элемент имеет N=', no);
writeln(' количество отрицательных элементов =', k); end;
readln;
END.
7.4. Локальные и глобальные описания объектов
Мы уже знаем, что программа – блок, т.е. раздел операторов, снабженный описаниями и имеющий заголовок. Вид блока-программы:
Program
имя программы (возможны опции); {опции не обязательны}
Label …;
{раздел описания меток}
Co
n
st …;
{раздел описания констант}
Туре …;
{раздел определения типов}
Var
…;
{раздел описания переменных}
Function …; Procedure …;
{раздел описания функций и процедур}
BEGIN ... END.
{раздел операторов}.
Функции и процедуры, в свою очередь, также являются блоками:
Procedure
имя (список входных формальных параметров);
Var
(список выходных формальных параметров);
Label …;
Const …;
Туре
…;
Var ...;
function …;
procedure …;
разделыописаний
begin ... end;
{телопроцедуры}
Таким образом, программа – всегда блок, в который могут быть вложены другие блоки.
Как один из вариантов, возможна следующая структура программы:
Program Prim38; {
начало
блока
1} label N,M; Const k=5.6; Type d=array[1..10] of integer; Var b,c:real; i,j:integer; z,y:d;
function f(f,b,c:real):real; {
начало
блока
2}
begin f:=1; end; {
конец
блока
2}
procedure proc(f,b,c:real; Var x,y,z:real); {
начало
блока
3}
label K,L;
var d,w,s:real;
function fp(a,b:real):real; {
начало
блока
4}
begin fp:=1; end; {
тело
fp,
конец
блока
4}
begin x:=1; y:=1; z:=1; end; {
тело
proc,
конец
блока
3}
BEGIN
b
:=1;
END
. {тело основной программы, конец блока 1}
Таким образом, программа состоит из четырех блоков. Все имена меток, констант, типов, переменных, функции f
и Р
r
ос
известны в блоке 1, поскольку они даны в его описании. Считается, что они описаны здесь локально.
В блоке 2 – function
– описаний нет, поэтому своих собственных объектов этот блок не имеет. Формальные параметры не в счет, поскольку они служат только для описания алгоритма вычисления результата с именем f
в функции f
, а ячейки памяти для b, с, f
здесь не выделяются. Однако в этом блоке можно использовать все объекты, которые описаны в блоке 1, так как блок 2 является составляющей частью блока 1. Иногда говорят, что имена объектов блока 1 описаны глобально для блока 2.
Аналогичная ситуация и с блоком 3 – Procedure
Р
r
ос
. Для нее все объекты блока 1 являются глобальными, т.е. доступны. Кроме того, в блоке 3 имеются свои описанные здесь объекты – метки К, L, переменные
d
, W, 8, функция fp
, которые могут быть использованы только в блоке 3 и не известны в блоках 1 и 2.
Как следствие возможно применение одинаковых имен в различных блоках (см. имя d
). В блоке 1 d
– массив. В блоке 3 (в Р
r
ос)
имеется свое d
, которое является собственным в блоке 3 и представляет собой не массив, а ячейку памяти типа real
.
8. Строковые данные
8.1. Общие замечания
Строка – это последовательность символов длиной 0-255. Для описания данных строкового типа используется слово string
, за которым могут следовать в квадратных скобках цифры, определяющие количество символов в строке. Если цифры в квадратных скобках и сами скобки отсутствуют, то для данной ячейки памяти будет выделяться максимально возможная длина: 256 байт для хранения 265 символов. Символьные константы (которые могут храниться) имеют вид совокупности символов, заключенных в апострофы.
Пример: 'a, b, с - символы'.
Примеры описаний:
Var а, b, с: string [70];
Выделяются ячейки с именами а, b, с, в каждую из которых может быть занесена совокупность символов в количестве до 70.
Например, возможны операторы:
а: = 'улица Садовая';
b: = улица Чкалова, 17, хаи';
с: = г. Харьков – большой город';
возможно предварительное описание типа:
Туре
a
=
string
[70];
Var b, с: а;
8.2. Строковые выражения
Выражения, в которых операндами служат строки, являются строковыми выражениями. Результат – строка. Опишем операции, которые можно применять при написании строковых выражений:
Операция сцепления, знак операции '+'
.
'Дом'+' номер'+'43'
дает результирующую строку 'Дом номер 43'
.
Операции отношения: =, < >, >, <, >=, <=.
Операции отношения выполняются раньше операции сцепления, т.е. имеют более высокий приоритет
.
Сравнения между строками производятся посимвольно, слева направо, до первого несовпадающего символа. Та строка считается больше, в которой первый несовпадающий символ имеет больший код по таблице кодов. Результаты сравнения – True
или False
.
Если строки имеют различную длину и более короткая совпадает с началом более длинной, то последняя считается большей.
При использовании оператора присваивания, если значение результата вычисления строкового выражения имеет большую длину, чем ячейка памяти, в которую записывается результат, то лишние правые символы отбрасываются. Если значение результата вычисления строкового типа короче, чем ячейка памяти, отведенная для его хранения, то результат записывается в ячейку памяти «прижатым» вправо, а лишние левые разряды заполняются пробелами.
Допускается при записи выражений строкового типа применять данные, описанные с атрибутом char
. В этом случае эти данные интерпретируются как string
[ 1]. К отдельным символам данного строкового типа можно обратиться по номеру этого символа в строке (аналогично индексу в массивах). В нулевом байте хранится длина строки.
Program
Prim
39;
var
st
1,
st
2:
string
[30];
BEGIN
st
1:='отдел № 256';
writeln
(
st
1); {на экране "отдел № 256"}
st
2:=
st
1[10];
writeln
(
st
2); {на экране "5"}
writeln
(
ord
(
st
1[0])); {на экране "11"}
readln; END.
Если бы вvar
было указано string[10], то writeln(st1), вывел бы результат "отдел № 25"
8.3. Стандартные процедуры и функции для обработки строк
8.3.1. Процедуры обработки строк
Delete (st, Poz, N)
– удаление N символов из строки с именем st
, начиная с позиции Poz
.
st
:='река_Волга'; Delete (st, 1, 5);
Результат 'Волга'.
insert (stl, st2, poz);
– вставка строки stl
в строку st2
, начиная с позиции Poz.
st1: = 'Дом_25_'
st2: =' На_улице_живет_петух_';
insert (stl, st2, 10);
Результат: "На_улице_дом 25_живет_петух";
st
r
(IBR, st);
преобразует число IBR
(типа integer, byte
или Real
) и помещает результат в строку st
. Возможно после IBR
указать ширину поля. Если ширины поля не хватает, оно автоматически расширяется до нужной величины.
str (1500:6, stl); даст результат '_1500';
str (4.8е+03:10, stl); – результат '_ 4.800E+03';
str (-46854:3, stl); – результат '-46854'.
Val (st, IBR, Cod)
; процедура преобразует значение st
в величину целочисленного или вещественного типа и помещает результат в IBR
. Значение st
должно содержать символьное изображение числа и не содержать символов, не присущих изображению чисел (например, пробелов перед цифрами), букв и т.п. Cod
- целочисленная переменная индуцирующая ошибку. Если Cod=0, преобразование произведено без ошибки, если Cod=5, то ошибка при преобразовании – 5 символов.
Программа Program Prim 40; иллюстрирует работу вышеописанных процедур:
Program Prim40; var st1,st2:string[30];
BEGIN st1:=' река Волга ';
delete(st1,1,5); writeln(st1);
st1:='
дом
25 '; st2:='
на
улице
живет
петух
';
insert(st1,st2,10); writeln(st2);
str(1500:6,st1); writeln(st1);
str(4.8e+03:10,st1); writeln(st1);
str(-46854:3,st1); writeln(st1);
readln;END.
8.3.2. Функции обработки строк
Сору (st, Poz, N)
выделяет из st
подстроку длиной N
символов, начиная с позиции Poz
.
stl:='absdefg'; writeln (Сору (stl, 2, 3));
результат bсd
Co
n
st (stl, st2,..., stn)
выполняет сцепление строк stl... stn
. Длина суммарной строки не должна превышать 255 символов.
Length (st)
определяет длину строки, результат – integer
.
Pos (stl, st2)
обнаруживает первое появление строки stl
в строке st2
. Результат – целое число, определяющее номер позиции, в которой находится первый символ подстроки st1
. Если st1
не содержится в строке st2
, то результат равен 0.
UpCase (ch)
преобразует строчную букву в прописную.
Параметр и результат имеют литерный тип.
ch:=a'; UpCase (ch) имеет результат 'A'.
Program Prim 41, Prim 42, Prim 43
иллюстрируют работу вышеописанных функций.
Program Prim41; var st1,st2:string[30]; s:char; BEGIN st1:='
отдел
№ 256'; writeln(copy(st1,7,5)); st2:='
находится
в
НИИ
5';
writeln(concat(st1,st2));
writeln(length(st2));
st2:='n 256';
writeln(pos(st2,st1));
s:='a';
writeln(upcase(s));
readln;END.
Program Prim42; {программа удаляет все пробелы в строке, стоящие в строке слева, если они имеются}
Var str:string[255]; { Var str: string;
Var dlina:byte;
Begin dlina:=Ord(stroka[0]);
while ((dlina>0)and(copy(stroka,1,1)=' '))do
delete(stroka,1,1);
del:=stroka;
end;
BEGIN writeln('
readln(str);
writeln(del(str)); readln;
END.
Program Prim43; { Даны три исходные строки A,B,C. В строке А определить первую бук } { ву; Затем заменить первую букву строки А со строчной на заглавную; } { объединить в одну строку A,B,C; Определить длины строк A,B,C} { и в результирующей строке вставить '-' между составляющими ее}{ строками. В результирующей строке найти номер позиции, в которой } { буква "а" встречается первый раз; определить длину результирующей } { строки. После каждого действия печатать результаты. }
Begin
delete(A,1,1); writeln(A);
writeln(upcase(ch[1]));
insert(upcase(ch[1]),A,1); writeln(A);
str:=concat(A,B,C); writeln(str);
d1:=length(A); d2:=length(B); d3:=length(C);
writeln('
writeln(str);
writeln('первый раз буква "а"стоит в результирующей строке ', 'в позиции ',pos('а',str)); writeln('общая длина строки =',length(str));
readln; END.
Ранее мы рассматривали структурированные данные, состоящие из компонент одного типа (массивы). Однако на практике часто необходимо иметь под одним именем совокупность данных различного типа. Например, информация о студенте может состоять из данных: фамилия, имя, отчество (тип string
Для объединения разнотипных данных под одним именем и возможности последующей их обработки в языке Pascal
Запись
Между record
end;
Var
F
Объем памяти, выделяемый в разделе Var,
М
V. Nomer:=3789;
М
V. Marka:='Таврия';
В операторах ввода-вывода: writeln
Допускается применение операторов присваивания к записям в целом, если они имеют одинаковые структуры. Так, для приведенного выше описания записей М
После выполнения этого оператора значения полей записи V
В ряде задач удобно пользоваться следующими массивами записей: Туре
FIO: string [30];
Prof: string [30); end;
Var List: array [1..50] of Person;
Здесь массив List
Сама запись может иметь поля любого известного нам типа, в том числе и массивного. Допускается, чтобы поле записи само было записью. Обращение к полям записи с помощью составных имен имеет несколько громоздкий вид, что особенно неудобно при использовании мнемонических идентификаторов длиной более 5 символов. Для облегчения этой ситуации в языке Pascal есть оператор with,
with имя переменной типа запись do
begin
Один раз указав в операторе with
без применения оператора with
М.
M
М.
М.
end;
Составить программу учета успеваемости студентов курса, состоящего из шести групп до 30 студентов в каждой группе. Каждый студент сдавал экзамены по пяти дисциплинам: высшая математика, основы информатики, философия, история Украины, архитектура ЭВМ. По каждому предмету можно получить оценки 2, 3, 4, 5. Каждый экзамен можно сдавать до трех раз. Произвести анализ: если у студента имеется три двойки по одному предмету или три непересданные двойки по трем предметам, то он должен быть отчислен; если студент все двойки пересдал, то его нужно поругать. Program Prim44;
label u,w;
type mo=array[1..5,1..3] of 0..5;
st=record
namb:integer;
fio:string[20];
o:mo; end;
var
gr:array[1..6,1..30] of st;
i,j,k,l,kol_dvoek,v,kgr,n:integer;
md:mo; ch:char;
predmet:string; kst:array[1..6] of byte;
procedure rea_ocenki(fio:string;Var oc:mo);
Var i:integer;
begin
for i:=1 to 5 do
Begin
case i of
1:predmet:='
2:predmet:='
3:predmet:='
4:predmet:='
5:predmet:='
writeln('
M1: readln(oc[i,1]);
if (oc[i,1]<2) or (oc[i,1]>5) then
Begin writeln('введите правильно оценку'); goto M1; end;
if oc[i,1]>2 then Begin oc[i,2]:=0; oc[i,3]:=0; goto M4; end else
M2: writeln('введите вторую оценку студента ',fio,' по ',predmet);
readln(oc[i,2]);
if (oc[i,2]<2) or (oc[i,2]>5) then
Begin writeln('введите правильно оценку'); goto M2; end;
if oc[i,2]>2 then begin oc[i,3]:=0; goto M4; end else
M3: Writeln('введите третью оценку студента ',fio,' по ',predmet);
readln(oc[i,3]);
if (oc[i,3]<2) or (oc[i,3]>5) then
begin writeln('введите правильно оценку'); goto M3; end;
M
BEGIN { начало блока ввода оценок студентов}
writeln('при вводе оценки набираются: 5, если экзамен');
writeln('сдан на 5 и, если были пересдачи, то 2,2,3 ');
z
writeln('задайте количество групп, не более 6 ');
readln(kgr);
for i:=1 to kgr do { установка индекса группы }
begin case i of { определяем группу по
1:n:=610;
2:n:=611;
3:n:=612;
4:n:=613;
5:n:=614;
6:n:=615;
else writeln('неправильно задано количество групп'); goto 2; end; end;
writeln('задайте количество студентов в группе ',n);
readln
for j:=1 to kst[i] do { установка номера студента
begin with gr[i,j] do { работать без составных имен }
begin namb:=n; writeln('
readln(fio);
for k:=1 to 5 do {
for l:=1 to 3 do
o[k,l]:=0;
writeln('введите оценки студентов ',fio);
rea_ocenki(fio,o); end;end;end;
{ конец ввода оценок студентов }
{ отображение на экране введения оценок }
for i:=1 to kgr do
for j:=1 to kst[i] do
Begin with gr[i,j] do
Begin for k:=1 to 5 do
write(o[k,1],o[k,2],o[k,3],' '); writeln; end; end;
{ конец вывода на экран оценок }
{ начало блока анализа успеваемости студентов }
for i:=1 to kgr do {
for j:=1 to kst[i] do {
Begin
with gr[i,j] do
Begin
for k:=1 to 5 do {
Begin
{ итак, анализируем состояние успеваемости студента, информация }
{ о котором хранится в записи gr[i,j]; так как мы работаем под уп-}
{равлением оператора with gr[i,j], то можно пользоваться не }
{ составными именами полей }
case k of { определить название предмета j }
1:predmet:='основы информатики';
2:predmet:='высшая математика ';
3:predmet:='философия';
4:predmet:='архитектура ЭВМ';
5:predmet:='
if o[k,1]=2 then if o[k,2]=2 then if o[k,3]=2 then begin
writeln('студент ',fio,' группы ', namb,' подлежит отчислению так как');
writeln('имеет три двойки по предмету ',predmet);
v:=1; readln; goto w; end { на новый предмет }
else Begin kol_dvoek:=kol_dvoek+2; goto w; end
else Begin kol_dvoek:=kol_dvoek+1; goto w; end;
w: end;
if v=1 then goto u {
else if kol_dvoek=0 then goto u
else Begin
writeln('студент ',fio,' группы ',namb,' является разгильдяем так как');
writeln('имеет в зимнюю сессию ',kol_dvoek,' двоек и является');
writeln('кандидатом на отчисление в весеннем семестре');
readln; end; end;
u: end; END.
Программа снабжена комментариями, поэтому при внимательном рассмотрении читается легко. Трудности могут возникнуть при разборе блока анализа результатов, поэтому мы приведем блок-схему логической части этого блока (рис. 9.1). 9.1. Комплексные данные
При работе с комплексными данными удобно пользоваться записями с двумя полями, первое содержит информацию о действительной части данного, а второе – о мнимой части данного. Program Prim45;
Type complex=record
deistv:real; mnim:real;
end;
Var a,b,c:complex;
BEGIN
a.deistv:=6.3;
a.mnim:=1.9; END.
9.2. Запись с вариантами
Записи, описанные выше, имеют строго определенную структуру. однако есть возможность создавать записи, имеющие несколько вариантов одного и того же поля. Вариантные поля записываются после описания безвариантных полей с помощью оператора Case
ТУРЕ
zap=record
описание безвариантных полей;
Case имя поля: тип имени поля of
список констант выбора: (поле,... тип); ...
список констант выбора: (поле,... тип);
end;
Пример: Туре zap=record Nomer: byte; {фиксированные поля} Articul: integer; Case Flag: boolean of {вариантныеполя} TRUE: (cena l: integer); FALSE: (cena 2; real); end; Var P, Si Zap; поле Cena l
поле Cena 2
При использовании записей с вариантами необходимо придерживаться следующих правил: - все имена полей должны отличаться друг от друга, даже если они встречаются в различных вариантах; - запись может иметь только одну вариантную часть, причем вариантная часть должна размещаться в конце её; Если поле, соответствующее какой-либо метке, является пустым, то оно записывается следующим образом: список констант выбора: ( );
Program
Type zap=record
nomer:byte;
artikul:integer;
case flag:boolean of
true:(cena1:integer);
false:(cena2:real); end;
Var h,s:zap;
BEGIN with h do
Begin nomer:=1; artikul:=2345; flag:=true; cena1:=25;
writeln('nomer=',nomer,' artikul=',artikul,' cena1=',cena1);
flag:=false; cena2:=3.2;
writeln('cena2 ',cena2);
end
10.1. Общие замечания В практике программирования часто встречаются задачи, решаемые с применением малоизменяемых во времени данных. К ним относятся, например, задачи бухгалтерского учета оптимального планирования и т.п. Ввод данных с клавиатуры при каждом счете задачи очень трудоемок, а иногда просто невозможен из-за временных ограничений. Для решения этой проблемы в языках программирования реализована концепция файлов, что позволяет после разового набора информации запомнить ее на внешнем носителе и обращаться к ней непосредственно из обрабатывающих программ при каждом счете задачи. Файл
Файл может быть связан с внешним носителем информации, т.е. располагаться на магнитном или СД диске, магнитной ленте, клавиатуре при вводе информации или на экране, принтере и при выводе её и т.д. Файлы бывают стандартными, т.е. определенными разработчиками или администраторами операционной системы или вычислительной среды, а также пользователем, т.е. человеком, составляющим программы в каком-либо алгоритмическом языке (например в Pascal), или с помощью других программных продуктов (баз данных, редакторов и т.д.). Каждый файл имеет свое имя, которое зарегистрировано в соответствующей директории (оглавлении). Определение файлового типа строится по такой схеме: Туре
Var
Например: Туре zap=record Nom: integer; FIO: string [20]; oklad: real; end; Ft=file of zap; Var a, b, с: Ft; Описаны три файла с именами а,
При работе с файлом «внимание» машины сосредоточено на компоненте, определенной указателем файла (этой компонентой будет работать машина при следующем обращении к файлу). Имя файла должно быть уникальным и состоящим из собственного имени и необязательного расширения – типа файла, содержащего три символа и отделенного от основного имени точкой. Расширение, как правило, указывает в мнемонической форме на содержимое файла: pas
Каждый диск, содержащий файлы, имеет оглавление, в которое помещается информация о его имени, расширении, времени и дате его создания, о местонахождении на физическом носителе (например, на диске С
Для поиска файла необходимо указать диск, каталог, подкаталог, имя файла, его расширения. Например: C:TURBOPrimPrim46.pas
Здесь файл Prim 46.pas
10.2. Стандартные процедуры и функции для работы с файлами Далее примем обозначения: FV
Assig и (FV, str);
Имя файла, которое является значением str
Rewrite (FV);
Reset (FV);
Read (FV, Р);
Write (FV, Р);
Seek (FV,
Fl
Close (FV);
Erase (FV);
Rename (FV, str);
Truncate (FV);
Eof (FV)
Filepos (FV)
Filesize (FV)
Loresult (FV)
10. 3. Стандартные файлы Con
Все внешние устройства ЭВМ трактуются в Pascal
Trm
Kbd
P
Aux
Usr:
10.4. Файлы последовательного доступа, созданные пользователем
Работа с файлом последовательного доступа предполагает его создание, обработку и корректировку. Для создания файла последовательного доступа необходимо: - объявить файловую переменную; - «привязать» файл к физическому носителю информации (присвоить файлу имя). (Assign
- открыть новый файл (Rewrite
- подготовить информацию для ввода в компоненту файла, т.е. сформировать запись для ввода в файл в качестве компоненты; - записать в файл компоненту (Write
- повторить п. 4, 5 необходимое количество раз; - закрыть созданный файл (Close
Для доступа к компонентам последовательного файла (например, для просмотра содержимого файла на экране или для обработки компонент в целях включения их в качестве фрагментов в программу обработки каких-либо данных и т.п.) следует: - присвоить файлу имя (Assign
- открыть уже существующий файл (Reset
- считать текущую компоненту из файла в рабочую область памяти (как правило, типа запись со структурой компоненты), (Read
- выполнить обработку информации (например, вывести на экран поля записи); - закрыть файл (Close
Возможны три типа корректировки файла как прямого, так и последовательного доступа: 1. Расширение файла за счет внесения новых компонент. 2. Полная замена содержимого компоненты. 3. Замена каких-либо полей отдельных компонент. Замена содержимого компонент отдельных записей или замена полей отдельных записей будет рассмотрена в следующем подразделе при изучении корректировки компонент файлов прямого доступа. Добавление новых записей в файл последовательного доступа выполняется путем записи компонент в конце файла. Маркер конца файла при этом переносится. Естественно, на физическом носителе при этом должно иметься свободное пространство. Для записи новых компонент в конце имеющегося файла необходимо: - присвоить файлу имя (Assign
- открыть уже существующий файл (Reset
- установить указатель файла за последней компонентой (Seek (FV, File sise (FV)):
- создать в специально выделенной области памяти (как правило записи) новую компоненту; - записать новую компоненту в файл (write
- закрыть файл (Close
Пример. Организовать последовательный файл с именем PRIM bibl.dos
Program Prim47;
type books=record {
nomer:integer;
avtor:string[16];
nazv:string[30];
index:integer; end;
var bf:file of books; {
rb:books; { участок памяти со структурой }
{
procedure org;
begin assign(bf,'C:TURBOPRIMbibl.dos');
Rewrite(bf);
with rb do { работать с записью rb без уточненных имен }
while True do
begin writeln('
readln(nomer);
if
Begin close(bf); Exit end;
writeln('
readln(avtor);
writeln('ввести название книги');
readln(nazv);
writeln('ввести значение индекса');
readln(index);
write(bf,rb); { записать компоненту из rb в файл }
end; end;
procedure Obr;
Begin Assign(bf,'C:TURBOPRIMbibl.dos');
Reset(bf);
with rb do
while not Eof(bf) do{
begin read(bf,rb);
writeln(nomer:5,avtor:16,Nazv:10,index:6); {
end; Close(bf); end;
procedure Rash;
begin Assign(bf,'C:TURBOPRIMbibl.dos');
Reset(bf);
Seek(bf,Filesize(bf)); { установить указатель на конец файла }
with rb do
while True do
begin writeln('
if nomer=9999 then begin Close(bf);Exit end;
writeln('
writeln('ввести название книги'); readln(nazv);
writeln('ввести значение индекса'); readln(index);
write(bf,rb); end;end;
BEGIN {
Org; Obr; Rash; Obr; readln;
END.
При создании больших программ их части удобно создавать в виде отдельных файлов (объектов), которые затем с помощью директивы компилятора {$i...} можно объединить в одну программу. Это удобно еще и тем, что несколько программистов могут создавать различные программы, что в несколько раз может ускорить процесс их создания. Создадим ту же программу, что и Prim 47,
procedure Org1;
begin
assign(bf,'C:TURBObibl.dos');
Rewrite(bf);
with rb do
while True do
begin
readln(nomer);
if nomer=9999 then
begin close(bf); Exit;
end;
writeln('ввести имя автора');
readln(avtor);
writeln('ввести название книги');
readln(nazv);
writeln('ввести название индекса');
readln(index);
write(bf,rb);
end;
end;
procedure Obr1;
begin
Assign(bf,'C:TURBObibl.dos');
Reset(bf);
with rb do
while not eof(bf) do
Begin read(bf,rb);
writeln(nomer:5,avtor:16,Nazv:10,index:6);
end;
Close(bf);
writeln('
end;
procedure Rash1;
begin Assign(bf,'C:TURBObibl.dos');
Reset(bf);
Seek(bf,Filesize(bf));
with rb do
while True do
begin writeln('
if nomer=9999 then begin Close(bf);exit end;
writeln('
writeln('введите название книги'); readln(nazv);
writeln('введите значение индекса'); readln(index);
write(bf,rb);
end;end;
Работу построим в режиме меню. Program Prim48;
label M;
type books=record
nomer:integer;
avtor:string[16];
nazv:string[30];
index:integer; end;
Var bf:file of books;
rb:books; regim:byte;
{$i C:TURBOOrg1.pas}
{$i C:TURBOObr1.pas}
{$i C:TURBORash1.pas}
BEGIN
M: writeln('введите режим работы');
writeln('1 – создание, 2 – обработка',
'3 – расширение, 4 – выход');
readln(regim);
case regim of
1:Org1;
2:Obr1;
3:Rash1;
4:Exit; else writeln('
goto
END
Для обеспечения работы с различными именами файлов имя файла вначале запрашивается, а затем передается в процедуры. Таким образом, мы можем создавать несколько файлов, содержащих данные о книгах, их обрабатывать, расширять и т.п. Program Prim49;
label M1,M2 ;
type books=record
nomer:integer;
avtor:string[16];
nazv:string[30];
index:integer; end;
Var bf:file of books;
rb:books; regim:byte; si:char; fl:string;
{$i C:TURBOOrg.pas}
{$i C:TURBOObr.pas}
{$i C:TURBORash.pas}
BEGIN
M1: writeln('где будет храниться файл? диск:каталогимя'),
readln(fl);
M2: writeln('введите режим работы');
writeln('1 – создание, 2 – обработка',
'3 – расширение, 4 – выход');
readln(regim);
case regim of
1:Org;
2:Obr;
3:Rash;
4:begin writeln('
writeln('или конец работы – любая клавиша');
readln(si);
if (si='Y')or(si='y') then goto M1 else HALT; end;
else begin writeln('неправильно задан режим');
goto M2; end; end; goto M2;
END.
Procedure Org2;
begin
assign(bf, fl);
Rewrite(bf);
with rb do
while True do
begin
readln(nomer);
if nomer=9999 then
begin close(bf); Exit end;
writeln('
readln(avtor);
writeln('введите название книги');
readln(nazv);
writeln('введите значение индекса');
readln
write(bf,rb);
end; end;
Procedure Obr2;
begin
Assign(bf, fl);
Reset(bf);
with rb do
while not Eof(bf) do
begin read(bf, rb);
writeln(nomer:5,avtor:16,Nazv:10,index:6);
end; Close(bf);
end;
Procedure Rash2;
begin assign(bf, fl);
Reset(bf);
Seek(bf,Filesize(bf));
with rb do
while True do
begin writeln('
if nomer=9999 then begin Close(bf);Exit end;
writeln('
writeln('введите название книги'); readln(nazv);
writeln('введите значение индекса'); readln(index);
write(bf,rb);
end;end;
10.5. Файлы произвольного доступа Файлы произвольного доступа используются при наличии зависимости значения какого-либо поля компоненты от ее порядкового номера в файле. Порядковый номер компоненты иногда называют ключом компоненты файла. Организовать файл произвольного доступа можно двумя способами: 1. Создать последовательный файл и обращаться к компонентам по порядковому номеру, трактуя последовательный файл как файл прямого доступа. 2. Создать файл фиктивных (с пустыми полями) компонент, затем загрузить его по ключу фактическими данными. этот способ – создание файла с фиктивными компонентами – называется форматизацией. Пример. Форматировать файл произвольного доступа из 20 компонент c:turbobibl.dos. Структура компонент такая же, как и в Prim 47–49. Оформим алгоритм в виде процедуры form
Procedure form;
Begin w
readln(filname);
assign(booksfile, filname);
rewrite(booksfile);
with recbooks do
Begin write
readln(razmer);
for i:=l to razmer do
Begin nomer:=i; avtor:=' '; index:=0; nazv:=' ';
write ( books file, recbooks)
end; end; writeln(
close
Напишем процедуру загрузки (procedure zagruz
procedure zagruz; Begin writeln('дать имя загружаемого по ключу файла');
readln(filname);
assign(booksfile,filname); reset(booksfile);
writeln('сколько записей будете вводить?'); readln(k);
with recbooks do
Begin for i:=1 to k do
Begin writeln('
writeln('
writeln('введите название книги'); readln(nazv);
writeln('
seek(booksfile,nomer-1); { номера компонент начинаются с 0 }
write(booksfile,recbooks); end; end;
close
Оформить процедуру прямого доступа по ключу к компонентам файла и выдачу их на экран монитора, записать ее в C:TURBOOBRAB.PAS; Procedure Obrab;
Begin writeln('
assign(booksfile,filname); reset(booksfile);
while true do
Begin writeln('
if k=9999 then Begin close(booksfile); exit; end;
seek(booksfile,k-1);
with recbooks do Begin read(booksfile,recbooks);
writeln(nomer:5,avtor:16,nazv:15,index:4);
end
Написать процедуру корректировки файла произвольного доступа в которой будут предусмотрены режимы корректировки: 1. Замена всех полей компоненты. 2. Расширение файла в пределах отформатированного пространства. все это делает процедура Коо
Procedure Koor;
Var nevavtor:string[16]; nevnazv:string[30]; nevindex:integer;
Begin writeln('
assign(booksfile,filname); reset(booksfile);
with
Begin writeln('сколько записей будете корректировать?'); readln(k);
for i:=1 to k do
Begin writeln('
nevavtor:=' '; nevnazv:=' '; nevindex:=0;
writeln('
writeln('введите название книги'); readln(nevnazv);
writeln('
avtor:=nevavtor; nazv:=nevnazv; index:=nevindex;
seek(booksfile,k1-1); write(booksfile,recbooks);
end; end; close(booksfile); end;
В программе Prim 50, с помощью меню рассматриваются работа с файлами произвольного доступа во всех режимах; форматирование файла, его загрузка, обработка, корректировка. Здесь следует заметить, что программа универсальна в том смысле, что может работать с различными файлами. Program Prim50;
Type books=record
nomer:integer; avtor:string[16];
nazv:string[30]; index:integer; end;
Var booksfile:file of books;
recbooks:books; razmer,k,k1,i,reg:integer;
filname:string[12];
{$i c:turboform.pas}
{$i c:turbozagruz.pas}
{$i c:turboobrab.pas}
{$i c:turbokoor.pas}
Begin while true do
Begin writeln('
writeln
writeln('2: загрузка по ключу');
writeln('3: обработка по ключу');
writeln('4: корректировка');
writeln('5: выход из программы');
readln(reg);
case reg of 1:form; 2:zagruz; 3:obrab; 4:koor; 5:halt;
end
end
end
10.6. Текстовые файлы
Компонентами текстовых файлов являются строки. Длина строки – 0-255 символов. Каждая строка завершается маркером строки, а файл – маркером конца файла. Для описания файловых переменных текстового типа используется зарезервированное слово text
Var instrl, instr2: text;
dokulnent: text;
Для работы с текстовыми файлами используются упомянутые выше функции и процедуры assign
Append (fv)
Eoln (fv)
Seekeoln(fv)
Seekeof(fv)
Организация текстового файла производится по схеме: 1) объявляется файловая переменная текстового типа; 2) присваивается файлу имя (assign
3) открывается файл (rewrite
4) подготавливается строка - компонента для записи в файл; 5) записывается строка - компонента в файл (writeln
6) повторяются п. 4, 5 столько раз, сколько нужно; 7) закрывается файл. Доступ к компонентам текстового файла: 1) присвоить файлу имя (assign
2) открыть файл для чтения (reset
3) прочитать компоненту-строку (readln
4) обработать компоненту-строку (например вывести на экран); 5) повторить п. 3, 4 столько раз, сколько нужно. 6) закрыть файл (close
Расширение текстового файла производится путем добавления в конец файла компонент-строк: 1) присвоить имя файлу (assign
2) установить маркер на конец файла (append
3) подготовить строку для записи; 4) записать строку (writeln
5) повторить нужное количество раз п. 3, 4. 6) закрыть файл (close
Замечание
procedure sozdt;
Begin writeln('дайте имя создаваемому текстовому файлу');
readln(filename);
assign(stro,filename); rewrite(stro);
while true do
Begin writeln('
readln(s); if s='zzz' then {'zzz' –
Begin close(stro); exit; end;
writeln(stro,s); end;end;
procedure obrt;
Begin writeln('
; readln(filename);
assign(stro,filename); reset(stro);
repeat readln(stro,s); writeln(s);
until seekeof(stro); close(stro); exit; end;
procedure rasht;
Begin writeln('
assign(stro,filename); append(stro);
while true do
Begin writeln('
if s='zzz' then Begin close(stro); exit; end;
writeln(stro,s); end; end;
Program Prim51;
Type dlina=string[60];
Var stro:text; s:dlina; reg:char; filename:string[12];
{$i c:turbosozdt.pas}
{$i c:turboobrt.pas}
{$i c:turborasht.pas}
Begin while true do
Begin writeln('
writeln('1: создание, 2: вывод на экран, 3: расширение, 4: выход');
readln(reg);
case reg of '1': sozdt;
'2': obrt;
'3': rasht;
'4': halt else writeln('
end;end;end.
Разработчики Турбо-Паскаля предусмотрели несколько подпрограмм, существенно увеличивающих возможности текстового ввода-вывода. Эти подпрограммы сосредоточены в библиотеке (модуле) CRT
11.1. Программирование клавиатуры Дополнительные возможности управления клавиатурой реализуются двумя функциями: keypressed
Функция keypressed
В реализуется так называемый асинхронный буферизованный ввод с клавиатуры. По мере нажатия на клавиши соответствующие коды помещаются в особый буфер, откуда они могут быть затем прочитаны программой. Стандартная длина буфера рассчитана на хранение до 16 кодов символов. Если программа достаточно долго не обращается к клавиатуре, а пользователь нажимает клавиши, буфер может оказаться переполненным. В этот момент раздается звуковой сигнал и «лишние» коды теряются. Чтение из буфера обеспечивается процедурами read/rеadln
Функция ReadKey
Uses
Var
с;
Begin
while Keypressed do
c:== ReadKey;
. . . . .
end
При использовании процедуры ReadKey
Следующая простая программа позволит определить расширенный код любой клавиши. Для завершения работы программы нужно нажать клавишу esc
Uses
Var
Begin
repeat
c:= ReadKey;
if c< >#0 then
writeln (ord(c))
else
writeln ('0', ord (ReadKey):8)
until c=#27 {27 – расширенный код клавиши esc}
end.
Если вы воспользуетесь этой программой, то обнаружите, что нажатие на некоторые клавиши игнорируется функцией ReadKey
в таблице приведены расширенные коды клавиш, возвращаемые функцией o
Расширенные коды клавиш Таблица 59...68 72 F1...F10 курсор вверх 0 11.2. Текстовый вывод на экран Библиотека Turbo Vision способна удовлетворить самым высоким требованиям, и мы настоятельно рекомендуем обращаться к ней при программировании сложных текстовых изображений (меню, окон и т.п.). Тем не менее, вполне возможно, что некоторые из читателей захотят использовать значительно более простые, но достаточно эффективные средства модуля CRT
Процедура TextMode
Procedure
Здесь mode
const bw40=0; {черно-белый режим 40*25} co40=l; {цветной режим 40*25} bw80=2, {черно-белый режим 80*25} co80=3; {цветной режим 80*25} mono=7; {используется с mda} Font8*8=256; {используется для загружаемого шрифта в режиме 80*43 или 80*50 с адаптерами EGA или VGA} Код режима, установленного с помощью вызова процедуры TextMode
следующая программа иллюстрирует использование этой процедуры в различных режимах. заметим, что при вызове TextMode
user CRT;
procedure print (s: string), {вывести сообщение s и ждать инициативы пользователя}
Begin
write
write
read
end; {print}
Var
lm: word, {начальный режим экрана}
Begin
lm:=LastMode; {запомнить начальный режим работы дисплея}
TextMode (
print ('
TextMode (co8o);
print ('
TextMode (co40+font8*8);
print ('
TextMode
print ('режим co80+font8*8'), {восстановить исходный режим работы:}
TextMode
end
Процедура TextColor
Procedure
Процедура TextBackGround
Procedure
Единственным параметром обращения к этим процедурам должно быть выражение типа byte, задающее код нужного цвета. Этот код удобно определять с помощью следующих мнемонических констант, объявленных в модуле CRT:
const
black
blue=l; {темно-синий}
green=2; {темно-зеленый}
суаn=3; { бирюзовый}
red=4; {красный}
magenta=8; {фиолетовый}
brown=6; {коричневый}
lightgray=7; {светло-серый}
darkgray=8; {темно-серый}
light
lightgreen
lightcyan
lightred
lightmagenta
yellow
white
blink=128; {мерцание символа}
Следующая программа иллюстрирует цветовые возможности Турбо-Паскаля. uses CRT, const col: array [1..15] of string [16] = ('темно-синий', 'темно-зеленый', 'бирюзовый', 'красный', 'фиолетовый', 'коричневый', 'светло-серый', 'темно-серый', 'синий', 'зеленый', 'светло-бирюзовый', 'розовый', 'малиновый', 'желтый', 'белый'); Var
k: byte,
Begin
for k:=l to 15 do
Begin {выводим 15 сообщений различными цветами}
textcolor (k),
writeln ("
end;
textcolor (white+blink); {
writeln ("мерцание символов");
{восстанавливаем стандартный цвет}
textcolor
writeln
end
Обратите внимание на последний оператор write
TextColor (lightgray);
Дело в том, что все цветовые определения предварительно заносятся в специальную переменную TextAttr
Процедура ClrScr
uses CRT;
Var
с
Begin
textbackground (red);
clrscr; {
writeln ("
с
textbackground (black);
clrscr {
end.
Процедура Window
Procedure
Здесь x1...y2
В следующем примере иллюстрируется вывод достаточно длинного сообщения в двух разных окнах: uses CRT;
Var
k: integer;
Begin {создать левое окно – желтые символы на синем фоне:}
textbackground (blue);
window (5, 2, 35, 17);
textcolor (yellow);
for k:= i to 100 do
write ("
readln, {
clrscr; {
{создать правое окно – белые символы на красном фоне:}
textbackground (red);
textcolor (white);
window (40, 2, 70, 17);
for k:= i to 100 do
write ("
readln
TextMode (Co8o) {сбросить все установки}
end.
Обращение к процедуре Window игнорируется, если какая-либо из координат выходит за границы экрана или если нарушается одно из условий: Х2>Х1 или Y2>Y1. Каждое новое обращение к Window отменяет предыдущее определение окна. Границы текущего окна запоминаются в двух глобальных переменных модулях CRT: переменная WindMin типа Word хранит X1 и Y1 (Х1 – в младшем байте), а переменная того же типа WindMax – Х2 и Y2 (Х2 – в младшем байте). При желании вы можете изменять их нужным образом без обращения к Window. например, вместо оператора Window (40, 2, 70,17);
можно было бы использовать два оператора: WindMin
(в отличие от обращения к Window, координаты, хранящиеся в переменных WindMin и WindMax, соответствуют началу отсчета 0, 0). Процедура GotoXY
Procedure
Здесь X, Y - новые координаты курсора. Координаты задаются относительно границ экрана (окна), т.е. оператор GotoXY (1,1);
Оператор указывает, перевести курсор в левый верхний угол экрана (или окна, если к этому моменту на экране определено окно). Обращение к процедуре игнорируется, если новые координаты выходят за границы экрана (окна). Функции WhereX
В следующей программе в центре экрана создается окно светло-бирюзового цвета, которое обводится рамкой. Program Prim52;
Uses CRT; {подключить библиотеку (модуль) CRT}
Const { константы, определяющие графические символы }
{ необходимые для вычерчивания рамки окна }
lu=#218; { левый верхний угол рамки }
ru=#191; { правый верхний угол рамки }
ld=#192; { левый нижний угол рамки }
rd=#217; { правый нижний угол рамки }
h=#196; { горизонтальная черта }
v=#179; { вертикальная черта }
{ координаты окна: }
x1=14; y1=5; { верхний левый угол }
x2=66; y2=20; { нижний правый угол }
Var
Begin
textmode(co80); { сброситъ все установки }
textbackground(lightcyan); { фон окна светло-бирюзовый }
textcolor(yellow); { цвет текстов в окне желтый }
window(x1,y1,x2,y2); { открытъ окно с координатами }
ClrScr;
{ рисуем рамку вокруг окна}
Write(lu); { левый верхний угол }
for k:=x1+1 to x2-1 do
write(h); {
write(ru); { правый верхний угол }
for k:=y1+1 to y2-1 do { рисуем вертикальные линии }
{ посимвольно слева и справа и построчно за счет цикла}
Begin GotoXY(1,k-y1+1); { курсор на левую границу }
write(v); { вывести вертикальную черточку }
GotoXY(x2-x1+1,whereY); { курсор на правую границу }
write(v); { вывести вертикальную черточку }
{ перейти на новую строку, пока не кончится цикл }
end;
write(ld); { левый нижний угол }
Window(x1,y1,x2,y2+1);
GotoXY(2,y2-y1+1); { kypcop
{ нового окна, без учета рамки }
for k:=x1+1 to x2-1 do write(h);{
write(rd); { нижний правый угол}
TextBackground(LightCyan);
GotoXY(2,2); { курсор в левый верхний угол}
{нового окна без учета рамки}
readln;
end.
Три следующие процедуры без параметров могут оказаться полезными при разработке текстовых редакторов. Процедура ClrEOL
Процедура
Процедура InsLine
Процедуры
Uses
begin
LowVideo
Writeln ('пониженная яркость');
NormVideo;
Writeln ('нормальная яркость');
HighVideo;
Writeln ('повышенная яркость')
end.
На практике нет разницы между пониженной и нормальной яркостью изображения. Процедура Assign CRT
В следующей программе измеряется скорость вывода на экран с помощью стандартной файловой процедуры и непосредственного обращения к видеопамяти. Вначале файловая переменная F
Показания системных часов хранятся в оперативной памяти компьютера в виде четырехбайтного слова по адресу [$0040:$006С] и наращиваются на единицу каждые 55 миллисекунд. Uses CRT;
var
F: Text;
t: Longint; {начало отсчета времени}
N1, N2: Word; {счетчик вывода}
const
txt
begin
{-----стандартный вывод в файл------}
Assign (F, “CON”);
Rewrite (F);
N1:=0; {
ClrScr; {
{запоминаем начальный момент:}
t
{ждем начало нового 55-миллисекундного интервала, чтобы исключить погрешность в определении времени:}
while Meml [$0040:$006C]=t do;
{цикл вывода за 5 интервалов}
while
begin
inc (N1);
Write (F, txt)
end
Close
{вывод с помощью быстрой процедуры прямого доступа к экрану}
AssignCRT (F);
Rewrite (F);
N2:=0;
ClrScr;
t:= Meml [$0040:$006C];
while Meml [$0040:$006]=t do;
while Meml [$0040:$006]<t+6 do
begin
inc (N2);
Write (F, txt)
end;
Close (F);
{
ClrScr;
Writeln (N1, N2:10)
end.
Следует учесть, что вывод на экран обычным образом, без использования файловой переменной (например, оператором Write (txt)
11.3. Программирование звукового генератора Звуковые возможности пк основаны на одноканальном управляемом звуковом генераторе, вырабатывающем электромагнитные колебания звуковой частоты. Колебания подаются на встроенный в пк динамик и заставляют его звучать. В модуль CRT
Процедура Sound
Процедура NoSound
Процедура Delay
Здесь Т
Для генерации звукового сигнала обычно используется вызов описанных процедур по схеме Sound—Delay—NoSound
Uses CRT;
const
F: array [1..12] of Real =
(130.8, 138.6, 146.8, 155.6, 164.8, 174.6, 185.0, 196.0, 207.7,
220.0, 233.1, 246.9); {массив частот 1-й октавы}
Temp = 100; {темп исполнения}
var
k, n: integer;
begin
{
for k:=0 to 3 do
for n:=1 to 12 do
Begin
Sound (Round (F[n]*(1 shl k)));
Delay (Temp);
NoSound
end;
{
for k:=3 downto 0 do
for n:=12 downto 1 do
begin
Sound (Round (F[n]*(1 shl k)));
Delay (Temp);
NoSound
end
end.
В следующей программе перемножается матрица на вектор, основу которой составляет ранее рассмотренные Program Prim 29 i Prim 29а
Программа в начале работы издает звуки частотой от 130 до 2130 Гц, затем при вводе величины a – частотой 2000 Гц, b – 1500 Гц длительностью n=100 мс. В конце работы программа издает звуки от 2130 до 130 Гц. Программа использует подпрограмму Wind
Program Prim53; Uses CRT; var i,j,n,m,k,l:integer; a:array[1..50,1..70] of byte; b:array[1..10] of byte;
c:array[1..10] of longint;
cv:byte;
{$i C:TURBO wind.pas}
BEGIN
Clrscr; {
cv:=11; {
wind(1,1,50,7); { открыть окно, обращения к процедуре}
Sound(330); { включить звук, частотой 330 гц } Delay(1000); { задержать на 1000 миллисекунд } NoSound; { выключить звук }
writeln ('ввести количество строк и столбцов');
GotoXY(2,3); l:=4; {l устанавливает курсор по y}
readln(n,m);
for i:=1 to n do
for j:=1 to m do
begin GotoXY(2,l);
writeln(' введите a[',i,',',j,'] элемент матрицы а ');
GotoXY(34,l); { перевести курсор в конец текста:}
{ввести a[i,j] – элемент матрицы'}
ClrEol; { удалить конец строки до границы окна}
readln(a[i,j]); { ввести очередное а в конце текста }
end;
L:=L+1;{}
for j:=1 to m do
begin GotoXY(2,l);
writeln(
GotoXY(33,l);
ClrEol;
readln(b[j]); end;
cv:=5; { фиолетовый цвет для нового окна }
wind
for i:=1 to n do { начало перемножения матрицы на векторы }
begin c[i]:=0;
for j:=1 to m do
c[i]:=c[i]+ a[i,j]*b[j]; end;
{ конец перемножения матрицы на вектор }
writeln(' распечатка массива а ');
for i:=1 to n do
begin GotoXY(2,l); l:=l+1; {
for j:=1 to m do
write(a[i,j]:5); end;
GotoXY(2,l); l:=l+1; writeln('распечатка массива b');
GotoXY(2,l);
for j:=1 to m do
write(' ',b[j]); L:=L+1;
GotoXY(2,L); L:=L+1; writeln('результирующий массив с');
GotoXY(2,L);
for i:=1 to n do
write(' ',c[i]);
readln; END.
12.1. Инициализация графического режима Для вывода графических изображений на экран турбо Паскаль предоставляет пользователю библиотеку Graph
Program имя; Uses Graph;
var
grDriver, grMode, errCode: integer;
begin
grDriver:= Detec
initGraph (grDriver, grMode,''); {инициализация графического режима}
if
begin { режим открыт и можно работать}
end else
begin {графический режим не удалось открыть, проанализируйте содержание переменной errCode}
end.
Замечание.
12.2. Процедуры и функции библиотеки Graph
Функции GetMaxX
Различные мониторы имеют различную разрешающую способность, например: VGA - 640´480 точек, IBM 8514Hi - 1024´768 точек. Функции GetX
Если выражение Clipon
Процедура MoveTo (Х, Y);
Процедура MoveRel (Ox, Dy);
Процедура ClearDevice,
Процедура PutPixel (Х, Y, Color);
Процедура
Где Туре
Тип линии: 0 – сплошная, 1 – точечная, 2 – штрихпунктирная, 3 – . . . . . . . . 4 – узор линии определяет пользователь параметром pattern. Thick=l – толщина линии в 1 пиксел. Thick=2 – толщина линии в 3 пиксела. Процедура Rectangle (Х1, Y1, Х2, Y2);
Процедура Draw
type
PointType=record
X, Y: Word
end;
При вычерчивании используются текущий цвет и текущий стиль линий. Процедура
Процедура Arc (Х, Y, Beg А, End А, R);
Процедура Ellipse (Х, Y, Beg А, End А, RX, RY);
Процедура Bar (Х1, Y1, Х2, Y2);
Процедура Ва
Процедура FillPoly (n, Coords);
Процедура F
Процедура Sector (Х, Y, Beg А, End А, Rx, Ry);
Процедура PieSlice (Х, Y, Beg А, End А, R);
Процедура SetColor (Color);
Процедура SetbkColor (Color);
Процедура SetF
Значения Fill
0 – заполнение фоном (узор отсутствует); 1 – сплошное заполнение; 2 – заполнение – – – – –; 3 – – « – /////// ; 4 – – « – утолщенными ///////; 5 – – « – утолщенными ; 6 – – « – ; 7 – – « – + + + + + +; 8 – – « – ******; 9 – – « – прямоугольной клеточкой; 10 – – « – редкими точками ; 11 – – « – частыми точками ; 12 – – « – узор определяется пользователем. Процедура FloodPill (Х, Y, Color);
Функция ImageSize (X1, Y1, X2, Y2);
Процедура GetImage (X1, Y1, X2, Y2, Buf);
Процедура PutImage (X, Y, Buf, Mode);
X
12.3. Примеры программ Ниже приведены программы, демонстрирующие некоторые возможности графики в Паскале. Программа Prim 54
Program Prim54;Uses Graph;var grDriver,grMode,errCode,Radius,i,Width,y0,y1,y2,x1,x2:integer;Begin grDriver:=detect; {
InitGraph
{ инициализация графического режима }
errCode:=GraphResult;
if errCode=grOK then
begin { графический режим открыт, можно работать }
for
begin { рисуем окружности с радиусами 10,20..50,
с центром x=200, y=70 точек растра }
Circle
{ Cleardevice;} { если бы этот оператор не был в
комментарных скобках, т.е. не заблокирован, то
сейчас окружности были бы стерты с экрана }
Ellipse(200,200,0,360,30,50); { рисуем дугу эллипса с центром 200,200, начальный угол=0, конечный – 360 (замкнутый,
эллипс радиусами 30,50 }
readln;
Ellipse(300,200,0,180,50,30); {полэллипса }
readln;
for Radius:=1 to 5 do
Arc(300,100,0,90,radius*10); {
0 до 90 градусов, радиусами 10,20..50}
readln;
Width:=10;
Bar(30,20,50,100); {прямоугольник с координатами 30,20 –
верхний левый угол и 50,100 – нижний правый угол}
for i:=1 to 5 do
Bar(10+i*Width,300+i*10,20+i*Width,400);
{пять прямоугольников: первый 20,310.30,400,
второй 30,320,40,400 и т.д. }
readln;
Bar3D(210,300,250,360,10,TopOn); {параллелепипед с крышкой}
readln;
x1:=410; y1:=300; x2:=450; y2:=360;
Bar3D(x1,y1,x2,y2,10,TopOff); {
readln;
CloseGraph; {
end
else Halt(1); {
End.
Prim 55
Program Prim55;
Uses CRT,Graph;
var GrDriver,grMode,errCode:integer;
begin grDriver:=Detect;
InitGraph(grDriver,grMode,' ');
errCode:=GraphResult;
if errCode=grOK then
begin Randomize; {запустить генератор случайных чисел}
repeat {рисуются цветные линии в квадрате 500 x 500,
пока не будет нажата любая клавиша, координаты
линий случайны, цвета линий случайны}
SetColor(Random(GetMaxColor)+1);
Line(Random(500),Random(500),Random(500),Random(500));
Delay(1000); {каждая линия рисуется с задержкой}
until KeyPressed;
Cleardevice;
MoveTo(1,2); {
LineRel(500,500); {провести линию из предыдущей точки в 500,500
последним цветом}
readln; readln;
repeat
LineTo(random(500),random(500)); {провести линию в случайную точку}
Delay(6000);
until KeyPressed; readln;
ClearDevice;
Rectangle(29,29,GetMaxX-29,GetMaxY-29); {
readln;
CloseGraph; end
else Halt(1); end.
Prim56
Program Prim56;
Uses CRT, Graph;
Var grDriver,grMode,errCode:integer;
Begin grDriver:=Detect;
InitGraph(grDriver,grMode, ' ');
errCode:=Graphresult;
if errCode=grOK then
Begin SetBkColor(blue);
SetFillStyle(1,4);
FillEllipse(220,150,50,50);
FillEllipse(420,150,50,50);
FillEllipse(320,230,50,130);
FillEllipse(370,405,50,30);
FillEllipse(275,410,50,30);
readln; end
else Halt(1); end.
Prim56
Program Prim57;
Uses Graph;
Var i,grDriver,grMode,TrrCode,errCode:integer; x,y:word;
xm,ym,rc,xc,yc,x1,y1,x2,y2,r:word;
k:arccoordsType; kr:array[1..20] of PointType;
Begin grDriver:=detect;
InitGraph(grDriver,grMode,' ' );
errCode:=GraphResult;
if errCode=grOK then
begin
x:=150; y:=150;
SetBkColor(white);
{
y1:=y-30; x1:=x-30; x2:=x+40; r:=15;
SetColor(lightred);
SetFillStyle(solidfill,brown);
pieslice(x1,y1,0,360,r);
pieslice(x2,y1,0,360,r);
r:=r-3;
SetFillStyle(solidfill,lightred);
pieslice(x1,y1,0,360,r);
pieslice(x2,y1,0,360,r);
{голова}
r:=(x2-x1) div 2-3;
x1:=x1+r+2;
y1:=y1+2;
xc:=x1;
yc:=y1;
rc:=r;
setColor(brown);
SetFillStyle(solidfill,brown);
pieslice(x1,y1,0,360,r);
{
setColor(brown);
SetFillStyle(solidfill,yellow);
y2:=y1+r-3;
x1:=x1-r div 2+2;
ym:=y2;
line(x1-5,y2-5,x1-27,y2+68);
x2:=x1+r+16;
xm:=x2;
line(x2-15,y2-5,x2+27,y2+68);
line(x1-27,y2+68,x2+27,y2+68);
putpixel(x2-22,y2+25,blue);
floodfill(x2-22,y2+25,brown);
{
setcolor(green);
setfillstyle(solidfill,green);
bar(112,215,214,225);
{
setcolor(blue);
setfillstyle(solidfill,blue);
kr[1].x:=113; kr[1].y:=223;
kr[2].x:=113; kr[2].y:=270;
kr[3].x:=165; kr[3].y:=270;
kr[4].x:=170; kr[4].y:=260;
kr[5].x:=180; kr[5].y:=270;
kr[6].x:=225; kr[6].y:=270;
kr[7].x:=212; kr[7].y:=223;
kr[8].x:=113; kr[8].y:=223;
fillpoly(8,kr);
{
setcolor(brown);
setfillstyle(solidfill,brown);
kr[1].x:=135; kr[1].y:=270;
kr[2].x:=145; kr[2].y:=320;
kr[3].x:=123; kr[3].y:=350;
kr[4].x:=145; kr[4].y:=358;
kr[5].x:=145; kr[5].y:=350;
kr[6].x:=162; kr[6].y:=320;
kr[7].x:=145; kr[7].y:=270;
kr[8].x:=135; kr[8].y:=270;
fillpoly(8,kr);
{
kr[1].x:=195; kr[1].y:=270;
kr[2].x:=205; kr[2].y:=320;
kr[3].x:=183; kr[3].y:=350;
kr[4].x:=205; kr[4].y:=358;
kr[5].x:=205; kr[5].y:=350;
kr[6].x:=222; kr[6].y:=320;
kr[7].x:=205; kr[7].y:=270;
kr[8].x:=195; kr[8].y:=270;
fillpoly(8,kr);
{
setfillstyle(solidfill,red);
pieslice(160,360,0,360,10);
pieslice(200,370,10,160,20);
pieslice(215,360,0,360,10);
pieslice(142,370,10,160,20);
setfillstyle(solidfill,white);
fillellipse(145,115,5,8);
fillellipse(163,115,5,8);
setfillstyle(solidfill,blue);
pieslice(147,115,0,360,3);
pieslice(165,115,0,360,3);
setcolor(yellow);
arc(154,160,30,145,30);
setcolor(red);
setfillstyle(solidfill,lightmagenta);
fillellipse(154,146,5,8);
{
kr[1].x:=140; kr[1].y:=153;
kr[2].x:=135; kr[2].y:=163;
kr[3].x:=155; kr[3].y:=158;
kr[4].x:=175; kr[4].y:=163;
kr[5].x:=170; kr[5].y:=153;
kr[6].x:=155; kr[6].y:=158;
kr[7].x:=140; kr[7].y:=153;
fillpoly(7,kr);
{
setfillstyle(solidfill,blue);
kr[1].x:=243; kr[1].y:=225;
kr[2].x:=255; kr[2].y:=280;
kr[3].x:=325; kr[3].y:=280;
kr[4].x:=335; kr[4].y:=225;
kr[5].x:=255; kr[5].y:=225;
fillpoly(5,kr);
sector(290,230,0,360,50,12);
setfillstyle(solidfill,lightcyan);
fillellipse(290,230,40,10);
{
setfillstyle(solidfill,brown);
kr[1].x:=184; kr[1].y:=164;
kr[2].x:=295; kr[2].y:=225;
kr[3].x:=300; kr[3].y:=215;
kr[4].x:=175; kr[4].y:=150;
kr[5].x:=180; kr[5].y:=160;
fillpoly(5,kr);
pieslice(295,224,0,170,12);
pieslice(265,244,0,360,10);
kr[1].x:=136; kr[1].y:=184;
kr[2].x:=265; kr[2].y:=255;
kr[3].x:=270; kr[3].y:=245;
kr[4].x:=135; kr[4].y:=170;
kr[5].x:=136; kr[5].y:=184;
fillpoly(5,kr);
end else halt(1);
readln; end.
Prim58
Program Prim58;
Uses CRT,Graph;
Label loop;
Const r=30; p=600; pr=1000; {константы, определяющие скорость}
{рисования и перемещения объектов}
Var
width,height,grDriver,grMode,errCode,a,b,c,
f,s,j:integer;
saucer:pointer;
Begin grDriver:=Detect;
InitGraph(grDriver,grMode,'');
errCode:=GraphResult;
if errCode=grOK then
Begin x:=r*3; y:=r*2; xm:=GetMaxX div 2; ym:=GetMaxY div 2;
{
SetBkColor(blue);
SetFillStyle(solidfill,red);
Ellipse(x,y,0,360,r+40,r div 10);
Ellipse(x,y-4,0,360,r-1,r);
Line(x+7,y-6,x+10,y-12);
Line(x-7,y-6,x-10,y-12);
Circle(x+10,y-12,2);
Circle(x-10,y-12,2);
Floodfill
{определяем габариты НЛО и помещаем данные о нем в кучу}
lx:=x-r-1;
ly:=y-14;
rx:=x+r+1;
ry:=y+r div 6;
Width:=rx-lx+1;
Height:=ry-ly+1;
Size:=Imagesize(lx-9,ly,rx+3,ry+10);
GetMem(Saucer,size);
GetiMage(lx-9,ly,rx+10,ry+3,saucer^);
{
Rectangle(xm,ym,3*xm,3*ym);
SetViewPort(xm+1,ym+1,3*xm-1,3*ym-1,Clipon);
xm:=2*xm;
ym:=2*ym;
for i:=1 to 200 do
PutPixel(random(xm),random(ym),white);
{
SetFillStyle(solidfill,DarkGray);
bar(320,240,640,480); Delay(p*10); {
bar(370,220,600,240); Delay(p*10); {
Line(320,240,640,240); Delay(p*10); {
Line(370,240,370,220); Delay(p*10); {левая стена чердака}
Line(600,220,600,240); Delay(p*10); {правая стена чердака}
Line(370,220,600,220); Delay(p*10); {
Line(430,220,430,180); Delay(p*10); {
Line(430,180,410,170); Delay(p*10); {
Line(430,180,410,190); Delay(p*10); {
Line(430,180,410,180); Delay(p*10); {
bar(0,460,640,480); Delay(p*10); {
Line(0,460,640,460); Delay(p*10);
SetFillStyle(solidfill,Yellow);
b:=270; {
for i:=1 to 4 do
begin a:=350; f:=b+20; c:=a+15; Delay(p*5);
for j:=1 to 8 do
begin
bar(a,b,c,f); Delay(p*5);
SetColor(DarkGray);
Line(a,b+8,c,f-12); Delay(p*5);
Line(a+5,b+8,a+5,b+20); Delay(p*5);
a:=a+35; c:=c+35; end;
b:=b+50; end; Delay(p*10);
Pieslice(500,80,300,100,20); {
SetColor(green); Delay(p*10);
Line(150,460,150,400); Delay(p*10); {
Circle(170,365,25); Delay(p*10);
Circle(165,375,25); Delay(p*10);
Circle(150,375,25); Delay(p*10);
Circle(135,365,25); Delay(p*10);
Circle(155,345,25); Delay(p*10);
{задаем начальное положение нло и направление движения}
x:=xm div 2;
y:=ym div 2;
dx:=100;
dy:=100;
{
Repeat
PutImage(x,y,Saucer^,XorPut);
Sound(Random(2*2000));
Delay(pr*2); NoSound;
Putimage(x,y,Saucer^,XorPut);
{получаем новые координаты}
loop
y:=y+dy;
if (x<0) or (x+width+1>xm) or (y<0) or (y+height+1>ym) then
begin
{НЛО достиг границы экрана, меняем направление его движения}
x:=x-dx; y:=y-dy;
dx:=GetMaxX div 10 - random(GetMaxX div 5);
dy:=GetMaxY div 30 - random(GetMaxY div 15);
goto loop;
end until KeyPressed;
if ReadKey=#0 then x:=ord(ReadKey);
end
end
Список использованной и рекомендуемой литературы: 1. А.Н. Воловачев, В.С. Крисевич. Программирование на языке Паскаль для персональных ЭВМ ЕС. – Минск: "Высшая школа", 1989. 2. В.Я. Сердюченко. Розробка алгоритмів та програмування мовою TURBOPASCAL. – Харьков: "Паритет", 1995. 3. В.В. Фаронов. TURBOPASCAL 7.0 /Практика программирования/ – "Нолидж", 1997. 4. В.В. Фаронов. TURBOPASCAL 7.0 /Начальный курс/ – "Нолидж", 1997. ОГЛАВЛЕНИЕ 1. Предварительные сведения...................................................... 4 1.1. Алфавит................................................................................................... 4 1.2. Решение задач......................................................................................... 4 2. Простейшие программы............................................................. 5 2.1. Оператор присваивания......................................................................... 5 2.2. комментарии........................................................................................... 7 2.3. Программа............................................................................................... 7 2.4. Простейший ввод-вывод........................................................................ 8 2.5. Арифметические выражения.................................................................. 9 2.6. Описания переменных......................................................................... 12 2.7. Раздел описания типов........................................................................ 14 3. Разветвляющиеся программы............................................. 16 3.1. Общие положения................................................................................. 16 3.2. Оператор goto, раздел описания меток............................................. 17 3.3. Оператор if............................................................................................. 19 3.4. Оператор case (оператор выбора)........................................................ 25 4. Циклические программы......................................................... 27 4.1. Оператор for.......................................................................................... 27 4.2. Оператор repeat. Общий вид................................................................ 32 4.3. Оператор While..................................................................................... 33 4.4. Вложенные циклы................................................................................. 34 5. Ввод – вывод...................................................................................... 37 5.1. Общие положения................................................................................. 37 5. 2. Ввод....................................................................................................... 38 5. 3. Вывод..................................................................................................... 39 5. 4. Некоторые возможности ввода-вывода........................................... 39 6. Массивы.............................................................................................. 41 6. 1. Описание массивов............................................................................ 41 7. Подпрограммы................................................................................ 49 7.1. Общие положения................................................................................. 49 7.2. Подпрограммы-функции, определенные пользователем................. 51 7.3. Подпрограммы-процедуры................................................................... 54 7.4. Локальные и глобальные описания объектов.................................. 58 8. Строковые данные....................................................................... 59 8.1. Общие замечания.................................................................................. 59 8.2. Строковые выражения.......................................................................... 60 8.3. Стандартные процедуры и функции для обработки строк................ 61 8.3.1. Процедуры обработки строк.............................................................. 61 8.3.2. Функции обработки строк................................................................. 62 9. Записи................................................................................................... 63 9.1. Комплексные данные........................................................................... 68 9.2. Запись с вариантами............................................................................ 70 10. Файлы.................................................................................................. 71 10.1. Общие замечания................................................................................ 71 10.2. Стандартные процедуры и функции для работы с файлами.......... 72 10. 3. Стандартные файлы........................................................................... 73 10.4. Файлы последовательного доступа, созданные пользователем. 74 10.5. Файлы произвольного доступа........................................................ 80 10.6. Текстовые файлы................................................................................ 83 11. Использование библиотеки CRT....................................... 85 11.1. Программирование клавиатуры....................................................... 85 11.2. Текстовый вывод на экран................................................................ 88 11.3. Программирование звукового генератора...................................... 96 12. Графика в Паскале...................................................................... 99 12.1. Инициализация графического режима............................................ 99 12.2. Процедуры и функции библиотеки Graph........................................ 99 12.3. Примеры программ............................................................................ 102 СПИСОК ИСПОЛЬЗОВАННОЙ ЛИТЕРАТУРЫ............................................109
будет
работать
же
} function del(stroka:string):string;
введите
строку
');
Var
A
,
B
,
C
:
string
[14];
str
:
string
[50];
ch
:
string
[1];
d
1,
d
2,
d
3:
integer
;
A
:='электронная';
B
:='вычислительная';
C
:='машина';
ch
:=
copy
(
A
,1,1);
writeln
(
ch
);
длины
строк
' ,d1:6,d2:6,d3:6); insert('-',str,d1+1); insert('-',str,d1+d2+2);
9. Записи
), домашний адрес (тип string
), пол (тип char
), номер группы (тип integer
), номер комнаты проживания в общежитии (тип integer
), изучаемые предметы (тип, массив строк) и т.д.
предусмотрен тип данных запись
.
– поименованный структурированный тип данных, состоящий из фиксированного количества различных компонент
. Определение (описание) данного типа "запись" начинается атрибутом record
и заканчивается end
.
и end
заключается список компонент записи, называемых полями, с указанием их имен и типа каждого поля. Туре имя типа=record идентификатор поля: тип компоненты; идентификатор поля: тип компоненты;
идентификатор: имя типа;
Возможно и «прямое» описание записи, без предварительного описания типа. Пример описания записи с помощью предварительного задания типа:Туре Car=record Nomer: integer; {номер} Marka: string [20]; {марка автомобиля} F
I
O: string [40], {ф.и.о. владельца} adres: string [60]; {адрес владельца}end;Var M, V: Car;
Либо «прямое» описание:Var М, V: Record Nomer: integer; Marka: string [20];
I
O: string [40]; adres: string [60]; end;
Идентификатор поля должен быть уникален только в пределах записи, однако во избежание ошибок лучше его делать уникальным в пределах программы.
для хранения записи складывается из объемов памяти – суммы длин полей. Значения полей записи могут использоваться в выражениях, при этом в них должны указываться составные (уточненные) имена, так как имена полей в различных записях могут совпадать. Например, чтобы получить доступ к полям записи Са
r
, необходимо пользоваться именами М.
FIO
, М. NOMER
для записи М
, а для записи V
- именами V. F
IO
, V. NOMER
. Эти имена можно использовать везде, где применяются обычные имена, например, в операторах присваивания:
. Nomer:=1678;
. Marka:'
газ
–24';
(м.
marka
);
и V
допустимо M:=V
;
станут равными значениям полей записи М
.
Person=record
будет состоять из 50 записей типа Person
.
который имеет следующий формат:
····················
end
.
переменную типа запись
, затем – в пределах begin... end
, стоящих после with
, можно работать с именами полей этой записи как с обычными переменными, т.е. без указания перед именем поля имени записи. Например:
:
NOM
:=5543;
.
MARKA
:='г
a
3-24';
FIO
:='Петров П. П.';
Adres
:='ул. Чкалова, 7, кв.32';
Label M1,M2,M3,M4;
основы
информатики
';
высшей
математике
';
философии
';
архитектуре
ЭВМ
';
истории
Украины
'; end;
введите
оценку
студента
',fio,' no ',predmet);
4:
end
;
end
;
: writeln('до первой положительной оценки');
i
}
(
kst
[
i
]);
i
в группе }
введите
фамилию
',j,' студента гр.
',namb);
обнуляем
массив
оценок
}
индекс
группы
}
номер
студента
}
kol
_
dvoek
:=0;
v
:=0; { работать без составных имен }
номер
предмета
}
история
Украины
'; end;
к
новому
студенту
}
.
доступно только тогда, когда Flag=TRUE
доступно только тогда, когда Flag=FALSE
Prim
46;
;
readln
;
END
.
10. Файлы
– поименованная область памяти, как правило, на внешнем носителе, предназначенная для хранения информации. файл можно также считать структурированным типом данных, состоящим из последовательности компонент одного и того же типа и одинаковой длины и структуры. чаще всего компонентами файла являются записи.
имя типа=file of
тип компонент;
идентификатор,.., идентификатор: имя типа;
b
, с
типа Ft
. Компонентами файлов служат записи типа zap
. Другими словами, файл схематично можно представить в виде «ленты» компонент, каждая из которых является записью типа zap
. Доступ к компонентам файла может быть последовательным и прямым. Последовательный доступ – это когда для обращения к n-й компоненте необходимо «посмотреть» n-1 компонент; прямой доступ – обращение к компоненте идет прямо по «ключу» (номеру компоненты), без «просмотра» предыдущих компонент.
, ехе, txt
и т.д. В некоторых случаях тип файла присваивается автоматически операционной системой или используемым пакетом.
или D
).
.
находится в подкаталоге Prim
каталога TURBO
диска С
.
- имя файловой переменной или просто имя файла, str
- строковое выражение, Р
- имя структурной компоненты файла, n
- целое выражение.
– процедура присвоения имени файла.
, присваивается переменной файлового типа FV
. Далее все действия над этой переменной будут эквивалентны действиям над файлом, определенным именем str
. Например: Assign (books, 'c:bibl.dos')
; позволяет работать не с именем 'c:bibl.dos'
, которое может быть достаточно длинным (если имеются каталоги и подкаталоги), а с именем books
.
– процедура создания нового файла с именем FV
на диске. Имя файла должно быть предварительно определено процедурой Assign.
Если на диске уже был файл с таким именем, то он уничтожается. Указатель файла устанавливается в первую позицию с номером 0. Файл еще не содержит ни одной компоненты, а только подготовлен к загрузке.
– процедура открытия (разрешение работать с файлом именем FV
) уже имеющегося файла. Указатель устанавливается на начало файла, в позицию с номером 0.
– процедура чтения компоненты файла, на которую установлен указатель, ее содержимое помещено в область памяти с именем Р
.
– процедура записи информации из области памяти Р
в файл FV
и компоненту, на которую установлен указатель.
n
);
– процедура установки указателей на компоненту с номером n.
ush (FV);
– очищение буфера сектора. Выполнение процедуры приводит к выталкиванию содержимого внутреннего буфера (области памяти) в файл.
– процедура закрытия файла, при этом записывается маркер конца файла. После работы с файлом его необходимо обязательно закрыть.
– процедура уничтожения файла. Если производится уничтожение открытого файла, его необходимо предварительно закрыть.
– процедура переименования файла. Файлу FV
присваивается имя str.
– процедура уничтожения всех компонент файла, начиная с места текущего положения указателя и подготовки файла к записи.
– функция проверки маркера конца файла. Значение функции равно True
, если указатель файла находится за последней компонентой, и False
– в противном случае.
– функция определения положения указателя.
– функция определения длины файла. Функция возвращает целочисленное значение, равное количеству компонент файла: если File Size
(FV) = 0
, то файл пуст.
– функция проверки результата последней операции ввода- вывода на наличие ошибок. Если ошибка обнаружена, возвращается код ошибки, если нет, то код = 0.
: – консоль (клавиатура или экран дисплея). Турбо-Паскаль устанавливает различия между этими устройствами по направлению передачи данных: чтение данных возможно только с клавиатуры, а запись - только на экран. Ввод с клавиатуры буферизуется: символы по мере нажатия клавиш помещаются в буфер, содержимое которого передается в ЭВМ только после нажатия клавиши ENTER
, поскольку вводимые и буферизированные символы отображаются на экране. Con
применяется «по умолчанию» для ввода с помощью операторов READ
и Readln
и для вывода на экран – операторов write
и writeln
, если не указано имя файла FV
.
как логические устройства, имеющие имена файлового типа и которым соответствуют заранее определенные (стандартные) файлы. Идентификацию (отождествление) устройства и стандартного файла осуществляют специальные программы (драйверы), которые обеспечивают выполнение операций ввода-вывода между процессором и конкретным физическим устройством. Ниже указаны имена файлов и соответствующие им устройства так, как они определены разработчиками системы.
: – терминал, предназначенный для ввода с клавиатуры и вывода на экран без редактирования.
: – клавиатура, используемая только для ввода с клавиатуры, при вводе информация не отображается на экран.
R
N:
– построчно печатающее устройство (принтер), используемое только для вывода.
:
– вспомогательное устройство, подключающееся через порты.
– устройство пользователя, применяемое при написании собственных драйверов для организации нестандартного ввода-вывода.
);
);
);
).
);
);
);
).
);
);
);
).
в подкаталоге Prim
каталога TURBO
на диске С
, т.е. C:TURBObibl.dos
. Компонента должна иметь структуру: индекс книги, порядковый номер экземпляра, фамилию, инициалы первых трех авторов (если их несколько), название книги. Блок создания файла оформить в виде процедуры с именем org
. Блок доступа к компонентам файла оформить в виде процедуры с именем obr
., а блок корректировки – в виде процедуры с именем Rash
.
базовая
запись
}
описать
файловую
переменную
}
компоненты
файла
}
ввести
номер
книги
');
nomer
=9999
then
{9999 – признак окончания ввода данных}
ввести
имя
автора
');
выйти
из
цикла
,
когда
закончится
файл
}
вывод
на
экран
}
ввести
номер
'); readln(nomer);
ввести
имя
автора
'); readln(avtor);
основная
программа
}
только пообъектно, тогда процедуру Org
запишем в C:TURBOOrg1.pas,
процедуру Obr
– в C:TURBOOrb1.pas
, процедуру Rash
– в C:TURBORash1.pas
, а вызывающую (основную программу – в C:TURBOPrim. 48
, в которой предусмотрим подключение объектов – процедур Org, Obr, Rash
к основной программе через директивы компилятора $
i
.
writeln
('ввести номер книги');
нажмите
enter'); readln;
введите
номер
'); readln(nomer);
введите
имя
автора
'); readln(avtor);
неправильно
задан
режим
'); end;
M
;
.
будем
ещё
работать
с
файлами
? - "Y"');
writeln
('введите номер книги');
введите
имя
автора
');
(
index
);
введите
номер
'); readln(nomer);
введите
имя
автора
'); readln(avtor);
, запишем ее в c:turboform.pas.
r
iteln ('
дайте
имя форматизируемому файлу');
l
n (
'
на
сколько
записей
форматировать
файл
?');
ф
op
матизация
',razmer,'
запись
выполнена
');
(
booksflle
);
end
;
), которая будет заменять поля фиктивных записей реальными значениями, и запишем ее в c:turbozagruz.pas;
введите
номер
'); readln(nomer);
введите
имя
автора
'); readln(avtor);
введите
индекс
'); readln(index);
(
booksfile
);
end
;
дайте
имя
файла
'); readln(filname);
укажите
ключ
обрабатываемой
записи
'); readln(k);
;
end
;
end
;
r
, записанная в c:turbokoor.pas.
дайте
имя
файла
'); readln(filname);
recbooks
do
дайте
номер
корректируемой
записи
'); readln(k1);
введите
имя
автора
'); readln(nevavtor);
введите
индекс
'); readln(nevindex);
укажите
режим
');
('1: форматизация');
;
;
.
.
,
rewrite
,
reset
,
close
,
read
,
readln
,
write
,
writeln
,
seekeof
, однако имеются и специфические функции и процедуры:
– открыть текстовый файл и установить указатель на маркер конца файла.
– возвратить true, если указатель файла достиг маркера конца строки, в противном случае, возвратить значения false.
– функция, аналогичная предыдущей, но указатель проходит все пробелы и знаки табуляции. возвращает true при достижении маркера конца строки.
– возвращает true, если указатель файла находится на маркере конца файла.
);
);
);
);
);
);
);
);
);
);
).
. При записи файлов прямого и последовательного доступа, созданных пользователем, содержимое компонент упаковывается, и поэтому посмотреть их в vc или nc по f3 или f4 нельзя, а текстовый файл не упаковывается, и его можно просмотреть.
напишите
содержимое
строки
');
признак
окончания
ввода
}
дайте
имя
обрабатываемого
файла
');
укажите
имя
корректируемого
файла
'); readln(filename);
введите
строку
'); readln(s);
укажите
режим
');
повторите
номер
режима
');
11. Использование библиотеки CRT
, входящей в комплект поставки Турбо-Паскаля. В модуль включены также процедуры sound, no sound, del
a
y
, позволяющие программировать звуковой генератор компьютера.
и ReadKey
.
возвращает значение типа boolean
, указывающее состояние буфера клавиатуры: false
означает, что буфер пуст, а true
– что в буфере есть хотя бы один символ, еще не прочитанный программой.
и функцией ReadKey
. обращение к функции keypressed
не задерживает исполнения программы: функция немедленно анализирует буфер и возвращает то или иное значение, не дожидаясь нажатия клавиши.
возвращает значение типа char
. При обращении к этой функции анализируется буфер клавиатуры: если в нем есть хотя бы один не прочитанный символ, код этого символа берется из буфера и возвращается в качестве значения функции, в противном случае функция будет ожидать нажатия на любую клавишу. Ввод символа с помощью этой функции не сопровождается эхо-повтором и содержимое экрана не меняется. Например, в какой-то точке программы необходимо игнорировать все ранее нажатые клавиши, коды которых еще непрочитаны из буфера, т.е. необходимо очистить буфер. Этого можно достичь следующим способом:
CRT
;
char
;
.
следует учесть, что в клавиатурный буфер помещаются так называемые расширенные коды нажатых клавиш. Если нажимается любая алфавитно-цифровая клавиша, расширенный код совпадает с ASCII
-кодом соответствующего символа. Например, если нажимается клавиша с латинской буквой «а» (в нижнем регистре), функция ReadKey
возвращает значение chr(97),
а если – «а» (в верхнем регистре) – значение chr(65).
При нажатии функциональных клавиш F1...
F
10
(клавиш управления курсором), клавиш I
ns, Home, Del, End, PgUp, PgDn
в буфер помещается двухбайтовая последовательность: сначала символ #0
, а затем расширенный код клавиши. Таким образом, значение #0
, возвращаемое функцией ReadKey
, используется исключительно для того, чтобы указать программе на генерацию расширенного кода. Получив это значение, программа должна еще раз обратиться к функции, чтобы прочитать расширенный код клавиши.
.
CRT
;
с
: char;
. Это прежде всего так называемые сдвиговые клавиши – Shift, Ctrl, Alt
. Сдвиговые клавиши в MS-DOS обычно используются для переключения регистров клавиатуры и нажимаются в сочетании с другими клавишами. Именно таким способом, например, различается ввод прописных и строчных букв. Кроме того, функция игнорирует переключающие клавиши Caps Lock, N
um
Lock, Scroll Lock.
rd
(ReadKey).
Код
Клавиша или комбинация клавиш
Код
Клавиша или комбинация клавиш
первый байт
второй байт
первый байт
второй байт
Алфавитно-цифровые клавиши
8
–
backspace (забой)
9
–
tab (табуляция)
13
–
enter
32
–
пробел
33
–
!
34
–
«
35
–
#
36
–
$
37
–
%
38
–
&
39
–
"
40
–
(
41
–
)
42
–
*
43
–
+
44
–
,
45
–
–
46
–
.
47
–
/
48...57
–
0...9
58
–
:
59
–
;
60
–
<
61
–
=
52
–
>
63
–
?
64
–
@
65...90
–
A...Z
91
–
[
92
–
/
93
–
]
94
–
^
95
–
_
96
–
"
97...122
–
a...z
123
–
{
124
–
??
125
–
}
126
–
~
128...159
–
A...Я
160...175
–
а...п
224...239
–
р...я
Управляющие клавиши и их сочетания со сдвиговыми
0
3
Ctrl–2
0
15
Shift – Tab
0
16...25
Alt–Q...Alt–P (верхний ряд букв)
0
30...38
Alt–A...Alt–L (средний ряд букв)
0
44...50
Alt–Z...Alt–M (нижний ряд букв)
0
0
71
Home
0
75
курсор влево
0
73
PgUp
0
79
End
0
77
курсор вправо
0
81
PgDn
0
80
курсор вниз
0
83
Del
окончание таблицы
код
клавиша или комбинация клавиш
код
клавиша или комбинация клавиш
первый байт
второй байт
первый байт
второй байт
0
82
Ins
0
94...103
Ctrl–F1...Ctrl–F10
0
84...93
Shift–F1... Shift–F10
0
114
Ctrl– PrtScr
0
104...113
Alt–F1...Alt–F10
0
116
Ctrl – курсор вправо
0
115
Ctrl – курсор влево
0
118
Ctrl – PgDn
0
117
Ctrl – End
120...131
alt–1...alt– = (верхний ряд клавиш)
0
119
Ctrl – Home
0
132
Ctrl – PgUp
, описываемые в этом разделе.
используется для задания одного из возможных текстовых режимов работы адаптера монитора. Заголовок процедуры:
TextMode
(
mode
:
word
);
– код текстового режима. в качестве значения этого выражения могут использоваться следующие константы, определенные в модуле CRT
:
, запоминается в глобальной переменной LastMode
модуля CRT
и может использоваться для восстановления начального состояния экрана.
сбрасываются все ранее сделанные установки цвета и окон, экран очищается и курсор переводится в его левый верхний угол.
l
n (s), {вывести сообщение}
l
n ('нажать клавишу enter...');
l
n {ждем нажатия клавиши enter}
со
40);
режим
40*25');
режим
80*25');
режим
co40+font8*8');
(
co
80+
font
8*8);
(
lm
)
.
определяет цвет выводимых символов. заголовок процедуры:
TextColor
(
color
:
byte
);
определяет цвет фона. заголовок процедуры:
TextBackGround
(
color
:
byte
);
=0; {черный}
blue
=9; {синий}
=10; {светло-зеленый}
=11; {светло-бирюзовый}
=12; {розовый}
=13; {малиновый}
=14; {желтый}
=15; {белый}
цвет
", k, "-", col [k] )
белые
мигающие
символы
}
(
lightgray
),
.
ln
. Если его убрать, режим мерцания символов сохранится после завершения программы, несмотря на то, что перед ним стоит оператор
модуля CRT
и используются для настройки адаптера только при обращении к процедурам write/writ
eln
.
очищает экран или окно (см. ниже процедуру window
). после обращения к ней экран (окно) заполняется цветом фона и курсор устанавливается в его левый верхний угол. например:
: char
заполняем
экран
красным
цветом
}
нажмите
любую
клавишу
...");
:= ReadKey, {
ждем
нажатия
любой
клавиши
}
восстанавливаем
черный
фон
экрана
}
определяет текстовое окно – область экрана, которая в дальнейшем будет рассматриваться процедурами вывода, как весь экран. Сразу после вызова процедуры курсор помещается в левый верхний угол окна, а само окно очищается (заполняется цветом фона). По мере вывода курсор, как обычно, смещается вправо и при достижении правой границы окна переходит на новую строку, а если он к этому моменту находился на последней строке, содержимое окна сдвигается вверх на одну строку, т.е. осуществляется «прокрутка» окна. Заголовок процедуры:
Window
(
xi
,
yi
, х2,
y
2:
byte
);
– координаты левого верхнего (х1, y1
) и правого нижнего (х2, y2
) углов окна. Они задаются в координатах экрана, причем левый верхний угол экрана имеет координаты (1,1), горизонтальная координата увеличивается слева направо, а вертикальная – сверху вниз.
нажать
клавишу
enter... ");
ждем
нажатия
enter}
очищаем
окно
}
нажать
клавишу
enter...
");
;
:=39+(
lshl
8);
WindMax
:= 69+(16
shl
8);
переводит курсор в нужное место экрана или текущего окна. Заголовок процедуры:
GotoXY
(Х,
Y
:
Byte
);
и WhereY
. С помощью этих функций типа Byte
можно определить текущие координаты курсора: WhereX
возвращает его горизонтальную, а WhereY
– вертикальную координаты.
k
:
integer
;
ClrScr
; { очиститъ экран}
верхнюю
горизонтальную черту }
в
нижний
левый
угол
+1}
нижнюю
горизонтальную черту}
стирает часть строки от текущего положения курсора до правой границы окна (экрана). Положение курсора не меняется.
DelLine
уничтожает всю строку с курсором в текущем окне (или на экране, если окно не создано). При этом все строки ниже удаляемой (если она есть) сдвигаются вверх на одну строку.
вставляет строку: строка с курсором и все строки ниже ее сдвигаются вниз на одну строку; строка, вышедшая за нижнюю границу окна (экрана), безвозвратно теряется; текущее положение курсора не меняется.
LowVideo
,
No
rm
Video
и
HighVideo
. С помощью этих процедур без параметров можно устанавливать соответственно пониженную, нормальную и повышенную яркости символов. Например:
CRT
;
;
связывает текстовую файловую переменную F с экраном с помощью непосредственного обращения к видеопамяти (т.е. к памяти, используемой адаптером для создания изображения на экране). В результате вывод в такой текстовый файл осуществляется значительно быстрее (в 3...5 раз), чем если бы этот файл был связан с экраном стандартной процедурой Assign
. Заголовок процедуры: Procedure Assign CRT (F: Text);
связывается «медленной» процедурой Assign
со стандартным устройством CON
(т.е. с экраном) и подсчитывается количество N
циклов вывода некоторого текста за 5*55=275 миллисекунд системных часов. Затем файловая переменная связывается с экраном с помощью процедуры быстрого доступа Assign CRT
и точно так же подсчитывается количество N2
циклов вывода. В конце программы счетчики NI
и N2
выводятся на экран.
= '
Text
';
готовим
счетчик
вывода
}
очищаем
экран
}
:=
Meml
[$0040:$006
C
];
Meml
[$0040:$006
C
]<
t
+6
do
;
(
F
);
печатаем
результат
}
), также осуществляется с помощью непосредственного доступа к видеопамяти, поэтому ценность процедуры AssignCRT
весьма сомнительна. Прямой доступ к видеопамяти регулируется глобальной логической переменной DirectVideo
модуля CRT
: если эта переменная имеет значение True
, доступ разрешен, если False
— доступ к экрану осуществляется с помощью относительно медленных средств операционной системы MS—DOS. По умолчанию переменная DirectVideo
имеет значение True
.
включены три процедуры, с помощью которых вы сможете запрограммировать произвольную последовательность звуков.
заставляет динамик звучать с нужной частотой. заголовок процедуры Procedure
Sound
(F
: Word);
здесь F
– выражение типа Word
, определяющее частоту звука в герцах. После обращения к процедуре включается динамик, и управление немедленно возвращается в основную программу, в то время как динамик будет звучать впредь до вызова процедуры NoSound
.
выключает динамик. Если он к этому моменту не был включен, вызов процедуры игнорируется.
oбеспечивает задержку работы программы на заданный интервал времени. Заголовок процедуры: Procedure
Delay
(
T
:
Word
);
— выражение типа Word
, определяющее интервал времени (в миллисекундах), в течение которого задерживается выполнение следующего оператора программы.
. следующая программа заставит пк воспроизвести простую музыкальную гамму. Используемый в ней массив F
содержит частоты всех полутонов в первой октаве от «до» о «си». При переходе от одной октавы к соседней, частоты изменяются в два раза.
восходящая
гамма
}
нисходящая
гамма
}
. Здесь максимальные размеры матрицы – 10*10 элементов типа byte
. Ввод информации производится в окне светло-бирюзового цвета, вывод результатов – в окне малинового цвета, цвет букв – желтый.
, написанную на основе Prim 52
.
очистить
экран
}
цвет
11,
светло
-
бирюзовый
}
ввести
b[',j,']
элемент
вектора
b');
(20,2,80,18);
GotoXY
(2,2);
l
:=3;
начать
новую
строку
}
12. Графика в Паскале
. Общий вид программы с использованием Graph
имеет следующий вид:
t
; {определение номера, установленного в системе драйвера}
errCode
=
grOK
then
Две кавычки в init
Graph
правомочны только тогда, когда графическая программа находится в том же каталоге, что и библиотека Graph
. В противном случае в кавычках должен стоять путь – указание, где находится библиотека Graph
.
и GetMaxY
возвращают значения типа Word
, содержащие максимальные координаты, соответственно, X и Y относительно левого верхнего угла в пикселах (точках).
и GetY
возвращают текущие координаты указателя. Процедура SetViewPort (Х1, Y1, Х2, Y2,
Clipon
);
устанавливает прямоугольное окно на графическом экране, X1, Y1
- координаты левого верхнего угла; Х2, Y2
- координаты нижнего правого угла окна.
имеет значение true
и элементы изображения не помещаются в окне, то они отсекаются, если – false
, то отсечка игнорируется.
устанавливает новое текущее положение указателя.
устанавливает приращения новых координат указателя относительно старых.
очищает графический экран, указатель устанавливается в левый верхний угол, экран заполняется цветом, заданным процедурой SetBkColor
.
выводит на экран точку Color
цвета. Процедура LineTo (Х, Y);
вычерчивает линию от текущего положения указателя до точки Х, Y
.
SetLineStyle (
Туре
, Pattern, Thick);
– тип линии. Pattern
– образец линии. Thick
– толщина линии.
вычерчивает прямоугольник с использованием текущего цвета и текущего стиля линий.
P
oly (N, Р);
вычерчивает произвольную ломаную линию. N
- количество точек излома, включая крайние; Р
- переменная типа PointType
, которая в Graph
имеет вид:
Circle (Х, Y, R);
вычерчивает окружность с центром X, Y
и радиусом R
.
вычерчивает дугу окружности Beg А
и End А
, соответственно, начальный и конечный углы дуги.
вычерчивает дугу эллипса с центром X, Y; Beg А, End А
– начальный и конечный угол, RX
и RY
– горизонтальный и вертикальный радиусы.
заполняет прямоугольную область экрана образцом узора и текущим цветом, которые устанавливаются процедурой SetF
il
lStyle
.
r
3
D
(Х1, Y1, Х2, Y2, Depth, Тор);
вычерчивает трехмерное изображение параллелепипеда и закрашивает его переднюю грань. Depth
– глубина третьего измерения, Top=
t
rue
– верхняя грань вычерчивается, false
- нет.
обводит линией и закрашивает замкнутый многоугольник; n
– количество вершин, Coords
– переменная типа Poin
t
Type
, содержащая координаты вершин (см. DrawPoly
).
il
lEllipse (Х, Y, Rx, Ry);
обводит линией и заполняет эллипс.
вычерчивает и заполняет эллипсный сектор.
вычерчивает и заполняет сектор окружности.
устанавливает текущий цвет для выводимых линий и символов.
устанавливает цвет фона окна.
ill
Style (Fill, Color);
устанавливает стиль Fill
и цвет заполнения Color
.
:
заполняет произвольную замкнутую линию (точки соединения должны совпадать, например, концы линий не могут пересекаться) текущим стилем и текущим цветом. X, Y
– координаты точки внутри фигуры, Color
— цвет ограничений линии. Если линии разомкнуты или пересекаются и концы «торчат», то цвет «разольется» по всему окну.
возвращает размер памяти в байтах, необходимый для размещения прямоугольного фрагмента изображения (например, окна с рисунком).
помещает в память копию прямоугольного фрагмента изображения. Buf
— переменная или участки кучи, куда будет помещена копия видеопамяти с фрагментом изображения. Размер Buf
должен быть не меньше значения, возвращаемого функцией ImageSize
с теми же координатами X1...Y2
.
выводит в заданное место экрана копию фрагмента изображения, ранее помещенную в память процедурой GetImage
.
, Y
— координаты левого угла того места на экране, куда будет скопирован фрагмент изображения. Buf
— переменная, или участок кучи, откуда берется фрагмент изображения. Mode
— способ копирования.
демонстрирует вывод различных простых объектов-окружностей, дуг, эллипсов, прямоугольников, параллелепипедов.
определение
номера
драйвера
}
(
grDriver
,
grMode
,'');
radius
:=1
to
5
do
(200,70,
Radius
*10);
readln
;
end
;
дуги
с
центром
300,100,
от
параллелепипед
без
крышки
}
закрыть
Graph}
режим
Graph
не
удалось
открыть
. }
рисует в динамике случайно расположенные цветные линии в окне до тех пор, пока не будет нажата клавиша Enter
. Затем машина выводит последним случайным цветом главную диагональ окна, после Enter
– случайные лучи и после Enter
– прямоугольник.
перевести
курсор
}
прямоугольник
}
рисует эллипсы и круги, закрашенные красным цветом.
рисуетобезьянустазиком.
уши
}
майка
}
пояс
}
штаны
}
левая
нога
}
правая
нога
}
башмаки
}
бабочка
}
тазик
}
руки
}
демонстрирует возможности мультипликации: по фоновому рисунку – дом, луна, висящий "базовый" НЛО; мечется с переменной скоростью малый НЛО и издает звуки случайными частотами.
d
,
m
,
e
,
xm
,
ym
,
x
,
y
,
lx
,
ly
,
rx
,
ry
,
size
,
i
,
dx
,
dy
,
тарелка
}
(
x
+1,
y
+4,
White
);
создаем
звездное
небо
}
дом
}
дом
}
чердак
}
крыша
}
крыша
чердака
}
мачта
антенны
}
верхний
ус
антенны
}
нижний
ус
антенны
}
средний
ус
антенны
}
земля
}
окна
}
месяц
}
дерево
}
основной
цикл
}
:
x
:=
x
+
dx
;
else
CloseGraph
;
.
Название реферата: Основы программирования на языке Паскаль
Слов: | 31454 |
Символов: | 292944 |
Размер: | 572.16 Кб. |
Вам также могут понравиться эти работы:
- Основы работы в операционной системе MS-DOS. Командные файлы и оболочка операционной системы Tot
- Компьютерное моделирование полимеров
- Тестувальна програма з дісциплини Вища математика
- История развития информационного рынка в России
- Руководство начинающего консультанта по SAP
- Экономико математическая модель
- Системне програмне забезпечення С