- •ПРЕДИСЛОВИЕ
- •1.1. История и классификация языков программирования высокого уровня
- •1.2. Первое (знакомство с Паскалем
- •Задания
- •Лекция 2
- •2.1. Некоторые сведения о системе ТУрбо-Паскаль
- •2.2. Способы описания языка программирования
- •Лекция 3
- •3.2. Типы данных
- •4.1. Структура Паскаль-программы
- •4.2. Арифметические операции, функции, выражения Арифметический оператор присваивания
- •Форматы процедуры write
- •Задания
- •1. Что будет напечатано программой
- •если последовательно вводятся три числа: 36, -6, 2345?
- •5.2. Функции, связывающие различные типы данных
- •Задания
- •Теперь посмотрим, как это программируется наТЛаскале.
- •Здесь
- •<параметр цикла>::= <имя простой переменной порядкового типа>
- •Задания
- •7.1. Подпрограммы-процедуры
- •7.2. Подпрограммы-функции
- •7.4. Рекурсивные подпрограммы
- •8.1. Что такое рекуррентная последовательность
- •8.2. Программирование вычислений рекуррентных последовательностей
- •Задания
- •Задания
- •6. Вывод результата.
- •Теперь будем составлять подпрограммы.
- •Задания
- •12.2. Операции над множествами
- •12.3. Примеры использования множеств
- •Красивая программа! К сожалению, ею нельзя воспользоваться для
- •В этой программе использована функция определений размера файла:
- •.Fiiesize(<HMH файловой переменной>);
- •Задания
- •14.2. Работа с файлами записей
- •Задания
- •15.2. Связанные списки
- •Лекция 16
- •16.1. Организация внешних подпрограмм
- •16,2. Создание и использование модулей
- •распечаткой текста программы с подробными комментариями.
- •выполнения следующих операции над обыкновенными дробями вида -q
- •(Р — целое, Q — натуральное):
- •1) сложение;
- •2) вычитание;
- •3) умножение;
- •4) деление;
- •5) сокращение дроби;
- •7) функции, реализующие операции отношения (равно, не равно,
- •Используя этот модуль, решить задачи:
- •При разработке модуля рекомендуется такая последовательность
- •Задания
- •Приведем текст программы целиком.
- •ЗАДАНИЯ ПО ТЕМЕ “ЛИНЕЙНЫЕ АЛГОРИТМЫ”
- •ЦЕЛОЧИСЛЕННАЯ АРИФМЕТИКА
- •Сортировка массивов
- •ЗАДАЧИ ПО ТЕМЕ “ОБРАБОТКА СТРОК”
- •ЗАДАНИЯ ПО ТЕМЕ “МОДУЛИ”
- •ЗАДАНИЯ ПО ТЕМЕ “ДИНАМИЧЕСКИЕ ПЕРЕМЕННЫЕ”
- •Задачи, предлагавшиеся на школьных олимпиадах по программированию (Пермская область)
- •Учебное издание
4.Выделение операндов. Проверка операндов на допустимый диа пазон значений. Перевод в целые числа.
5.Выполнение операции. Проверка результата на допустимый ди апазон.
6.Вывод результата.
Program Interpretator;
Type Pozlnt - 0..Maxlnt
Var Line String;
A, В Pozlnt;
Znak Char;
Flag Boolean;
Rezult |
Integer; |
String; M Byte; Var N Byte); |
Procedure Propusk(Stroke |
||
Begin |
|
|
{ ---------------------- - ................. |
- .................................... |
Пропускает подряд стоящие пробелы в строке Stroka, начиная с символа номер М. В переменной N подучает номер первого символа, не являющегося пробелом.
End; |
|
|
|
|
Function |
Cifra(C |
Char) |
Boolean; |
|
Begin |
|
|
|
|
{ ........... |
- ....................... |
|
- .................................................. |
если символ с является цифрой, |
|
Получает значение True, |
|||
|
и False - в противном случае. |
|||
Function |
Sintах(Stroka |
String) |
Boolean; |
|
Begin |
|
|
|
|
{ ............. |
............ ............... |
|
- ................................................... |
|
Синтаксический контроль. Получает значение True, если в строке нет других символов хроме цифр, знаков операции, знака и пробелов. В противном случае - False.
End;
Function Semantika(Stroka String) Boolean;
Begin
{ ---------------------------------------------------------------------------------
Проверяет, соответствует ли структура строки формату
"а@Ъ«"? Если ”да”, то получает значение True, если
"нет” |
False. |
|
} |
----------------------------------------- |
|
------------- |
|
End; |
|
|
|
Procedure Operand(Stroka |
String; Var A, В |
Pozlnt; |
|
Begin |
Var Z |
Char; Var Flag |
Boolean); |
|
|
|
|
{ ........................ |
- |
................. - ------------------------------------------ |
Выделяет операнды. Проверяет их на допустимый диапазон значении. Переменная Flag получает значение True,
если результат проверки положительный, и False - в противном случае. Преобразует операнды в целые положительные числа А, В. В переменной Z получает знак операции.
---------------------------- >
End; |
|
|
|
|
Procedure Calc(А, |
В Pozlnt; Znak |
Char; Var Rez |
Integer; |
|
Var Flag |
Boolean); |
|
|
|
Begin |
|
|
|
|
{ ---------------------------------------------------------------------- |
результат |
операШШ. |
Проверяет |
----------- |
Вычисляет |
|
принадлежность результата диапазону от -Maxlnt д<?
Maxlnt. Flag - признак результата проверки. Результат операции получается в переменной Rez.
------------------------ ----------- ----------- .------>
End;
Begin {------- Начало основной части программы ----} WriteLnOВведите выражение: *);
WriteLn;
Read(Line);
If Not Sintax(Line)
Then WriteLn(* Недопустимые символы’)
Else If Not Semantika(Line)
Then WriteLnО Неверное выражение’)
Else Begin
Operand(Line, A, B, Znak, Flag);
If Not Flag
Then WriteLn( ’Слишком большие операнды’)
Else Begin
Calc(A,В ,Znak,Rezult,Flag);
If Not Flag
Then WriteLn(’Большой результат1)
Else WriteLn(Rezult)
End
End
Теперь будем составлять подпрограммы.
Procedure Propusk(Stroka |
String; М Byte; Var N |
Byte); |
|
Begin |
M; |
|
|
N |
*) And (N < Length(Stroka)) |
Do |
|
While |
(StrokaCN] = |
N := N + 1
End;
Function Cifra(C Char) Boolean;
Begin
Cifra := (С >= >0’) And (C <= >9>)
End;
Function |
Sintax(Stroka |
String) |
|
Boolean; |
||
Var I |
Byte; |
|
|
|
|
|
Begin |
:= True; |
|
|
|
|
|
Sintax |
|
|
|
|
||
For I :■ 1 To Length(Stroka) Do |
|
|
||||
If Not |
((StrokaEl]*’ ’) Or Cifra(Stroka[I]) Or (StrokaE^*^’) |
|||||
|
Or (Stroka[l]ss,->) Or |
(Stroka[I] =,*>) Or (Stroka[I] = ,=>)) |
||||
Then Sintax := False |
|
|
|
|||
End; |
|
|
|
|
|
|
Function |
Semantika(Stroka |
String) |
Boolean; |
|||
Var I |
Byte; |
|
|
|
|
|
Begin |
|
|
|
|
|
|
Semantika :■ True; |
I); |
|
|
|
||
Propusk(Stroka, |
1, |
|
|
|
||
If Not Cifra(Stroka[I]) |
|
|
|
|||
Then |
|
|
|
|
|
|
Begin |
|
|
|
|
|
|
Semantika := False; |
|
|
|
|||
Exit |
|
|
|
|
|
|
End; |
|
|
|
|
|
|
While Cifra(Stroka[I]) Do |
|
|
||||
I:=I+1; |
I, |
I); |
|
|
|
|
Propusk(Stroka, |
|
|
|
|||
If Not ((StrokaCl] |
= »+’) Or (Stroka[I] = »-») Or (Stroka[I] - »*»)) |
|||||
Then |
|
|
|
|
|
|
Begin |
|
|
|
|
|
|
Semantika := False; |
|
|
|
|||
Exit |
|
|
|
|
|
|
End; |
|
|
|
|
|
|
I := I + 1; |
I, |
I); |
|
|
|
|
Propusk(Stroka, |
|
|
|
While Cifra(Stroka[l]) Do
Begin |
|
|
Stroka[I]; |
|
||||
Q |
:* Q + |
|
||||||
I |
|
I + |
1 |
|
|
|
|
|
End; |
|
|
|
|
|
|
|
|
If Error(Q) |
|
|
|
|
|
|||
Then |
|
|
|
|
|
|
|
|
Begin |
:* False; |
|
|
|
||||
Flag |
|
|
|
|||||
Exit |
|
|
|
|
|
|
|
|
End; |
|
|
|
|
I, |
I); |
|
|
Propusk(Stroka, |
|
|||||||
Z :*» Stroka[I] ; |
|
|
|
|||||
I |
I + |
1; |
|
|
I, |
I); |
|
|
Propusk(Stroka, |
|
|||||||
P :* |
|
|
|
|
|
|
|
Do |
While Cifra(Stroka[I]) |
||||||||
Begin |
|
|
|
|
|
|
|
|
P |
:* P + StrokaCl]; |
|
||||||
I |
|
I + |
1 |
|
|
|
|
|
End; |
|
|
|
|
|
|
|
|
If Error(P) |
|
|
|
|
|
|||
Then |
|
|
|
|
|
|
|
|
Begin |
|
|
|
|
|
|
|
|
Flag :■ False; |
|
|
||||||
Exit |
|
|
|
|
|
|
|
|
End; |
|
A, |
Code); |
|
|
|
||
Val(Q, |
|
|
|
|||||
Val(P, |
B, |
Code) |
|
|
|
|||
|
{Стандартная процедура Val преобразует цифровую |
|||||||
End; |
строку в соответствующее число; Code - код ошибки} |
|||||||
|
|
|
|
|
|
|
|
|
Procedure |
Calc(А, |
В |
Pozlnt; Znak Char; |
|||||
Var X, |
Y, Z |
Var Rez |
Integer; Var Flag Boolean); |
|||||
Real; |
|
|||||||
Begin |
:« True; |
|
|
|
|
|||
Flag |
|
|
|
|
Y:= A;
Z:= B;
Case |
Znak Of |
+ Z; |
|
*+' |
X |
:= Y |
|
|
X |
:* Y |
- Z; |
|
X |
:= Y |
* Z |
End;
If Abs(X) > Maxlnt
Then
Мы уже говорили о том, что качественная программа ни в каком варианте не должна завершиться аварийно. Тесты программы Inter- pretator должны продемонстрировать, что при правильном вводе ис ходной строки будут всегда получаться правильные результаты, а при наличии ошибок (синтаксических, семантических, выход за диапазон) будут получены соответствующие сообщения. План тестирования на шей программы может быть, например, таким:
N |
Что вводим |
|
Что должно получиться |
||
1 |
25+73= |
|
|
98 |
|
2 |
5274 |
- |
12315 |
= -7041 |
|
3 |
614 * |
25 |
= |
|
15350 |
4 |
25,5 |
+ 31,2 |
= |
Недопустимые символы |
|
5 |
5=6-1 |
|
|
|
Неверное выражение |
6 |
72315 |
- |
256 |
= |
Слишком большие операнды |
7 |
32000*100= |
|
Большой результат |
Правильное прохождение всех тестов есть необходимое условие пра вильности программы. Замечу, что “необходимое” , но не всегда доста точное. Чем сложнее программа, тем труднее построить исчерпываю щий план тестирования. Опыт показывает, что даже в “фирменных” программах обнаруживаются ошибки в процессе эксплуатации. По этому проблема тестирования программы — очень важная и, одно временно, очень сложная.
Обратите внимание на то, что уже сама удачно выбранная форма записи данных дает возможность достаточно удобно и быстро полу чить новую информацию. Например, из таблицы легко узнать, в каком году был самый холодный январь или какой месяц был самым неста бильным за десятилетие.
Для значений, хранящихся в такой таблице, удобно использовать двухиндексные обозначения. Например, # 1981,2 обозначает температуру в феврале 1981 года и т.п. А вся совокупность данных, соста вляющих таблицу, математически обозначается так:
i = 1981..1990; j = 1..12.
Обработка таких данных производится с двухиндексными величинами. Например, средняя температура марта за 10 лет вычисляется по фор муле:
I |
1990 |
# с р .м а р т = ттг |
# 1 ,3 * |
1Ui=1981
А значение средней температуры за весь десятилетний период вы числяется так:
1 |
1990 |
1 |
12 |
iU t=1981 |
и |
£*«•./ |
|
l£ j=1 |
11990 12
=Ш Е
1ZUi=1981 j=l
В Паскале аналогом таблиц является структурированный тип дан ных, который называется регулярным типом или массивом. Так же, как и таблица, массив представляет собой совокупность пронумеро ванных однотипных значений, имеющих общее имя. Элементы массива обозначаются в виде переменных с индексами. Индексы записываются в квадратных скобках после имени массива. Например:
Г[1], Г[5], ТЩ, #[1981,9], Я М И т .п .
Массив, хранящий линейную таблицу, называется одномерным, прямоугольную таблицу — двумерным. В программах могут исполь зоваться массивы и большей размерности.
Тип элементов массива называется его базовым типом. Очевидно, для рассмотренных массивов температур базовым типом является ве щественный (Real).
Описание массивов. Переменная регулярного типа описывается в разделе описания переменных в следующей форме:
До сих пор речь шла об одномерных массивах, в которых типы эле ментов скалярные. Многомерный массив в Паскале трактуется как одномерный массив, тип элементов которого также является массивом (массив массивов). Например, рассмотренную выше прямоугольную таблицу можно хранить в массиве, описанном следующим образом:
Var Н Array[1981..1990] Of Array[1..12] Of Real;
Вот примеры обозначения некоторых элементов этого массива:
н[1981] [1] ; н[1985] [10]; Н[1990] [12] .
Однако чаще употребляется другая, эквивалентная форма обозначения элементов двумерного массива:
Н [1981,1]; Н[1985,10]; Н[1990,12].
Переменная Н [1981] обозначает всю первую строку таблицы, т.е. весь массив температур за 1981 год.
Другим эквивалентным вариантом приведенному выше описанию является следующее:
Type Month = Array [1..12] Of Real;
Year = Array [1981..1990] Of Month;
Var H Year;
Наиболее краткий вариант описания данного массива такой:
Var Н Array[1981..1990, 1..12] Of Real;
Продолжая по аналогии, можно определить трехмерный массив как одномерный массив, у которого элементами являются двумерные мас сивы. Вот пример описания трехмерного массива:
Var A Array[1..10, 1..20, 1..30] Of Integer;
Это массив, состоящий из 10 20 30 = 6000 целых чисел и занимающий в памяти 6000 2 = 12000 байт. В Паскале нет ограничения сверху на размерность массива. Однако в каждой конкретной реализации Паскаля ограничивается объем памяти, выделяемый под массивы. В Турбо-Паскале это ограничение равно 64 килобайтам.
По аналогии с математикой одномерные числовые массивы часто называют векторами, а двумерные — матрицами.
В Паскале не допускается употребление динамических массивов, т.е. таких, размер которых определяется в процессе выполнения. Измене ние размеров массива происходит через изменение в тексте програм мы и повторную компиляцию. Для упрощения таких изменений удобно определять индексные параметры в разделе констант.
Const Imax=10; JmaxB20;
Var Mas Array[1 ..Imax, l..Jmax] Of Integer;
Теперь для изменения размеров массива Mas и всех операторов прог раммы, связанных с этими размерами, достаточно отредактировать только одну строку в программе — раздел констант.
Действия над массивом как единым целым. Такие действия допустимы лишь в двух случаях:
-присваивание значений одного массива другому;
-передача массива в качестве фактического параметра при обращении
кподпрограмме.
Впервом случае оба массива должны быть идентичны по описанию.
Пример:
Type Mas = Аггау[1..5, 1. 10] Of Real;
Var Р, Q Mas;
При выполнении операции присваивания
Р := q
все элементы массива Р станут равны соответствующим элементам массива Q.
Как уже отмечалось, в многомерных массивах переменная с индек сом может обозначать целый массив. Например, если в таблице Н тре буется данные за 1989 год сделать такими же, как за 1981 год (девятой строке присвоить значение первой строки), то это можно делать так:
Н[1989] := Н[1981].
Во втором случае должен соблюдаться принцип соответствия типов между массивами - формальными параметрами и массивами - фактически ми параметрами. Например, в программе имеются следующие описания:
Type Mas = Аггау[1..5, 1 .10] Of Real; Var Y: Mas;
Procedure PRIM(X: Mas);
Тогда в этой программе возможно следующее обращение к процедуре:
PRIM(Y);
116
Обработка массивов в программах производится покомпонентно. Вот примеры ввода значений в массивы:
For I :* 1 То 12 Do
ReadLn(T[I]);
For I :» 1 To IMax Do
For J :* 1 To Jmax Do
ReadLnCMasCl, J]);
Здесь каждое следующее значение будет вводиться с новой строки. Для построчного ввода используется оператор read.
Аналогично в цикле по индексной переменной организуется вывод значений массива. Например:
For I :*1 То 12 Do Write(T[I] :8:4);
Следующий фрагмент программы организует построчный вывод матрицы на экран:
For I:«l То IMax Do
Begin
For J:*l to JMax Do
Write(Mas[I,J]:6);
WriteLn
End;
После печати очередной строки матрицы оператор writeln без пара метров переведет курсор в начало новой строки. Следует заметить, что в последнем примере матрица на экране будет получена в есте ственной форме прямоугольной таблицы, если Jmax не превышает 12 (сами подумайте, почему).
Рассмотрим несколько примеров типовых программ обработка мас
сивов.
Пример 1. Вернемся к массиву среднемесячных температур Т[1..12]. Требуется вычислить среднегодовую температуру, а также ежемесячные отклонения от этой величины.
Program Example;
Cont |
N |
* |
12; |
Type |
Vec |
*= Array [1..N] Of Real; |
|
Var T, |
Dt*: Vec; |
||
|
St |
|
Real; |
|
I |
|
Integer; |
Begin |
{____________ Ввод исходных данных. |
|
.} |
||||||
WriteLn(*Вводите таблицу температур ’); |
|
|
|||||||
For I := 1 То N Do |
|
|
|
|
|
||||
Begin |
|
2, |
|
|
|
|
|
|
|
Write(I |
|
|
|
|
|
|
|||
ReadLn(T[I] ) |
|
|
|
|
|
||||
End; |
{_________Вычисление средней температуры__________ } |
||||||||
|
|||||||||
St := 0; |
|
|
|
|
|
|
|
||
For I := 1 To N Do |
|
|
|
|
|
||||
St |
:= St + T[IJ ; |
|
|
|
|
|
|||
St |
:= St |
/ N; |
|
|
|
|
|
||
For |
{____ Вычисление таблицы отклонений от среднего___ } |
||||||||
I |
:= 1 То |
N Do |
|
|
|
|
|
||
Dt[I] |
:« St |
- T[I]; |
|
|
|
|
|
||
|
{___________ Вывод результатов___________________ } |
||||||||
WriteLn(’Средняя температура рйЬна |
’f St |
6 |
2); |
||||||
WriteLn; |
|
|
от средней температуры:’); |
|
|||||
WriteLn(’Отклонения |
|
||||||||
For |
I |
:= 1 To |
N Do |
DtCl] |
6 |
2) |
|
|
|
WriteLn(I |
1, ’ |
|
|
||||||
End. |
|
|
|
|
|
|
|
|
|
По этой программе можно рассчитать среднее значение и вектор отклонении от среднего для любого одномерного вещественного мас. сива. Настройка на размер массива осуществляется только РеЦактировакием раздела констант.
П ример 2. В ы бор максимального элемента. Пусть Из рас смотренного выше массива температур требуется отобрать самую высокую температуру и номер месяца, ей соответствующий. ^ горитма решения этой задачи: чтобы получить максимальную Темпе ратуру в вещественной переменной ТМах, сначала в нее заносится первое значение массива Т[1]. Затем поочередно сравнивается зна чение ТМах с остальными элементами массива температур, и каждое значение, большее чем ТМах, присваивается этой переменнойДдд по_ лучения номера самого теплого месяца в целой переменной N umK{ax в нее следует каждый раз засылать номер элемента массива тО^^ратур одновременно с занесением в ТМах его значения.
ТМах := Т [1]; NumMax := 1;
For I 2 То 12 Do
If T[I] > ТМах
Then
Begin
TMax := T[I] ;
NumMax := I
End;
Заметим, что если в массиве температур несколько значений, рав ных максимальному, то в NumMax будет получен первый номер из этих элементов. Чтобы получить последнюю дату, нужно в операторе if заменить знак отношения ” > ” на ” > = ”
П ример 3. С ортировка массива. В одномерном массиве X из N элементов требуется произвести перестановку значений так, чтобы они расположились по возрастанию, т.е. Х\ < Х 2 < •.> < X N.
Существует целый класс алгоритмов сортировки. Ниже описан ал горитм, который называется “метод пузырька”
Идея: производится последовательное упорядочивание смежных пар элементов массива: Х\ и Х 2, X 2 и X 3, ..., X^^i и Ху. В итоге мак симальное значение переместится в Х ^ . Затем ту же процедуру по вторяют до Xjy-i и т.д., вплоть до цепочки из двух элементов Х\ и X*i' Такой алгоритм будет иметь структуру двух вложенных циклов, причем внутренний цикл — переменной (сокращающейся) длины.
For I 1 То Ы - 1 Do
For К := 1 То N - I Do
If Х[К] > Х[К + 1]
Then
Begin
А := X[К];
Х[К] := Х[К + 1]; Х[К + 1] := А End;
П ример 4. Дан описанный выше двумерный массив среднемесяч ных температур за 10 лет. Определить, в каком году было самое теплое лето, т.е. в каком году была наибольшая средняя температура летних
месяцев.
Идея решения: в векторе S получить средние температуры летних месяцев за 10 лет. Затем найти номер наибольшего элемента в этом векторе, это и будет искомый год.
Program Example_2;
Type Month = Array[1.. 12] Of Real;
Year ■ A r r a y [1981..1990] Of Month;
Var H Year;