Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Алгоритмизация и языки программирования. Учебно-методический комплекс.pdf
X
- •1. СИЛЛАБУС ДИСЦИПЛИНЫ ДЛЯ СТУДЕНТОВ
- •Тема 1. Понятие алгоритма, свойства, типы, исполнители
- •Структура программы.
- •Имена, ключевые слова и знаки операций
- •Тема 7. Символьные типы данных.
- •Обработка символьных данных.
- •Тема 9. Строки. Строковые процедуры.
- •Функции
- •Тема 11. Множества (Set)
- •Работа с текстовыми файлами
- •Тема 13. Записи
- •Тема 14. Построение изображений на экране
- •Отображение точки на экране
- •Отображение линий на экране
- •Построение прямоугольников на экране
- •Построение многоугольников
- •Построение дуг, эллипсов и окружностей
- •Основная литература
- •Дополнительная литература
- •ГЛОССАРИЙ

Такие способы ввода и вывода данных массива распростра-
няются и на массивы большей размерности. Элементы многомерных
массивов в памяти компьютера располагаются «по строкам». То есть
сначала расположены все элементы первой строки (первый индекс
фиксирован и равен своему минимальному значению), затем второй и
т.д. Таким образом, при равноправном расположении вложенных
циклов для обработки многомерного массива сначала следует
организовать цикл по первому индексу, потом по второму и т.д.
Наибольший интерес представляют квадратные матрицы, то
есть двумерные массивы, у которых количество строк и столбцов
совпадает, например:
a: array[1..3,1..3] of integer;
Обращение к компонентам массива
Массивы относятся к структурам прямого доступа. Это озна-
чает, что возможно напрямую (не перебирая предварительно все
предшествующие компоненты) обратиться к любой интересующей
нас компоненте массива.
Доступ к компонентам линейного массива осуществляется так:
<имя_массива>[<индекс_компоненты>]
а многомерного - так:
<имя_массива>[<индекс>,_,<индекс>]
Правила употребления индексов при обращении к компонентам
массива таковы:
1. Индекс компоненты может быть константой, переменной или
выражением, куда входят операции и вызовы функций.
2. Тип каждого индекса должен быть совместим с типом,
объявленным в описании массива именно для соответствующего
"измерения"; менять индексы местами нельзя.
3. Количество индексов не должно превышать количество
"измерений" массива. Попытка обратиться к линейному массиву как
к многомерному обязательно вызовет ошибку. А вот обратная
ситуация вполне возможна: например, если вы описали N-мерный
массив, то его можно воспринимать как линейный массив, состоящий
из (N-1)-мерных массивов.
Примеры использования компонент массива:
a2['z']:= a2['z']+1;
41

a3[-10]:= 2.5;
a3[i+j]:= a9[i,j];
a10[x>0, sgn(x), '!' , abs(k*5)]:= 0;
Задание массива константой
Для того чтобы не вводить массивы вручную во время отладки
программы (особенно если они имеют большую размерность), можно
пользоваться не только файлами. Существует и более простой
способ, когда входные данные задаются прямо в тексте программы
при помощи типизированных констант.
Если массив линейный (вектор) или как мы его называли ранее
одномерный, то начальные значения для компонент этого вектора
задаются через запятую, а сам вектор заключается в круглые скобки.
Многомерный массив также можно рассматривать как линей-
ный, предполагая, что его компонентами служат другие массивы.
Таким образом, для системы вложенных векторов действует то же
правило задания типизированной константы: каждый вектор ограничивается снаружи круглыми скобками.
Исключение составляют только массивы, компонентами кото-
рых являются величины типа char. Такие массивы можно задавать
проще: строкой символов.
Примеры задания массивов типизированными константами:
type mass = array[1..3,1..2] of byte;
const a: array[-1..1] of byte = (0,0,0); {линейный}
b: mass = ((1,2),(3,4),(5,6)); {двумерный}
s: array[0..9] of char = '0123456789';
Замечание: Невозможно задать неименованную или нетипизи-
рованную константу, относящуюся к типу данных array.
Тема 9. Строки. Строковые процедуры.
Тип string (строка) не входит в стандартный язык Паскаля, но он
прочно вошел во все известные компиляторы с этого языка. Причин,
по которым он был добавлен в язык, несколько. Для строк
(последовательностей символов) этой операции явно не достаточно.
Кроме того, в отличие от произвольных массивов, можно выделить
несколько общих операций над массивами символов, которые часто
42

применяются при решении совершенно различных задач. Эти
операции были оформлены в виде стандартных процедур и функций.
Если говорить о том, какую именно информацию удобно хранить в
переменных строкового типа, то в первую очередь следует упомянуть
последовательности символов, обозначающие имена собственные,
например, фамилии людей или географические названия. Именно для
подобных данных над строками были введены операции сравнения.
Кроме того, одно слово любого текста (последовательность символов,
окруженная разделителями) также удобно анализировать в пере-
менной строкового типа. В строке можно хранить и содержимое
одной строки большого текста. Сам же текст целиком удобнее
хранить в файле, массиве символов или массиве строк.
Итак, строка – это последовательность символов (литер),
заключенная в одиночные апострофы.
Значениями данного типа в Паскале являются различные
последовательности символов длиной от 0 до 255 символов. При
описании строковой переменной в квадратных скобках может быть
указан ее максимальный размер, не превосходящий 255. Если такой
размер опущен, то считается, что длина строки может достигать 255
символов. Указание размера строки влияет только на распределение
памяти для хранения соответствующих переменных. Все переменные
строковых типов совместимы между собой при выполнении различных операций над строками.
В разделе var строки описываются следующим образом:
type <имя типа> = string[<max длина строки>];
var <имя_строки>: <имя типа>;
или
var <имя_строки>: string[[<длина>]]
Если <длина> не указана, то считается, что в строке 255
символов. Поэтому для экономии памяти следует по возможности
точно указывать длину используемых строк.
Примеры описаний:
var s1: string[10]; (*строка длиной 10 символов*)
s2: string; (*строка длиной 255 символов*)
43

Необходимо отметить, что один символ и строка длиной в один
символ
var c: char;
s: string[1];
совершенно не эквивалентны друг другу. Вне зависимости от
своей реальной длины, строка относится к конструируемым структурированным типам данных, а не к базовым порядковым.
При определении строкового типа данных после слова string
указывается максимальное число символов, которое будет иметь
значение переменной этого типа. Например:
type bigstring[80];
var s: bigstring;
Здесь s – переменная строкового типа с максимальной длиной
строки 80 символов. Если в программе определить число символов
больше, чем n для переменной типа string[n], лишние символы
потеряются.
type abc=string[20];
var st1: abc;
st2, st3: string[8];
st2:= ' ' – пустая строка. st2:= '123' –длина строки равна 3.
Неименованные константы
В тексте программы на языке Pascal последовательность любых
символов, заключенная в апострофы, воспринимается как символ или
строка. Например:
c:='z'; {c: char}
s:='abc'; {s: string}
Константе автоматически присваивается "минимальный" тип
данных, достаточный для ее представления: char или string[k].
Поэтому попытка написать
c:='zzz'; {c: char}
вызовет ошибку уже на этапе компиляции.
44

Кроме того, не забывайте, что если константа длиннее той
а. Дело в том, что для хранения любой строки
переменной-строки, куда ваша программа пытается ее записать, то в
момент присваивания произойдет усечение ее до нужной длины.
Пустая строка задается двумя последовательными апостро-
фами:
s:=' ';
Если же необходимо сделать так, чтобы среди символов строки
содержался и сам апостроф, его нужно удвоить:
s:='Don''t worry about the apostrophe!';
Если теперь вывести на экран эту строку, то получится сле-
дующее:
Don''t worry about the apostrophe!
Нетипизированные константы
Все правила задания символов и строк как неименованных
констант остаются в силе и при задании именованных нетипизированных констант в специальном разделе const. Например:
const c3 = ''''; {это один символ - апостроф!}
s3 = 'This is a string';
Типизированные константы
Типизированная константа, которая будет иметь тип char или
string, задается в разделе const следующим образом:
const c4: char = ''''; {это один символ - апостроф!}
s4: string[20] = 'This is a string';
Действия с символами
Строку почти всегда можно рассматривать как массив символов,
то есть обращаться из программы к отдельным символам строки:
s1[1], s2[1], txt
[1][10] (в последнем случае имеется в виду десятый
символ первой строки). Нумерация символов в строке всегда
начинается с 1. Однако присваивание отдельным элементам строки
конкретных символьных значений может не привести к желаемому
результату. Чтобы понять, почему это иногда происходит, необходимо рассмотреть принципы организации строковых переменных в
памяти компьютер
отводится ровно на 1 байт больше, чем указано при ее описании (256
45

байт для строк, размерность которых не указана явно). Причем этот
Содержимое памяти, выделенной
строковой переменной s
var s:
string[6];
s[0]
s[
1] s[2] s[3] s[4] s[5]
s[6]
s:=‘ ‘;
0
‘ ‘
s:=‘Yes’;
3 Y e s
‘Yes’
s[4]:=‘!’;
3 Y e s !
‘Yes’
s:=s+’No’;
5 Y e s N o
‘YesNo’
s[4]:=‘!’;
5 Y e s ! o
‘Yes!o’
вспомогательный байт располагается в самом начале строки,
фактически это ее нулевой байт. В нем хранится текущая реальная
длина строки. Собственно говоря, такой механизм и накладывает
максимальные ограничения на возможную длину строк в языке
Паскаль, так как максимальное число, представимое в одном байте,
равно 255. Значение этого байта автоматически изменяется про-
граммой при выполнении стандартных операций над строками:
считывании, присваивании строковой переменной строкового выражения, обращении к стандартным процедурам и функциям, рабо-
тающим со строковыми выражениями. Рассмотрим на примере, как
меняется содержимое памяти и реальное значение строки при
выполнении тех или иных операций:
Операция
Значение s
На этом примере можно понять, что операция присваивания
значения элементу строки, индекс которого превосходит текущую
длину строки, не является корректной и фактически не оказывает
влияния на результат. Поэтому применения подобных конструкций
при программировании следует избегать, стараясь обходить
стандартными операциями над строками. Рассмотрим их подробнее.
В отличие от массивов, над строковыми переменными опреде-
лены операции считывания и печати. К строкам применима операция
сложения. При сложении двух строк концу первой из них приписывается вторая (по-другому эту операцию называют конкатенацией
строк).
st2:=’a’ + ‘123’ + ‘b’; → st2:=’a123b’;
Над строками между собой производится согласно так
называемому лексикографическому порядку. Строка s1 считается
меньше строки s2, если существует такая позиция k, что s1[1..k-1] =
s2[1..k-1] и s1[k]<s2[k] или такой позиции не существует, но строка s1
46

короче строки s2. При операциях сравнения идет сравнение строк,
начиная с левого края до первого несовпадающего символа.
Например:
‘a123b’ <= ‘a’
‘Дом’ = ‘Дом’
‘Дом’ > ‘дом’
Пример. Покажем переменные, выражающие результат от
строки ‘институт’.
a: string[4]; a:=’институт’ ⇒ a:=’инст’;
b: string[8]; b:=’институт’ ⇒ b:=’институт’;
с: string[15]; с:=’институт’ ⇒ с:=’институт…’;
В программе можно обратиться также и к определенному
символу строки:
b:=’институт’; b[3]:=’с’;
Строковые процедуры
Delete(st,poz,n) – удаление из строки st n символов, начиная с
позиции poz.
delete(’институт’, 3, 4) ⇒ ’инут’;
st2:=’королева’;
delete(st2, 5, 2) ⇒ st2:=’корова’;
Insert(st1,st2,poz) – вставка строки st1 в строку st2, начиная с
позиции poz.
insert(‘ле’, ‘корова’, 5) ⇒ ’королева’
str(a,st) – преобразовывает число или переменную типа integer,
byte, real в строку и помещает результат в переменную st.
str(178, c) ⇒ c=’178’;
str(x,c) ⇒ c=’-123.79’ при
val(‘17425’,x,cod) – преобразовывает переменную st строкового
типа в переменную типа integer, byte, real.
Val(‘17425’, x, cod) x=17425 cod=0
47
x=-123.79

Если преобразование не может быть выполнено, то в переменную cod записывается номер символа строки, который является
причиной неудачи преобразования. Если преобразование выполнено
успешно, то значение cod=0.
val(‘174а5’, x, cod) - ошибка cod=4
Строковые функции
1. Copy(st,poz,n) – из строки st выделяется n символов, начиная
с позиции poz.
copy(‘класс’, 3, 2) ⇒ ‘ac’ - результат
2. Concat(st1,st2,…,stN) – дает новую строку, состоящую с st1
до stN строк, соединенных («сцепленных») в одну, для выполнения
той же функции можно использовать знак «+».
а:=concat(st1, st2, st3);
3. Length(st) – длина строки st.
4. Pos(st1,st2) – обнаруживает первое появление в st2 под-
строки st1.
st2:=’abcde’;
Pos(‘z’. st2) = 0; Pos(‘bc’, st2)=2;
Pos(‘ce’, st2) = 0; Pos(‘cde’, st2)=4;
5. UpCase(Ch) – преобразовывает строчную латинскую букву в
прописную.
UpCase(‘а’)= ‘A’
Тема 10. Процедуры и функции
Подпрограммы
При описании алгоритмов решения реальных задач часто
возникает необходимость многократного выполнения какой-либо
части действий, повторяющейся в разных местах процесса решения.
Конечно можно каждый раз записывать в программе группу опера-
торов, выполняющих повторяющуюся часть, но это не рационально.
Удобнее сгруппировать эти действия в подпрограмму, описать их
один только раз и по мере необходимости обращаться к ней, изменяя
надлежащим образом входящие в нее исходные данные.
48

С другой стороны, сложную задачу программист разбивает на
некоторое число подзадач, используя метод последовательных
уточнений, определяя тем самым ряд отдельных подпрограмм,
составляющих часть основной программы.
Весьма поэтичное объяснение понятия подпрограмма дал В.Ф.
Очков: "Подпрограмма - это припев песни, который поют несколько
раз, а в текстах песен печатают только один раз".
С математической же точки зрения любая подструктура - это
замкнутая часть целого, которую можно рассматривать как самостоятельную структуру: подмножество является множеством, подгруппа - группой, подалгебра - алгеброй, подпространство - пространством и т.д.
Таким образом, подпрограмма - это в первую очередь про-
грамма. Со всеми полагающимися полноценной программе атрибутами: именем, разделами описания меток (label), констант (const),
типов (type), переменных (var) и даже со своими (вложенными)
функциями и процедурами.
В языке Pascal имеется два вида подпрограмм: процедуры и
функции. Описывая их общие черты, мы будем употреблять
обобщенный термин "подпрограмма". Если же в тексте встретятся
слова "процедура" или "функция", то это будет означать, что
излагаемая информация свойственна только одному конкретному
виду подпрограмм: либо только процедурам, либо только функциям.
Процедура – это программа, или, еще лучше «отдельный блок»,
в котором результат является не обязательно окончательно рассчитанным значением, в то время, как вычислении функции всегда
должно производиться до конца. Представим себе хотя бы стандартную функцию, такую как sqr(x). Результат этой функции всегда
вычисленное значение. Процедуру же в отдельных программах
можно, например, использовать для печати какого-либо текста.
Объявление и описание
Подпрограммы объявляются и описываются в начале Pascalпрограммы, до ключевого слова begin, означающего начало тела
программы.
Различия между процедурами и функциями начинаются уже с
момента их объявления.
49

Объявление функции
Функции объявляются следующим образом:
function<имя_функции>[(<список_параметров>)]:<тип_результата>;
В отличие от констант и переменных, объявление подпрограммы может быть оторвано от ее описания. В этом случае после
объявления нужно указать ключевое слово forward:
function<имя_функции>[(< параметры>)]:<тип_результата>;
Объявление процедуры
Процедуры следует объявлять так:
procedure <имя_процедуры> [(<список_параметров>)];
Если объявление процедуры оторвано от ее описания, нужно
поставить после него ключевое слово forward:
procedure <имя_процедуры> [(<список_параметров>)];
Описание подпрограммы
Описание подпрограммы должно идти после ее объявления. Оно
осуществляется по следующей схеме (единой для процедур и
функций):
[ uses <имена_подключаемых_модулей>;]
[ label <список_меток>;]
[ const <имя_константы> = <значение_константы>;]
[ type <имя_типа> = <определение_типа>;]
[ var <имя_переменной> : <тип_переменной>;]
[ procedure <имя_процедуры> <описание_процедуры>]
[ function <имя_функции> <описание_функции>;]
begin {начало тела подпрограммы}
<операторы>
end; (* конец тела подпрограммы *)
Если объявление подпрограммы было оторвано от ее описания,
то описание начинается дополнительной строкой с указанием только
имени подпрограммы:
function <имя_подпрограммы>;
или
procedure <имя_подпрограммы>;
50
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
