Учебное пособие-конспект по языку Pascal - Часть 1

Алексей Владимирович Горшков,
старший преподаватель каф. технологии приборостроения ЮУрГУ

УЧЕБНОЕ ПОСОБИЕ-КОНСПЕКТ ПО КУРСУ
ПРОГРАММИРОВАНИЕ НА ЯЗЫКАХ СЕМЕЙСТВА PASCAL

ВВЕДЕНИЕ В УЧЕБНОЕ ПОСОБИЕ
С большой благодарностью
моему учителю вычислительной
математики и программирования –
преподавателю (ныне профессору) Демченко.

Курс построен на основе опыта программирования в 1984–2005  гг. на разнообразных языках: Фортран-4, Фортран-77, Бэйсик-П, PL, Турбо-Паскаль, С, Object-Паскаль и др. и опыта преподавания программирования на языке Паскаль школьникам 6–11 кл. в МГП "Физтех-Колледж" при Московском физико-техническом институте в 1995–1998 гг. Для современного студента или старшеклассника представляется вполне возможным изучить и освоить его практически за 4 недели (за исключением одного скромного параграфа – об азбуке вычислительной математики. Потому что математике, в т.ч. вычислительной, нужно учиться  далеко не один год).
Примечание 1: это лишь краткая "шпаргалка" с основными, наиболее часто используемыми сведениями, желательными программисту – математику, физику, экономисту, связисту и т.п. Полное описание языка – см. в списке литературы толстые учебники и многотомные официальные описания.
Примечание 2: это конспект в основном по ЯЗЫКУ Паскаль, а не по процедурам и функциям модулей Турбо- (версии 5), Борланд- (версии 6..7) или Object-Паскаля (Delphi). Иначе объем этого конспекта стал бы слишком велик. Для ознакомления с неуказанными функциями модулей – смотрите свои записи лекций, образцы программ (приложение к этому учебному пособию)  или встроенные в Вашу среду программирования на версиях Паскаля подсказки-help'ы (на английском).
Примечание 3: структура нашего курса сильно отличается от обычной в учебниках по языкам программирования. Опыт преподавания показал преимущества такой (нашей) структуры. А именно, наш курс построен по педагогическому принципу цикличности академика В.Г. Разумовского, т.е. при рассмотрении многих тем  мы  сначала обходимся лишь необходимым минимумом знаний по теме, стараясь как можно быстрее сформировать круг начальных понятий, умений и навыков их применения, а если тема ими не исчерпывается, то через некоторое время мы возвращаемся к этой же теме, изучая её шире и глубже. Последовательность самих тем построена по общеизвестному приницпу "от простого в освоении и притом необходимого к сложному в освоении".
Примечание 4: в этом тексте есть примеры программ и их важных частей. Учащимся выдаётся также пакет файлов с авторскими учебными программами на языке Паскаль.

1-е издание 1-й части – Copyright (С) А.В. Горшков и МГП "Физтех-Колледж", 1996.
2-е издание 1-й части, переработанное и дополненное – Copyright (С) А.В. Горшков, 2011.
Части 2-я, 3-я , 4-я – Copyright (С) А.В. Горшков, 2011.

РЕКОМЕНДУЕМАЯ ЛИТЕРАТУРА:
1. Абрамов В.Г., Трифонов Н.П., Трифонова Г.Н.  Введение в язык Паскаль. –  М.:Наука, 1988. – 320  с.
2. Процедуры и функции турбо-Паскаля. – М.: ИВК-Софт, 1991. – 77 с.
3. Фаронов В.В. Основы турбо-Паскаля. – М.: МВТУ-ФестоДидактик, 1992. –
4. Borland Pascal with Objects 7.0. Руководство по языку программирования. – Borland International, 1993. – 393 с.
5. Фаронов В.В. Delphi 3. – М:Нолидж, 1998. – 400 с.

ЧАСТЬ   1. Азбука языка Паскаль.  Линейное,  процедурное и структурное программирование.

" М А М А   М Ы Л А   Р А М У .
                М А Ш А   Е Л А   К А Ш У   ."
(Букварь)
Тема 1. ОБЩИЕ СВЕДЕНИЯ.

ПРО АЛГОРИТМЫ
Алгоритм – понятное для исполнителя  предписание деятельности, состоящей из отдельных действий (шагов), пригодное для решения некоторой группы сходных задач ("алгоритмической проблемы"), содержащее действия по принятию исходных данных и извлечению результата.
Нормальный алгоритм – детерминированный (однозначно определённый) на каждом шаге, конечный по длине, потенциально завершаемый алгоритм.
Правильный алгоритм – приводящий для каждого правильного данного к правильному результату, потенциально завершаемый алгоритм.
Примечание: математикам известны разные сочетания "нормальности" и "правильности" алгоритмов. Существуют "алгоритмически неразрешимые" (т.е. для которых доказано, что для них не существует нормального алгоритма) задачи.
Циклы алгоритма – участки алгоритма, содержащие возвраты только такие, что алгоритм обладает потенциальной завершаемостью.
"Зацикленный" алгоритм – алгоритм, не обладающий потенциальной завершаемостью.
"Зависающий" алгоритм – алгоритм, обладающий зацикленностью или возможностью самопроизвольного останова ранее достижения выхода из него.

ПРО ПРОГРАММЫ ВООБЩЕ
Программа – запись алгоритма и начальных данных (если они есть) на одном из языков.
Команда – непосредственное указание исполнителю очередного элемента действия.
Процессор (обработчик) – исполнитель команд, преобразователь исходных данных в результат.
Оператор языка программирования – законченная фраза языка программирования, определяющая действие (очередной этап обработки данных). Оператор может состоять из операндов, аргументов и результатов.
Операнд – составная часть оператора, отдельное слово языка программирования.
Аргумент – составная часть данных оператора.
Проблемно-ориентированный код – запись цели, задачи, критерия достижения цели на одном из языков программирования.
Алгоритмический код – запись пути достижения цели от исходных данных до критерия (условия) окончания (выхода) и извлечения результата.
Машинно-ориентированный код – запись блоков команд процессора (возможно, ещё без исходных данных и без связей между блоками).
Исполняемый (загружаемый) машинный код – машинно-ориентированный взаимосвязанный код, снабжённый исходными данными (если они есть).

ОСНОВНЫЕ РАЗНОВИДНОСТИ ПРОГРАММ
1. Системные = необходимые или полезные для нормальной работы устройства и программ на нём
• загрузчики операционной системы (ОС) = ищет, проверяет и загружает  ОС, передаёт ей управление
• операционная система (ОС) = обрабатывает команды и управляет другими программами
; искатель устройств и программ
; загрузчик программ
; обработчик команд и прерываний
; диспетчер и оптимизатор оперативной памяти
; диспетчер и оптимизатор множества задач
• драйверы ("водители") = посредники между ОС и устройствами,  в т.ч. средства связи низких уровней
• операционная оболочка = посредник между ОС и человеком
• служебные = проверяют, настраивают и оптимизируют доступные ресурсы (устройства, память и др.)
; проверяльщики
; форматировщики
; утилиты ОС
; упаковщики (сжиматели, архиваторы)
; антивирусы
; настройщики параметров
; автоматические оптимизаторы параметров
; дефрагментаторы
; средства связи промежуточных уровней
; и др.
2. Инструментальные = средства создания других программ
• редакторы программ
• трансляторы
• редакторы связей
• загрузчики
• отладчики
3. Прикладные = нужные пользователю
• средства связи высоких уровней
• текстовые, графические, музыкальные редакторы = создают упорядоченные данные
• системы управления базами данных (СУБД вообще, электронные таблицы и гипертекст в частности) = создают упорядоченные данные со связями между ними
• системы управления базами знаний (СУБЗ) = СУБД с определёнными отношениями в связях и средствами интерфейса с человеком, средствами прямой или обратной связи
• экспертные системы (ЭС) = СУБЗ со средствами поиска знаний в базе, анализа и оценивания знаний, выведения следствий, отбора знаний (в т.ч. следствий) по заданному множеству критериев
• системы искусственного интеллекта (СИИ) = ЭС со средствами принятия решений (отбора, оценивания и свёртывания следствий в критерий приближения к некоторой цели их деятельности,  одно определённое следствие)
• автоматические системы управления (АСУ) = СИИ со средствами командования исполнителями
• узкоспециализированные вычислительные системы
• узкоспециализированные аналитические системы
• узкоспециализированные средства защиты информации
• узкоспециализированные игровые программы
• узкоспециализированные обучающие программы
• узкоспециализированные средства автоматического перевода с языка на язык
• узкоспециализированные средства управления производством
• узкоспециализированные медицинские, финансовые, военные, эвристические программы
• и т.д., и т.п., и др.

НЕМНОГО ФИЛОСОФИИ (ЛИРИЧЕСКОЕ ОТСТУПЛЕНИЕ)
• {Система = множество составляющих (элементов и их связей), где каждая составляющая необходима, а вместе взятые достаточны для её существования. Примеры систем: пустое множество;  множество всех множеств; Вселенная; триады философских категорий (вида "тезис+синтез+антитезис"), взятые по отдельности от других триад философских категорий; живое существо с ресурсами, необходимыми для его жизни; арифметика; геометрия; алгебра; теория множеств; теория групп; основания математики;  государство с народом и ресурсами, необходимыми для их жизни; физическая теория с её разумным носителем и ресурсами для его нормальной жизнедеятельности; и т.д., и т.п., и др.}
• {Одной из триад является "длительность+событие+прекращение". Длительность длительности есть событие длительности, прекращение прекращения есть событие длительности, прекращение длительности или же длительность прекращения есть событие прекращения (однократное или повторящееся). В другой из триад пространство относится к категории "длительности", а время относится к категории "прекращения" так же, как возможность события движения относится к категории "событие".}
• {Материя = то во Вселенной, для чего существуют законы сохранения. Материю условно делят на вещество и поле. Во Вселенной существует и нематериальное, например: отношение, число, информация, противоречие и другие математические понятия; любовь, нравственность и другие гуманитарные понятия; и т.д., и т.п., и др. Материальное и нематериальное образуют систему – Вселенную.}
• Живые системы (ЖС) = программы с методами поддержания своей деятельности и, возможно, размножения и изменения, в подходящей среде, снабжённые средствами осуществления этих методов.
• {Живое вещество (ЖВ) = ЖС в преимущественно вещественной форме. Например, вирусы живых существ.}
• {Живое поле = ЖС в преимущественно полевой форме.}
• Живые интеллектуальные системы (ЖИС) = живые АСУ, снабжённые методами и средствами ещё и адаптивного изменения (развития) в подходящей  (даже изменчивой) среде.
• Разумные системы (РС) = ЖИС, снабжённые методами и средствами саморазвития (обратными адаптирующими связями), "способные из хаоса сделать космос".
• {Надсистемы = системы, состоящие из систем.}
• {Живое существо = ЖВ или система из ЖВ, снабжённые частью среды жизни (внутренними ресурсами). Например, риккетсия, бактерия, растение, животное.}
• Социальные живые системы (СЖС) = живые системы, состоящие из живых систем. (Например, все многоклеточные живые существа,  в т.ч. человек;  многие человеческие общества.)
• Разумные социальные живые системы (РСЖС) = разумные СЖС, или, что то же, социальные РС.
• Нравственные (рефлексивные) системы (НС) = системы, снабжённые, в своём составе, критерием своей деятельности (системой своих ценностей); например, к НС относятся даже все системы искусственного интеллекта (см. выше); однако "нравственность" у них обычно очень непохожа на нашу.
• {Можно придумать много сочетаний признаков "живая", "разумная", "социальная", "нравственная", обойдёмся, для примера, лишь двумя:}
• нравственная разумная система = нравственная РС или, то же самое, разумная НС; примером таковой является взятый отдельно человек (но, к сожалению, не каждый);
• нравственные социальные разумные живые системы = нравственные РСЖС или, что то же, разумные нравственные СЖС;  примером таковой является человеческое общество.
• Данная классификация ничего не говорит о том, являются ли диалектические противоречия, движущие развитием какой-либо системы, неантагонистическими либо антагонистическими (даже антагонистические общества обычно относятся к НСРЖС). Факт существования какой-либо НСРЖС ещё ничего не говорит о том, будет ли она существовать в следующее мгновение времени и если да, то как она будет устроена. Предпочтительнее, как это следует  из критерия Б.Рассела "что такое лучше/хуже", солидарные НСРЖС (с внутренне непротиворечивой подсистемой ценностей).
• Высоконравственной обычно называют НС, чья система ценностей оценивается субъектом (т.е. с конкретной субъектвной точки зрения, по его критериям) оценивания выше собственной.

Упражнения (без офиициального ответа):
1) К какому типу программ относится система интернет-ресурсов (гиперсреда, наполненная содержанием) ?
2) К какому типу программ относятся компьютерные вирусы?

ПРО ИНСТРУМЕНТАЛЬНЫЕ СРЕДСТВА
Редактор программы – программа для написания программ на том или ином языке.
Транслятор (translator, переводчик) – программа, которая преобразует программу, написанную на одном языке, в программу, написанную на другом языке.
Компилятор (compiler, собиратель, составитель) – транслятор с языка высокого уровня (например, проблемно-ориентированного, алгоритмического или универсального) в машинно-ориентированный код.
Интерпретатор (interpreter, толкователь) –  транслятор, который делает построчно анализ и проверку, трансляцию и одновременно выполнение программы  без компиляции.
Редактор связей ( link editor ) – объединяет несколько независимо скомпилированных машинно-ориентированных модулей в один и устанавливает внутренние связи между ними и исходными данными (если они есть), образует исполяемый машинный код.
Загрузчик (loader) – загружает исполняемый код в память и передаёт ему право на исполнение.
Отладчик (debugger) – управляеет исполнением программы, позволяет проверять и задавать значения переменных, прерывать исполнение программы.

ПРО УСТРОЙСТВА
ПЗУ (ROM) – постоянное запоминающее устройство; информацию из него можно только читать (Read Only Memory).
ЦП (CPU) – Центральный Процессор (Central Processor Unit).
Регистры процессора – ячейки памяти процессора для ввода аргументов и вывода результатов элементов действий.
ОЗУ – оперативное запоминающее устройство (быстродействующая память за пределами регисторов процессора).
Очередь (FIFO) – запоминающее устройство с последовательной обработкой типа "кто первый вошёл, тот первый вышел" (First Input First Output).
Магазин (стек, FILO) – запоминающее устройство с последовательной обработкой типа "кто первый вошёл, тот последний вышел" (First Input First Output).
ППД (RAM) – память произвольного доступа, запоминающее устройство с произвольной выборкой (Random Access Memory).
Векторный регистр – устройство с параллельной обработкой.
Конвейер – устройство для обработки последовательности однотипных данных одинаковым алгоритмом с совмещением во времени.
Долговременная память – запоминающее устройство, не требующее постоянного питания.
Виртуальная память – часть оперативной памяти (ОЗУ), временно используемая вместо долговременной.
Буферная память – разные запоминающие устройства, промежуточные между основными видами памяти (регистрами процессора, оперативной и долговременной), а также внешними устройствами.
Сверхоперативная память (Memory Cache) – разновидность буферной памяти, промежуточная между основными регистрами процессора и ОЗУ (обычно некоторые дополнительные регистры ЦП).

ЕДИНИЦЫ ИЗМЕРЕНИЯ КОЛИЧЕСТВА ИНФОРМАЦИИ
Историки предполагают, что основы двоичной системы счисления были известны ещё древним египтянам и китайцам. Двоичная логика была создана ещё Аристотелем. Однако двоичную арифметику достаточно разработал лишь Лейбниц. Двоичная система оказалась удобна для реализации на механических, релейных (логическая релейная машина Щукарёва, неосуществлённый проект универсальной релейной вычислительной машины Торреса-и-Кеведо, осуществлённая релейная вычислительная машина Цузе), электронно-ламповых триггерных (триггер изобрёл советский инженер Бонч-Бруевич, первые недостроенные электронно-ламповые машины – Лебедева 1939–1941, Атанасова и Берри 1940–1942, первая в мире полностью построенная британская "Колоссус" 1943), транзисторных триггерных (полупроводниковый усилитель с 2-мя p-n переходами "кристодин" изобрёл советский инженер и учёный Лосев в 1922 г., через два десятка лет Бардин и компания усовершенствовали кристодин, уменьшив толщину его базы, и назвали это "транзистором") вычислительных машинах.
Единицей измерения количества информации является 1 двоичная позиция (бит – Binary digiT). Она определяет возможность нумерации до 2^1=2 вариантов. Более крупная единица: байт (8 бит, Bites EighT). Она определяет возможность нумерации до 2^8=256 вариантов. Обозначают биты и байты так: 1 B = 8 b. Ещё более крупные единицы: 1 kB = 1000 B , 1 KB = 210=1024 B. Есть стандартная шутка: "начинающий пользователь знает, что 1 кг = 1000 г, и думает, будто 1 Кбайт = 1000 байт. Опытный пользователь знает, что 1 кг = 1000 г, и что 1 Кбайт = 1024 байт. Программист-хакер-немножко-маньяк знает, что 1 Кбайт = 1024 байт, но думает, будто 1 кг = 1024 г". 1 МБ = 1020 (10242) Б. 1 ГБ = 1030 (10243) Б. 1 ТБ = 1040 (10244) Б.
В математике, кроме двоичной логики Аристотеля (истинно/ложно), известна и широко применяется на практике трёхзначная логика Диогена (истинно/неопределённо/ложно), многозначная логика Лукашевича и др. Советский учёный и инженер Брусенцов изобрёл троичную симметричную систему счисления, радикально избавленную от недостатков двоичной системы. Это на порядок упрощает конструкцию машины, в разы ускоряет операции вычитания и деления, на много порядков медленнее накапливается погрешность округления и в итоге приводит к большой точности результата сложных вычислений. Были выпущены несколько крупных серий троичных ЭВМ "Сетунь". Соответствующую единицу измерения количества информации называют "трит".

Тема 2. ВИДЫ И ЯЗЫКИ ПРОГРАММИРОВАНИЯ

ОСНОВНЫЕ ВИДЫ ПРОГРАММИРОВАНИЯ
Последовательное, или Линейное – начальный этап развития программирования, линейная запись команд (в т.ч. переходов). Есть лемма о возможности преобразования "путанки" команд к их "линейке".
Процедурное – появление составных команд, выделение часто повторяемых подпрограмм-процедур, подпрограмм-функций и их автоматически компонуемых библиотек.
Структурное – появление средств доказательства нормальности алгоритма и избежания зацикливания (циклы Ершова–Дейкстры, преобразования Янова–Бома–Джакопини) путём ограничения множества допустимых операторов.
Модульное (Канторовича) – средства сокрытия (независимости) почти всех составляющих внутреннего содержания сложных подпрограмм (внутренних данных и действий над ними) от связанных с ними иных подпрограмм и программы, кроме тех составляющих, которые явно объявлены как взаимодействующие со внешними.
Объектное (Ершова–Канторовича–Дейкстры) – объединение данных и обрабатывающих их действий в единое целое ("объект", "класс", алгебру).
Динамическое – распределение ресурсов (в т.ч. памяти для размещения данных или команд) в процессе исполнения программы, а не заранее.

РАЗНОВИДНОСТИ ЯЗЫКОВ ПРОГРАММИРОВАНИЯ ПО ОРИЕНТАЦИИ
Машинно-ориентированные языки программирования – строится последовательность конкретных команд, исполняемых конкретным процессором.
Алгоритмические (универсальные) языки программирования – строится конкретный путь для достижения цели (от получения исходных данных до извлечения результата), но не конкретизируя команды процессору.
Проблемно-ориентированные языки программирования – ставится конкретная цель, формулируется конкретная задача (в т.ч. критерий достижения этой цели), но не алгоритм и не команды.

РАЗНОВИДНОСТИ ЯЗЫКОВ ПРОГРАММИРОВАНИЯ ПО УРОВНЮ
"Низкоуровневые" языки программирования – машинные команды, автокоды, ассемблеры, машинно-ориентированные языки. Хороши они по сравнению с высокоуровневыми тем, что позволяют полнее использовать возможности конкретного процессора; плохи тем, что неудобны, трудоёмки, высока вероятность ошибки. Хотя некоторые почему-то считают их разновидностью проблемно-ориентированных – ориентированных на проблему полного использования возможностей процессора :-)
"Высокоуровневые" языки программирования – алгоритмические (универсальные) и проблемно-ориентированные.
"Сквозные" языки программирования – объединяющие в себе возможности от "низкоуровневых" до "высокоуровневых". Примеры "сквозных" языков: C, С++, С#, Эль-76, паскалеподобные языки Modula-2, Oberon, Turbo-Pascal, Borland-Pascal, Object-Pascal (Delphi) и др.

ОСНОВНЫЕ ПРИЁМЫ РАЗРАБОТКИ И ОФОРМЛЕНИЯ, СТИЛЬ ПРОГРАММИРОВАНИЯ
1. Исторически (со времён Ады Лавлейс) различают восходящее и нисходящее проектирование. При восходящем проектировании (от простого к сложному) начинают от операторов, группируют их в подпрограммы, модули, и, наконец, программу в целом. При нисходящем проектировании (от сложного к простому) начинают от общей схемы программы, специализации модулей, взаимосвязей подпрограмм, главной части программы, и, в конце концов, доходят до операторов. Практически применяют оба приёма проектирования. Для малых программ – обычно простое восходящее, для сверхбольших – разумнее использовать нисходящее.
2. Есть текстовое программирование (программист пишет текст программы), визуальное программирование ("кнопочно-формовое": программист сооружает принципиальную схему, за программиста часть текста пишет автоматика) и др.
3. Важно обеспечить читаемость программ. Это нужно и самому автору программы, и смежникам, и заказчику. Есть традиция подчинённые блоки операторов сдвигать вправо. Среды программирования предоставляют возможность автоматической раскраски текста программы в условные цвета. Короткие операторы, идущие подряд без переходов и условий, удобно размещать в одну строчку вместе. Длинные операторы или операторы с условиями, с переходами, удобнее размещать по одному в строке. Начало и конец блока операторов желательно делать на одном уровне. Примеры см. далее.
4. Важно обеспечить документирование текста (но не злоупотреблять этим). Пусть читатель (например, сам автор 20 лет спустя), прочитав сложный оператор, увидит рядом объясняющее его описание (примечание, комментарий).
5. Полезно давать постоянным, переменным, подпрограммам и т.д. разумные, достаточно понятные названия.
6. Есть традиция (со времён "дедушки Фортрана") имена переменных целого типа начинать с букв i,j,k,l,m,n .
7. Есть много и других приёмов программирования. Есть смысл показывать их не все сразу, а по мере приобретения учениками опыта.

Разные языки программирования предназначены для разных целей. Поэтому различны даже самые принципы их построения. Для примера рассмотрим два семейства языков, относящихся к одному и тому же типу (универсальные сквозные), причём равных по своей мощности (то есть на которых можно написать всё, что угодно), причём совместимые на уровне объектных модулей, библиотек и исполняемых модулей (если иметь в виду продукцию одной и той же фирмы Borland). На языках семейства С (С++, С# и др.) разрешено всё, кроме того, что запрещено явно. На языках семейства Паскаль (Pascal, Modula-2, Oberon, Delphi и др.) запрещено  всё, кроме того, что разрешено явно. Поэтому С-подобные языки очень любят те программисты, которые свято верят в свою непогрешимость, а также те, кому хочется писать программы относительно быстро (нажимать на клавиши на 30% меньше). А паскалеподобные языки очень любят те, кто не верит в непогрешимость кого бы то ни было (кроме теорем математики), кому требуется писать особо большие и при этом высоконадёжные программные комплексы (например, 10 млн. строк и ни одной ошибки, сделанной кем-либо из 1000 программистов). На тех же принципах, что Паскаль, построены и некоторые другие широко известные языки – Algol, Ada и др. Например, Ada несколько десятков лет был (и, возможно, остаётся) основным языком программирования в Пентагоне и подведомственных ему учреждениях. В СССР тоже были разработаны паскалеподобные языки и их трансляторы  специального назначения. Для сравнения, по имеющимся (непроверенным, но исходящим из авторитетного источника) сведениям, продукцию фирмы Майкрософт Пентагон использовать в своём ведомстве запрещает.

В подтверждение нашей позиции приведём ссылки на известных и авторитетных специалистов.
• "Главной проблемой при программировании сложных систем является обеспечение безошибочности. Нас не устроило бы, если в программном обеспечении системы управления РВСН содержалась хотя бы одна неустранённая ошибка на 10 миллионов операторов." (Профессор, д.т.н., лауреат разных премий Гликман, из лекции в НИИ тепловых процессов им. М.В. Келдыша, конец 80-х гг.)
• "...Рискну утверждать, что все, что можно создать на профессиональном языке программирования Си, можно (и при том в ряде случаев значительно проще) создать и на языке системы Турбо Паскаль." (В.В.Фаронов, [3].)
• "...Любое ограничение, с одной стороны, вводится для повышения надёжности программ, а с другой –уменьшает мощность языка, делает его менее пригодным для каких-то применений. В Турбо-Паскале немногочисленные исключения в отношении типов данных придают языку необходимую гибкость, но их использование требует от программиста дополнительных усилий и таким образом свидетельствует о вполне осознанном действии." (В.В.Фаронов, [3].)
• "...По статистике, в больших программных комплексах (например, система управления ПВО, математическое обеспечение крупного узла связи, банка и проч. т.п.) допускается порядка 1 ошибки на 10 тыс. строк; допустим, что при особо тщательной проверке и использовании систем программирования так называемого высокого уровня удастся снизить уровень ошибок до величины порядка 1 на 1 млн. строк. Но тогда в проектируемых программных комплексах ПРО объёмом порядка 100..1000 млн. строк ожидаемое количество ошибок будет порядка 100..1000, что представляется всё-таки непpиемлемо большой величиной." (Из книги "Космическое оружие: дилемма безопасности". Ред. Е.П.Велихов, Р.З.Сагдеев, А.А.Кокошин. 1986 г.)

Тема 3. СРЕДА ПРОГРАММИРОВАНИЯ НА ЯЗЫКЕ ПАСКАЛЬ
(редактор текста, компилятор, редактор связей, загрузчик  и отладчик) Turbo-Pascal, Borland Pascal и т.п.
Alt+Shift+Enter – развернуть окно среды программирования (под Windows) в полный экран (как в DOS).

F1 – получить подсказку по редактору. А если подвести курсор к любому слову и нажать Ctrl+F1, то если Редактор такое слово "знает", то появится подсказка с полным описанием, относящимся к нему, и даже с примером простейшей программы с его использованием.

Выделение блока текста:
Способ 1: мышкой.
Способ 2: Shift+стрелки.
Способ 3: Ctrl+K B   – начало (Begin) блока, Ctrl+K K   – конец (Конец) блока.
Копирование (Copy) выделенного блока: Ctrl+K C.
Перемещение (moVe) выделенного блока: Ctrl+K V.
Удаление (Delete, Ignore, "Y-даление") выделенного блока: Ctrl+K Y  (в старых версиях – Ctrl+K D   ).
Чтение (Read) выделенного блока из другого файла:            Ctrl+K R (как бы скопировать).
Запись (Write) выделенного блока в другой файл:                Ctrl+K W (как бы вставить).
Распечатка (Print) выделенного блока:                Ctrl+K P.
 
F10 – переход в меню.
Пункт меню FILE – создать новый, прочитать существующий,  переименовать и сохранить, просто сохранить, выход.
Пункт EDITOR – кроме вышеприведенных операций с блоками,  можно скопировать (Copy) блок в "карман", "буфер", "доску  вырезок" (ClipBoard). Или вырезать, "отсечь" (Cut) туда же.  Ее можно посмотреть (Show ClipBoard). Из нее можно вставить  блок (Paste или Insert).
F6  или Ctrl+F6 – если одновременно открыты несколько файлов,  то можно выбрать любой из них активным. То же самое есть внизу меню File  или Window (или Screen).
Пункт Search или Find – Поиск (Find) в тексте строки указанного Вами образца; Search Again – повторить поиск того же;  Replace – поиск строк одного образца и автоматическая замена  их на строки другого образца.
Пункт Compile – выбор назначения расположения exe-модуля Вашей  программы (Destinаtion – Memory or Disk) и собственно  компиляция (Compile).
Пункт Run (Запуск) – загрузка скомпилированной программы в  память машины на исполнение.
Alt+F5 – убрать/показать окно среды программирования
Пункт Options (Настройки):
   Options–Compiler–087/0287 – работать с арифметическим   сопроцессором либо имитировать его наличие. Рекомендуется указать наличие арифметического сопроцессора с использованием соответствующих типов данных {$N+} и эмуляцию (имитацию) его наличия в случае его отсутствия {$E+}.
   Options–Directories – указать каталоги, где, например, хранятся стандартные модули Borland Pascal и куда помещать результаты компиляции:
• EXE&TPU – куда будут помещаться *.exe и *.tpu  в результате компиляции.
• INCLUDE – откуда будут браться фрагменты текста, указанные директивой {$I ИмяФайла.pas}.
• UNIT    – откуда будут браться объявленные скомпилированные модули, т.е. файлы *.tpu.
• OBJ     – откуда будут браться объектные файлы *.obj , указанные директивой {$L ИмяФайла.obj}
   Options-Environment – настроить внешний вид и сервис редактора   по своему вкусу.
   Options-Save – сохранить настройки.
Пункт DEBUG – отладчик (начинающим рекомендуется его не трогать. Это будет в Теме 18).

Есть традиция подчинённые (внутренние) блоки программы писать правее подчиняющего (внешнего). Для отступа вправо удобна клавша Tab. Удобно, если конец блока находится на том же уровне (в  смысле, в том же столбце экрана), что и начало. Образцы см. далее.

Кроме F1 и Ctrl+F1, можно не только смотреть подсказки, но и копировать из них примеры: в выбранном примере нажали Alt+E  –  CopyExamples  –  Enter  –  Esc  –  вставить в нужное место вашей программы Shift+Ins.

Тема 4. ОСНОВНЫЕ ПОНЯТИЯ ЯЗЫКА PASCAL.

Мы будем различать стандарт языка Паскаль и некоторые из его реализаций (Turbo Pascal, Free Pascal, Borland Pascal, Modula-2, Oberon, Delphi Object Pascal и др.). Ориентироваться будем в основном на Turbo Pascal как наиболее доступный в нашей стране.

АЛФАВИТ языка ПАСКАЛЬ
  Цифры: 0,1,2,3,4,5,6,7,8,9.  В Турбо- и Борланд-Паскале (здесь и далее "ТБ-Паскаль") цифры есть и 16-ричные:
        0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f.
  Буквы: от A до Z  и  от a до z  – в ТБ-Паскале;  причем компилятору безразлично, заглавная буква или        строчная (примечание: в "каноническом" Паскале – от A до Z, т.е. только заглавные);  и еще символ подчеркивания _ ("Shift минус"). Буквы кириллицы в алфавит Pascal не входят.
  Знаки арифметических операций:  умножение *, деление /,   сложение +, вычитание - .
  Знаки операций сравнения (используются 1 или 2 символа): равенство (или соответствие) =, неравенство <>,
        меньше <, меньше или равно <=, больше >, больше  или равно >=.
  Разделители:  . , ; : ( ) [ ] { } ' ^  и еще символ "пробел" (код=32)   (их применение см. далее)  и другие "невидимые" символы управления с кодами от 0 до 31.
  Еще спецсимволы ТБ-Паскаля:   $ # @   (их применение см. далее).
  Пары символов:
       (выше см. >=, <=  ...)
       (*  и  *)  – почти то же, что и { и }
       (. и .) – то же, что и [ и ]
       .. – его применение см. далее
       :=  – его применение см. далее

 КОММЕНТАРИЙ (ПРИМЕЧАНИЕ) – заключённая в фигурные скобки любая последовательность символов, кроме закрывающей фигурной скобки. Если ее первый символ не $, то комментарий компилятором  игнорируется, т.е. Вам удобно снабжать примечаниями текст. Если приходится "закомментировать" кусок текста, уже содержащий комментарий, то можно воспользоваться парами символов (* и *), эквивалентными символам { и } соответственно.
 В Обжект-Паскале комментарием может служить и то, что стоит в строке после пары знаков // до конца строки.
Примеры:
       {Здесь комментарий}
       (* и здесь тоже *)
       (* и даже {вот здесь} *)
        // Комментарий Обжект-Паскаля
       {$I-} {: а вот это не комментарий, а директива (указание) компилятору}

ДИРЕКТИВЫ КОМПИЛЯТОРУ: например, {$I-} – отключить прерывание программы при ошибке ввода-вывода, {$I+} – включить его. {$R ИмяРесурса} – подключение ресурсов. Примеры использования директив и другие директивы (подключение сопроцессоров, условная компиляция и др.) будут рассмотрены позже.

СЛУЖЕБНЫЕ СЛОВА  ( их значение см. далее; в иных значениях их применять нельзя !):
       and  array  begin  case  const  div  do  downto  else  end  for  function  goto  if  in  label  mod  nil  not  of  or  packed  procedure  program  record  repeat  set  then  to   type  until  var  while  with.
В Борланд-Паскале есть ещё дополнительные служебные слова ... :    asm  constructor  destructor  exports  file  implementation   inherited  inline  interface  library  object  shl  shr string  unit  uses  xor
...  и стандартные директивы:   absolute  assembler  export  external  far  forward  index  interrupt  name  near  private  public  resident  virtual  (... но при описании объектов слова private и public  относятся к служебным.)
Все служебные слова и стандартные директивы следует запомнить, чтобы не давать имена, совпадающие с ними.

ИМЕНА (идентификаторы) – введённые программистом слова,  используемые для именования (т.е. отличения от других) констант, типов, переменных, полей в записях, процедур, функций, модулей, программ и др. объектов. Не должны совпадать со служебными словами. Длина имени <= 63 символов. В имени – только буквы и цифры Паскаля (см. выше) (в т.ч. символ подчеркивания) без пробелов. Начинаться может только с буквы или подчеркивания, но не с цифры.

ЧИСЛА:
целые;
        Примеры: 1   -5   367
действительные;
        Примеры:  2.0   -5.786   6.8E+5   6.66E-12  -5.4E1
Начиная с Т-Паскаль (Б-Паскаль, О-Паскаль) еще и 16-ричные байты (беззнаковые целые числа)
        Примеры:  $07   $bf   $c7

ЗНАКИ (СИМВОЛЫ, ЛИТЕРЫ):
Знаки оформляются с обеих сторон апострофами ("одиночными кавычками"). Примеры знаков:
        'A'   '6'   'S'   'Ы'  '"'  ' '  '='  '?'        . Если надо записать сам апостроф, то его надо повторить дважды: ''''.
Другой способ: в Б-Паскаль если стоит #, то далее идет десятичный номер (код) этого символа, например:
        #81 – то же, что символ байта $51 (буква 'Q')
        #13 – то же, что Enter     (символ байта $0d)
        #27 – то же, что Esc       (             $1b)
        #32 – то же, что ' ', т.е. пробел.   (   $20)
        #07 – пищание            ("псевдосимвол" $07)
В Т-, Б- и О-Паскале есть СТРОКИ (упорядоченные наборы символов). Строка целиком берётся в апострофы. Подробнее о строках см. далее, в теме о составных типах данных. Примеры (все 3 строки получатся одинаковые !):
        'Мама мыла раму'
        'Мама'+' мыла ра'+'му'
        'Ма'+'ма'#32'мыла'#32'раму'

ЛОГИЧЕСКИЕ ЗНАЧЕНИЯ
true – истинно
false – ложно
К сожалению, в Паскале, как и в Си, нет значений трёхзначной (Диогеновой) логики (включающей значение "неопределённо"), а есть только двузначная (Аристотелева).

УКАЗАТЕЛИ (они же АДРЕСНЫЕ ВЕЛИЧИНЫ, они же ССЫЛКИ)
Их значением является адрес ячейки в памяти ЭВМ, с которой начинается хранение соответствующей переменной. В Б-Pascal предусмотрено несколько разновидностей указателей. Обычно в качестве указателей применяются двухбайтовые и четырёхбайтовые слова. О них см. в Теме 22.

ОПЕРАТОР – "законченная фраза языка, определяющая некоторый этап обработки данных".
Операторы Паскаля см. далее (Тема 6).

{Наша первая программа на Паскале}
Begin                {начало главной части}
  write('Мама мыла раму. ');  {строка напишется, курсор не переведётся, потому что оператор write }
  writeln('Маша ела кашу.');  {строка напишется, курсор переведётся, потому что оператор writeln}
  readln;                {Здесь программа будет ждать, пока не нажмёте Enter}
end.                {конец всей программы}

Тема 5. СТРУКТУРА ПРОГРАММЫ на Паскале.

ОБЩАЯ СТРУКТУРА ПРОГРАММЫ
Принцип построения программы на "каноническом" Паскале состоит в том, что любой объект, появляющийся в программе, должен быть либо элементом языка Паскаль, либо объявлен (введён в употребление с описанием правил использования) хотя бы на строчку раньше.
1. Заголовок.
2. Раздел объявления модулей {в ТБ-Паскале}.
3. Раздел объявления меток.
4. Раздел объявления констант.
5. Раздел описания типов.
6. Раздел объявления переменных.
7. Раздел процедур и функций.
8. Раздел экспортирования.
9. Раздел операторов.
Разъяснять каждое слово будем в ином порядке.
ЗАГОЛОВОК  – начинается со слова program (либо unit), содержит имя программы (либо, соответственно, модуля, см. далее), у него возможны параметры (о них см. в следующих частях конспекта).
КОНСТАНТА (постоянная) – идентификатор, обозначающий объект с неизменяемым  значением. Её значение располагается после знака равенства.  Пример: const e=2.73;
В Б-Паскале в разделе констант можно описать еще и "переменные с НАЧАЛЬНЫМ значением", т.е. переменную (а не постоянную), у которой при компиляции появляется начальное значение. После двоеточия указан тип переменной (см. далее). Пример: const klass: integer=8; (Конечно, удобнее было бы, если разработчики языка придумали бы что-нибудь легче запоминающееся, например, var  klass: integer=8; но сделали они всё же const.) Подробнее о переменных с начальным значением см. в Теме 14.
ПЕРЕМЕННАЯ (var) – идентификатор, обозначающий объект со значением,  могущим изменяться в ходе выполнения программы.  Тип переменной указывается после двоеточия.
МЕТКА (label) – "идентификатор строки программы". Целое число от 0 до 9999. Используется вместе с оператором goto (см. далее).
ТИП (type) – ограничивает множество значений, которые может принимать  данная описываемая переменная, и виды операций, которые можно производить над этой переменной. Список типов см. далее.  Можно конструировать оригинальные, "нестандартные", типы на основе стандартных.
О разделе ЭКСПОРТА расскажем значительно позже. В нём  перечисляются используемые процедуры и функции, описанные вне данной программы или динамической библиотеки.

Что такое ОПЕРАТОР вообще, Вы уже представляете. Примеры у нас   еще впереди. Операторы программы могут представлять собой:
    а) стандартные операторы языка Паскаль;
    б) вызовы процедур (см. далее) из внешних модулей (см. далее);
    в) вызовы процедур из раздела "процедур и функций" программы.
     У оператора может быть в круглых скобках список фактических   значений параметров, необходимых для работы данного оператора   (или процедуры).
     Отдельные операторы разделяются знаком ; (точка с запятой).
СОСТАВНОЙ ОПЕРАТОР – последовательность 2-х или более операторов,  заключенных в "алгоритмические скобки" begin  и  end; она представляется компилятору как "единый большой оператор". В конце главной части программы  – РАЗДЕЛА ОПЕРАТОРОВ, т.е. в конце всей программы (терминаторе), после слова end ставится не точка с запятой, а точка.
ВЛОЖЕННЫЙ ОПЕРАТОР – внутри одного оператора действует другой оператор. Например, вложенные циклы, вложенные условные операторы и др.
Примеры программ см. первая – выше, остальные – ниже.

:=  – оператор ПРИСВАИВАНИЯ. Переменной, стоящей слева,  присваивается значение, равное правой части. Подробнее об операторе присваивания см. далее. Пример, как поменять местами значения двух переменных:

var
a,b,c: integer;   {целый тип переменных}
begin
writeln('Введите A='); readln(a);                {например, 5}
writeln('Введите B='); readln(b);                {например, 7}
writeln;
a:=a*10;
writeln('Числа А=',a,'    ,    B=',b);               {будет написано A=50 , B=7 }
c:=a;
a:=b;
b:=c;
writeln('Числа А=',a,'    ,    B=',b);               {будет написано A=7 , B=50 }
end.

О ПОДПРОГРАММАХ ВООБЩЕ
Составной оператор, который мы используем в программе много раз и/или из разных мест без изменения его внутреннего алгоритма, хотя и, возможно, с различными от вызова к вызову входными параметрами, удобно сделать ПОДПРОГРАММОЙ-ПРОЦЕДУРОЙ (иногда это называют ПРОЦЕДУРА-ОПЕРАТОР, procedure, в Фортране это называлось subroutine) или же ПОДПРОГРАММОЙ-ФУНКЦИЕЙ (иногда это называют ПРОЦЕДУРА-ФУНКЦИЯ, function).
В ОПИСАНИИ процедуры или функции параметры формальные, а не фактические.
При ВЫЗОВЕ процедуры или функции при исполнении программы вместо формальных параметров автоматически подставляются фактические.
В списке параметров могут быть как данные – местные константы, так и данные – местные переменные (т.е. результаты этой процедуры или функции). Если перед списком переменных слова var отсутствует, то эти "переменные" свое значение изменять здесь не могут, т.е.  это "как бы константы" (с точки зрения языковедов, не следует  путать "параметр с неизменяемым в ходе исполнения процедуры или функции значением" от истинной "константы с неизменяемым в ходе исполнения программы значением"). Если перед списком переменных слово var есть, то указанные данные – переменные.
"Внешняя" разница между ними состоит в форме вызова.

ПОДПРОГРАММА-ПРОЦЕДУРА
Формат описания подпрограммы-процедуры:
procedure ИмяПроцедуры(ИменаФормальныхПараметров: ТипыЭтихПараметров);
begin
        {операторы – содержание процедуры}
end; {конец процедуры}
Процедура вызывается "сама по себе", "отдельной строчкой", т.е. её имя с фактическими параметрами :
ИмяПроцедуры(ИменаИлиЗначенияФактическихПараметров);
Примеры вызова процедур:
РядовойИванов(огонь); ЛейтенантПетров(обстрел,Доннердорф);
ГенералСидоров(штурм,Берлин); МаршалЖуков(взять,Берлин,май,результаты);
Пример программы с подпрограммой-процедурой:
program PokazProcedury;

procedure Kub(x:real; var  xkub:real);
begin
xkub:=x*x*x;
end; {конец процедуры}

var
a,akub,a9: real;                {переменные типа действительные числа}
begin
wrile('Введите А=');
readln(a);
Kub(a,akub);                {возведение А в куб}
writeln('А**3=', akub:0:3);  {форматный вывод действительного числа}
Kub(akub,a9);                {возведение А в кубе ещё раз в куб}
writeln('А**9=', a9:0:3);     {форматный вывод действительного числа}
readln;
end. {конец программы}

При выводе действительных чисел вместо оператора обычного вида write(величина) удобнее использовать его вариант с "ФОРМАТНЫМ" выводом вида: write(величина:Поле:ПослеЗапятой); где ПослеЗапятой – количество цифр, оставляемых после запятой, а Поле – ширина текстового поля, не менее которой будет занимать это число. Пример: write(pi:8:2); и напишется число "пи" в виде 3.14 в правой части поля из 8-ми позиций (а первые 4 позиции останутся пустыми). Если длина числа, округлённого до указанного числа знаков после запятой, больше, чем указанное поле, то число займёт больше места, сколько ему потребуется.
В Б- и О-Паскале предусмотрены многочисленные варианты форматного вывода не только действительных чисел, но и даты, времени. О них – позже.

ПОДПРОГРАММА-ФУНКЦИЯ
Формат описания подпрограммы-функции:
function ИмяФункции(ИменаФормальныхПараметров: ТипыЭтихПараметров):ТипРезультатаФункции;
begin
        {операторы – содержание функции}
        {не менее чем в одном месте где-то должно быть выражение вида:}
        ИмяФункции:=ЗначениеРезультатаФункции;
end; {конец функции}
Функция вызывается как имя, поставленное не "само по себе", а в качестве аргумента (в параметрах подпрограмм или в операндах операторов):
или
Оператор Операнд1 ИмяПроцедуры(ИменаИлиЗначенияФактическихПеременных) Операнд3 Операнд4;
Примеры вызова функций, в т.ч. вложенного вызова:
z:=sin(b);
z:=cos(b*3+sin(c));
if sin(b)>0.5 then z:=cos(b+1);
Kub(5+sin(2*pi*r),z);      {вызов процедуры Kub, в свою очередь, вызывающей функцию sin}
ГдеТочно:=РазведчикКузнецов(искать,ГдеПриблизительноПротивник);
{вызов процедуры ГенералСидоров, в свою очередь, вызывающей функцию РазведчикКузнецов}
               {Если результат функции РазведчикКузнецов(искать,ГдеПротивник)=Берлин , то вышеуказаный вариант "приказа генералу Сидорову" сделает то же самое, что варианты вида ГенералСидоров(штурм,Берлин) или ГенералСидоров(штурм,ГдеТочно)  }
Пример программы с подпрограммой-функцией (сравните с вышеуказанной подпрограммой-процедурой):
program PokazFunkzii;

function Kub(x:real):real;
begin
Kub:=x*x*x;
end; {конец функции}

var
a,akub,a9: real;
begin
wrile('Введите А=');
readln(a);
akub:=Kub(a);                {возведение А в куб}
writeln('А**3=', akub:0:3);  {форматный вывод действительного числа}
a9:=Kub(akub);                {возведение А в кубе ещё раз в куб}
writeln('А**9=', a9:0:3);      {форматный вывод действительного числа}
readln;
end. {конец программы}

САМОСТОЯТЕЛЬНО разберите ещё примеры процедур и функций, более трудные:

{ Пример описания подпрограммы-процедуры: }
Procedure Sounder(friquency,time:integer; var how,concret:char); 
{звучалка с заданными частотой и длительностью, спрашивает, понравилось ли, причём очень либо нет}
{здесь friquency,time – константы, how,concret – переменные}
begin
    Sound(friquency);                {включает звук}
    Delay(time);                {задержка}
    NoSound;                {выключает звук}
    write('Если понравилось, введите Y, иначе N :');
    readln(how);                {понравилось либо нет}
    write('Очень ? (Y/N) :');      
    readln(concret);                {очень либо не очень}
end; {конец процедуры Sounder}
{Пример вызова этой процедуры из тела некоторой программы:}
Sounder(2000,300,PoNdravuAliKak,Aimenno);
if PoNdravuAliKak='Y' then writeln('Вах ! Хорошо звучит !! ') else writeln('Бяка !');
if Aimenno='Y' then writeln ('Причём очень !') else writeln('Но не очень ...');
{Примечание: в Обжект-Паскале, кроме процедуры Sound(с частотой), есть процедура MessageBeep(с параметром) стандартного модуля System, которая выдаёт короткий звук}

{ Пример описания подпрограммы-функции: }
Function Sounder(friquency,time:integer; var concret:char):char;
{здесь friquency,time – константы, concret – переменная}
{ну и сама функция – тоже "переменная", это всегда так}
{здесь, по замыслу, её значение имеет смысл "понравилось либо нет"}
var
        how:char;
begin
    Sound(friquency);
    Delay(time);
    NoSound;
    writeln('Если понравилось, введите Y, иначе N :');
    readln(how);
    Sounder:=how;
    writeln('Очень ? (Y/N) :');
    readln(concret);
end; {конец функции}

{Пример вызова этой функции из тела некоторой программы:}
if Sounder(2000,300,Aimenno)='Y' then writeln('Вах ! Хорошо звучит !! ') else writeln('Бяка !');
if Aimenno='Y' then writeln ('Причём очень !') else writeln('Но не очень ...');

ИЗО ВСЕХ ЭТИХ ПРИМЕРОВ ВИДНО, что если результатом подпрограммы является некоторая единственная величина, то обычно удобнее оформить подпрограмму в виде  функции, а не процедуры.

ПОДПРОГРАММА-МОДУЛЬ – отдельный блок (обычно даже отдельный файл) текста  программы, могущий компилироваться отдельно от основной   части программы. Модули обычно используют (и создают),   
во-первых, если некоторые процедуры и функции часто   используются во многих наших программах (т.е. удобно написать   их один раз в отдельный, оригинальный, модуль, а затем просто к очередной программе подключать ещё и этот модуль объявлением его в разделе uses. В других языках программирования аналогичный раздел обычно оформляется в виде отдельного файла – "проекта", что менее  удобно);   
во-вторых, если программа оказалась настолько громоздка,   что при компиляции не хватает оперативной памяти, и поэтому   приходится делить программу на несколько раздельно   компилируемых частей.
в-третьих, если программа в целом необозримо велика или над ней работает коллектив разных людей, и желательно, во избежание путаницы великого множества переменных, констант, типов, объектов и т.д.и т.п,, выдуманных разными авторами разных частей программы, сделать те переменные, которые только "внутреннего пользования", скрытыми от иных модулей и программы, а те, которые должны взаимодействовать "снаружи" модуля, объявить таковыми составляющими интерфейса этого модуля. 
Стандартные модули Турбо-Паскаля: System, Crt, Dos, Graph, Overlay.  Их назначение и состав – будут описаны далее, в Темах 15, 16 и 27.
Модуль System автоматически подключается всегда, даже без объявления (по умолчанию).
В Б-Паскале и Обжект-Паскале (Дельфи) есть ещё много других модулей: Forms и др. 
Как сделать свой собственный модуль – будет описано далее.

ОБЛАСТЬ ДЕЙСТВИЯ ОПИСАНИЙ 
Если описание (переменных, типов и т.д.) находится ВНУТРИ процедуры или функции, то оно действует только в её пределах, т.е. "локально".  В частности, если описание находится ПЕРЕД главной частью (т.е. разделом операторов программы), НО ПОСЛЕ описания процедур и функций, то оно действует только  в пределах главной части.
А если мы описание поместим в НАЧАЛО программы, точнее, перед  разделом процедур и функций, то оно будет действовать везде –  и в главной части, и в процедурах (функциях), т.е. "глобально".
Вообще, создание процедур и функций делается по тем же правилам, и в том же порядке их описаний, что и вся программа в целом. (Кроме заголовков program, unit и раздела uses : он может быть только в начале ВСЕЙ программы или модуля, но не в началах процедур.)
А вот модули оформляются не совсем так, как процедуры и функции (о модулях см. в Теме 17), причём снаружи и наружу модуля может взаимодействовать обычно только то, что объявлено в специальной части описания модуля – в интерфейсной части.

{Пример некоей программы, обладающей стандартным видом. Писать её вам не требуется. Пусть не всё в ней пока понятно, но надо найти в ней части, уже вам известные – описания, подпрограммы, главную часть:}
program ExampleOfProgram;      {это заголовок}
uses                {объявление используемых модулей, в дополнение к System}
    crt,dos;                {список модулей разделяется запятыми}
label                {объявление меток}
     1,2;
const              {введение глобальных постоянных. ПОСТОЯННЫЕ РАЗДЕЛЯЮТСЯ ТОЧКОЙ С ЗАПЯТОЙ !}
     Ze=1.6E-19;
     C=3E8;
     kuku=150;
     kukareku:integer=0;                {введение глобальной переменной с начальным значением}
type                {описание нестандартных глобальных типов}
    Rainbow=(Red,Orange,Yellow,Green,LightBlue,Blue,Violet);  {это тип "перечислимый", см. далее}
    Teenagers=11..19;                {это тип "интервальный", см. далее}
var                {описание глобальных переменных}
    number:integer;                {типа целый}
    value,v2,bbb:real;                {типа действительный}
    ch:char;                {типа знаковый}
    help:string;                {типа строковый}
    color:rainbow;                {типа rainbow, описанного выше}
    age:teenagers;                {типа teenagers, описанного выше}

procedure Sound2(friquency,time:integer);          {описание процедуры}
begin
     Sound(friquency);
     Delay(time);
     NoSound;
end; {Sound2}

procedure Beep;                {описание процедуры}
begin
     Sound2(3000,500);                {вызов процедуры Sound2, описанной выше}
end; {Beep}

function Energy(Massa:real):real;                {описание функции}
begin
    Energy:=Massa*sqr(C);                {формула Эйнштейна Е=mc2 }
end; {Energy}

function Calcul(t:real):real;              {описание функции}
var                {описание локальных переменных этой функции}
   i:integer;
   j,y:real;
begin
     if t<=0.0 then begin                {условный оператор if ... then, о нём см. далее. Если t неположительная, то пищит}
Beep;                {вызов процедуры Beep, описанной выше}
Calcul:=0.0;
exit;                {досрочный выход из функции, возвращение туда, откуда её вызвали}
     end;
               {Дальше какой-то хитрый расчёт:}
    y:=sqrt(t);                {корень квадратный}
     j:=Ze*number/y;
     i:=Round(j);                {случайное число в диапазоне от 0 до j-1}
    Calcul:=Energy(i+15.6);                {вызов процедуры Energy, описанной выше}
end; {Calcul}

{начинается область главной части, про кукушку:}
var                {описание локальных переменных главной части}
   i:integer;
begin                {начинается сама главная часть - раздел операторов}
    clrscr;                {очистка экрана}
    help:='лет';
    value:=17.5;
    Sound2(200,1000);                {вызов процедуры, описанной выше}
    TextColor(white);                {задание белого цвета текста}
    writeln('Сколько '+help+' ?');
    for i:=1 to kuku do begin                {оператор цикла со счётчиком for ... to ... do , о нём см. далее}
        {TextColor((i mod 16)+Blink);} {эти 2 строчки мы "вырезали", "закомментировали" в фигурные скобки}
        {TextBackGround((i div 16) mod 8);}
        Textattr:=i;                {задание атрибутов текста – разом цвет текста, фона и моргание}
        writeln('Ку-ку      (',i,')');
        Sound2(1000,50);                {вызов процедуры}
        Delay(200);
        Sound2(300,50);                {вызов процедуры}
        {Delay(700);}
    end;                {конец оператора цикла}
    textcolor(white);                {задание белого цвета текста}
1:  writeln('Очень секретные сведения: ',Calcul(value));              {строка с меткой, сюда можно перейти из другого
места оператором безусловного перехода, см. далее}
    repeat until keypressed;     {оператор повторения с постусловием repeat ... until ... , о нём см. далее}
                {функция keypressed типа логический принимает значение истинно,
     если буфер клавиатуры непустой}
end.     {конец всей программы}
Если Вы читаете конспект этой темы первый раз, то вернитесь к  её началу и прочитайте её ещё один раз. Напишите примеры этих программ. Придумайте и свои. Это тоже не вредно.



Тема 6.  ОСНОВНЫЕ ТИПЫ ДАННЫХ.

Типы делятся на ОСНОВНЫЕ (ПРОСТЫЕ) и ПРОИЗВОДНЫЕ (СОСТАВНЫЕ, СЛОЖНЫЕ). Каждое значение любого из основных типов состоит из единственного данного. Производные типы образуются путём комбинации данных, которые могут быть как простых типов, так и производных (разумеется, "в конечном счете"  и они состоят из простых).
Основные типы делятся на СКАЛЯРНЫЕ, ССЫЛОЧНЫЙ (он же адресный, он же указатель, pointer) и (в Обжект-Паскале) ДАТА+ВРЕМЯ. Точнее сказать, ссылки бывают и простые, и составные.
Скалярные типы делятся на:
УПОРЯДОЧЕННЫЕ (порядковые, ordinal – все скалярные типы, кроме действительного)
и ДЕЙСТВИТЕЛЬНЫЙ (вещественный). {Математики от такого условного названия в ужасе – ведь в математике действительные числа вообще-то тоже упорядочены!}
             СКАЛЯРНЫЕ ТИПЫ в Т-Паскале:
Их обозначение                Их название                Их примеры
real                – действительный (вещественный) 4-байтовый –                16.7E-3      -4.9E2
integer                –  целый  2-байтовый –                2   -5   120
char  (character)         – знаковый (символьный, литерный) 1-байтовый –                'S'   'Ы'  '7'   ' '
boolean (Булевский) – логический (1-битовые операции, фактически расходует 1 байт) –    false  true
Т-Паскаль был ориентирован на 8-разрядные процессоры, с этими четырьмя типами он работает быстрее всего. остальные типы при вычислениях автоматически временно преобразуются на составляющие этих типов, а после вычислений восстанавливаются обратно.
Ещё к скалярным упорядоченным типам относятся ПЕРЕЧИСЛИМЫЕ  и ОГРАНИЧЕННЫЕ (интервальные, диапазонные), но о них – см. далее.
В Т- и Б-Паскале есть ещё типы, аналогичные (по правилам обращения с ними) целому. Это shortint (1-байтовое) и longint (4-байтовое).
В Т- и Б-Паскале есть ещё типы беззнаковые целые. Это byte (1 байт) и word (2 байта).
В Т- и Б-Паскале есть ещё типы, аналогичные (в смысле правил обращения с ними) действительному. Это (как бы математические действительные) single (2-байтовые), double (8-байтовые), extended (10-байтовые).
Большинство действительных типов относятся к числам с плавающей запятой (т.е. в его состав входят знак числа, мантисса и показатель степени основания). Некоторые из действительных типов относятся к числам с фиксированной запятой.
Например, в Т- и Б-Паскале есть тип comp (8-байтовый), который принимает только целые значения, но правила обращения с ним, функции – как у действительных типов (т.е. это действительное число с фиксированной запятой, ни одного знака после запятой).
В О-Паскале длина целых типов увеличена. А именно, smallint 2-байтовый целый, integer и longint 4-байтовые целые, cardinal 4-байтовый беззнаковый; single 4-байтовое действительное, real 6-байтовое, double 8-байтовое,  extended 10-байтовое; тип comp 8-байтовый; ещё появился 8-байтовый действительный тип currency с фиксированной запятой (4 десятичных знака после запятой). Поэтому, начав работать в новой для вас среде программирования, проверьте по автоматической подсказке длины используемых вами типов данных.
Б-Паскаль был ориентирован на 16-разрядные процессоры с арифметическим сопроцессором, там самый быстрый из действительных типов – 8–байтовый double, а из целых типов – его 4-байтовые integer и longint.
О-Паскаль ориентирован на 32-разрядные процессоры. Возможно, что в более новых реализациях Паскаля самыми быстрыми типами будут типы с ещё большей длиной.

САМОСТОЯТЕЛЬНОЕ УПРАЖНЕНИЕ
Составьте древовидную схему простых типов данных. Заготовьте место для схемы составных типов данных.

Особенности типа целый, беззнаковый целый и т.п.:
операции деления, как действительных, / нет; но есть целочисленное деление div ...
Примеры: 7 div 2           {=3};               3 div 5             {=0};            (-7) div 2             {=-3};
... и взятие остатка mod по натуральному модулю. По определению, только при n>0:
если m>=0, то (m mod n) = m-((m div n)*n)
если m<0,  то (m mod n) = m-((m div n)*n)+n
Примеры: 7 mod 2        {=1};                3 mod 5           {=3};             (-14) mod 3          {=1};      (-15) mod 5     {=0}.
Ещё есть сдвижка битов влево – x shl y – с заполнением освободившихся младших позиций нулями (фактически быстрое умножение двоичного числа на 2y) и сдвижка битов вправо – x shr y – с заполнением освободившихся старших позиций нулями (фактически быстрое целочисленное деление на 2y). Примеры:
i shl 3  {умножение на 8}
i shr 3  {то же, что   i div 8}
Процедура инкремента inc(i,j) увеличивает аргумент i на j единиц (т.е. i:=i+j), по умолчанию увеличивает на 1. Она действует быстрее, чем универсальное сложение. Ещё быстрее действует приращение на единицу inc(i).
Процедура декремента dec(i,j) уменьшает аргумент i на j единиц (т.е. i:=i-j), по умолчанию уменьшает на 1. Она действует быстрее, чем универсальное вычитание. Ещё быстрее действует уменьшение на единицу dec(i).
{Декремент и инкремент были введены для совместимости языков Борланд-Паскаля и Борланд-Си.}
Функция Odd(i) , если i чётное, даёт значение false, а если i нечётное, даёт  значение true; Even(i) всё наоборот.
Функция Chr(b) для беззнаковых целых даёт символ с порядковым номером b.
Если ch – строчная латинская буква, то функция UpCase(ch) даёт в Обжект-Паскале заглавную букву.
Для беззнаковых целых функция Hi(word) даёт старший байт слова, Lo(word) даёт младший байт слова, Swap(word) меняет местами байты в слове.
Для беззнаковых целых и неотрицательных целых random(i) – случайное значение в диапазоне от 0 до i-1.
Рекомендуется инициализировать (перетасовать) генератор случайных чисел процедурой Randomize.

Для всех упорядоченных типов определены функции:
succ(i) – непосредственно следующее за i значение
pred(i) – непосредственно предыдущее i значение
ord(i) – порядковый номер значения i среди возможных для его типа
Однотипные значения упорядоченных типов можно сравнивать между собой.
Примеры:
7>5
'C'>'A'
true>false
white>green>black
Для всех скалярных типов есть ещё функции:
abs(x)    – абсолютная величина (модуль);
sqr(x)    – возведение в квадрат;
trunc(x)  – усечение до целого;
round(x)  – округление до целого по правилам арифметики.

Для действительных типов определены ещё функции:
frac(x)          {даёт дробную часть аргумента}
int(x)            {даёт целую часть аргумента}
sin(x)
cos(x)
arctan(x)     {это функция Arctg(x)}
sqrt(x)         {квадратный корень}
Ln(x)
exp(x)
Трудный пример:  как записать 5,7+4,33,5  ?  Ответ:  5.7+exp(4.3*Ln(3.5));
Для действительных random(x) – случайное значение в диапазоне от 0 до x-1.
Постоянная pi даёт число ;.

Для логического типа:
значения только false – ложно и true – истинно; они упорядочены: false<true.
Операции НАД значениями логического типа: not – не, and – и, or – или, xor – либо.
{не:}
not true = false          
not false= true
{и ..., и ...:}
true and true = true      
true and false = false
false and true = false
false and false = false
{хотя бы ... или ...:}
true or true = true      
true or false = true
false or true = true
false or false = false
{"либо", логическое исключающее или, "строго одно из двух", сложение по модулю 2:}
true xor true = false
true xor false = true
false xor true = true
false xor false = false

Самостоятельное упражнение: составьте таблицу c 4-мя строками и с колонками:
x, y, not x, x and y, x or y, x xor y. Заполните её логическими значениями этих переменных и функций.

Переменная ССЫЛОЧНОГО (адресного) типа, или Указатель (pointer) – переменная, значением которой является адрес в памяти ЭВМ. Их применение рассмотрим позже, при работе с динамическими переменными (при работе с модулем Graph, построении динамических структур данных, баз данных). Ссылки бывают и простые, и составные.

В О-Паскале есть тип TDateTime (ДАТА+ВРЕМЯ), занимает 8 байтов подобно действительному числу, в его целой части – дата, в дробной – время. Относить тип "дата+время" к простым либо составным – вопрос несколько философский, мы не будем его касаться.  В О-Паскале предусмотрены функции для работы с этим типом: Date, Time, и функции типа строка: DateTimeToStr(ДатаВремя), DateToStr(ДатаВремя), TimeToStr(ДатаВремя).

Способы приведения переменных слева и справа к единому типу состоят, во-первых, в том, что более мощному типу можно присвоить значение менее мощного типа, например, действительному числу присвоить целое значение; во-вторых, менее мощному типу присвоить усечённое значение более мощного типа. Примеры:
1) действительное – в целое:
i:=round(x);          {округление, см.выше}
i:=trunc(x);           {усечение до целого, см.выше}
i:=int(x);                {целая часть, см. выше}
Начиная с T-Паскаля возможно приведение типов универсальной формулой вида
Переменная:=ИмяТипаЭтойПеременной(АргументДругогоТипа);
2) символ – в целое: i:=integer(ch); или i:=ord(ch); i:=integer(byte);
3) короткое целое или байт – в символ: ch:=chr(i);     {функция chr даёт тип символьный, char}
4) целое – в действительное: x:=1.0*i;
5) целое – в байт: b:=$01*i;
6) любое из упорядоченных типов – в целое: i:=ord(true);  {функция ord даёт порядковый номер аргумента}

О двух разновидностях упорядоченных типов – перечислимых и ограниченных – см. далее.

Тема 7. ОСНОВНЫЕ ОПЕРАТОРЫ ЯЗЫКА ПАСКАЛЬ.

;   – ПУСТОЙ оператор. Он же используется для разделения других  операторов. Или для резервирования места в алгоритме программы. Он ничего не делает.

:=  – оператор ПРИСВАИВАНИЯ. Переменной, указанной слева от него, присваивается значение, указанное справа от него. Типы данных слева и справа обычно должны быть одинаковыми.  За исключением случая, когда слева – действительное число (переменнная), а справа – целое число (значение). 

Оператор БЕЗУСЛОВНОГО ПЕРЕХОДА на строку (оператор) с МЕТКОЙ: goto Метка; пример: goto 7;
простые программы с оператором goto писать и проверять легко; для сложных программ это совсем не так.
Очевидно, что при использовании операторов безусловного перехода можно построить такие программы, исполнение которых не будет заканчиваться никогда.
Математики доказали даже, что даже всего лишь доказать, завершится исполнение некоторого алгоритма либо нет, если в его состав входят операторы безусловного перехода, в общем случае невозможно (т.е. построение нормального алгоритма, проверяющего некоторый другой алгоритм, содержащий безусловные переходы, на потенциальную завершаемость, в общем случае, для произвольного проверяемого алгоритма, невозможно; т.е. проверка алгоритма, содержащего безусловные переходы, на потенциальную завершаемость является алгоритмически неразрешимой задачей).
Ляпунов и Янов в СССР, а позже Бом и Джакопини за рубежом доказали, что можно так ограничить множество допустимых операторов, причём запретить употребление безусловных переходов, что задача проверки алгоритма, построенного с помощью только этих допустимых операторов структурного программирования, будет алгоритмически разрешимой. Ляпунов, Янов, Ершов, Дейкстра и др. ввели в употребление такой набор небезусловных переходов (простые ветвления – условные переходы, сложные ветвления – варианты; многократные повторения – циклы Ершова), который позволил осуществлять это, так называемое "структурное программирование".

УСЛОВНЫЙ (выбирающий) оператор БЕЗ ЯВНОЙ АЛЬТЕРНАТИВЫ:
if Условие then Оператор;
{Если Условие=true (т.е. истинно), то выполнять  Оператор. }
Здесь и далее словом Оператор будет обозначаться произвольный оператор – простой или же составной.
Примеры:  if name='Вася' then writeln('Здравствуй, Вася!');  if x>5.8 then x:=x+33; if x>3 then writeln('больше');

УСЛОВНЫЙ (выбирающий) оператор С ЯВНОЙ АЛЬТЕРНАТИВОЙ:
if Условие then Оператор1 else Оператор2;
{Если Условие=true, то выполнять Оператор1,  а иначе выполнять Оператор2.  }
Примеры:
if not ZerGut then writeln('бяка') else writeln('нака');
if not Odd(i) then writeln('чётное') else writeln('нечётное');
if parol=pass then begin
         TextColor:=Green;
          writeln('Заходи !');
end
else Arest;
{Обратите внимание: перед else точка с запятой не ставится ! Иначе это был бы ещё один оператор – пустой.}

Интересно, что в некоторых языках программирования есть ещё условные операторы трёхзначной логики Диогена (истинно, ложно, неопределённо), а в языке Фортран есть условный оператор тоже с 3-мя вариантами, в зависимости  от того, отрицательно, равно нулю либо положительно значение аргумента.

Оператор ПОВТОРЕНИЯ С ПРЕДУСЛОВИЕМ:
while УсловиеДеятельности do Оператор;
{до тех пор, пока УсловиеДеятельности является истинным, повторять Оператор. Как только УсловиеДеятельности окажется ложным, повторение прекращается. Оператор выполняется ноль или более раз.}
{Обратите внимание: перед do точка с запятой не ставится!}
Примеры:
while true do;   {Не делайте так ! Это простейший пример "зацикливания", "зависания" – на одном месте!}
while x<100 do x:=x+1;
{Следующий пример программы очищает буфер клавиатуры и затем сообщает код нажатой клавиши.
Бывают двухбайтовые клавиши, в этом случае программа должна дать два числа.}
program AnalizatorKodaKlavishi;     {Анализатор кода клавиши}
uses crt;    {в этом модуле живут нужные нам логическая функция keypressed и символьная readkey}

procedure OchistkaKlav;
var
b:byte;
begin
while keypressed do b:=byte(readkey);  {до тех пор, пока буфер непустой, читать его побайтово впустую}
end; {конец процедуры очистки}

label 1;
var
ch1,ch2:char;
i1,i2:shortint;
begin
clrscr;                {очистка экрана}
writeln('Начинает работу анализатор кода клавиш.');
1: OchistkaKlav;              {вызов процедуры очистки буфера клавиатуры}
ch1:=readkey;
i1:=shortint(ch1);
if keypressed then begin   {если клавиша была двухбайтовая, то буфер клавиатуры ещё не пуст, читать ещё}
ch2:=readkey;
i2:=shortint(ch2);
writeln('Вы нажали двухбайтовую клавишу с кодами ',i1,' и ', i2);
end else writeln('Вы нажали однобайтовую клавишу ',ch1,' ; её код ',i1);
if i1=27 then begin
writeln('Это была клавиша Esc. На этом программа заканчивает работу. Нажмите Enter.');
readln;   {ждать, пока не нажмём Enter}
end else goto 1;  {возврат на метку 1. Это можно делать, программа простая, завершаемость очевидна.}
end. {конец программы}
Кстати сказать, у двухбайтовых клавиш первый байт равен $00. Убедитесь в этом.

program face;          {Рисует мордочку, которую можно гонять по экрану стрелками:}
uses
crt,dos;
var
x,y:integer;
ch:char;
spec:boolean;
begin
clrscr;                {очистка экрана}
while keypressed do ch:=readkey;                {очистка буфера клавиатуры}
x:=1; y:=1;  spec:=false;
while integer(ch)<>27 do begin                {если нажата клавша Esc, то выход}
clrscr;
GotoXY(x,y);                {переход в указанную клетку}
TextColor(white);                {белый цвет на чёрном фоне}
write(chr($01));         {мордочка}
textattr:=0;         {чёрный цвет на чёрном фоне – для стирания}
ch:=readkey;                {чтение знака из клавиатуры}
if integer(ch)=0  then spec:=true else spec:=false;    {специальная ли клавиша}
if spec then begin
ch:=readkey;                {чтение второго знака из буфера клавиатуры}
case integer(ch) of                {если нажаты стрелки}
75:x:=x-1;
77:x:=x+1;
72:y:=y-1;
80:y:=y+1;
end; {case}
if x<1 then x:=80;                {невыход за пределы экрана}
if x>80 then x:=1;
if y<1 then y:=25;
if y>25 then y:=1;
end;   {if}
end;   {while}
end.

Оператор ПОВТОРЕНИЯ С ПОСТУСЛОВИЕМ:
repeat Оператор until УсловиеПрекращенияДеятельности;
{ повторять Оператор до тех пор, пока УсловиеПрекращенияДеятельности является ложным. Другими словами, повторять Оператор до тех пор, пока УсловиеПрекращенияДеятельности не станет истинным. Как только после выполнения Оператора оказалось, что УсловиеПрекращенияДеятельности истинно, повторение прекращается. Оператор выполняется однин или более раз.}
{Обратите внимание: перед until точка с запятой не ставится !}
Примеры:
repeat until keypressed; {повторять пустой оператор до тех пор, пока буфер клавиатуры пустой}
repeat begin
write('Мама !!! Введите число:');
readln(x);
end until x<0;
Перепишем главную часть программы "анализатор клавиатуры" так, чтобы можно было обойтись без goto.
begin
    clrscr;
writeln('Начинает работу анализатор кода клавиш.');
    repeat begin
OchistkaKlav;
ch1:=readkey;
i1:=shortint(ch1);
if keypressed then begin
ch2:=readkey;
i2:=shortint(ch2);
writeln('Вы нажали двухбайтовую клавишу с кодами ',i1,' и ', i2);
end else writeln('Вы нажали однобайтовую клавишу ',ch1,' ; её код ',i1);
    end until i1=27;
    writeln('Это была клавиша Esc. На этом программа заканчивает работу. Нажмите любую клавишу.');
    repeat until keypressed;     {ждать, пока не нажмём какую-ниюудь клавишу}
    OchistkaKlav;                {убрать её код из буфера клавиатуры}
end. {конец программы}

ЦИКЛ (оператор повторения) с ВОЗРАСТАЮЩИМ счётчиком:
{Переменная Счётчик должна быть одного из упорядоченных типов}
for Счётчик:=НачальноеЗначение to КонечноеЗначение do Оператор;
{Шаг 1. Присвоить Счётчику НачальноеЗначение.
Шаг 2. ЕСЛИ Счётчик<=КонечногоЗначения, ТО выполнить Оператор, ИНАЧЕ выход.
Шаг 3. ЕСЛИ Счётчик <КонечногоЗначения, ТО увеличить Счётчик на 1, ИНАЧЕ выход.
Шаг 4. Перейти на Шаг 2.}
Если НачальноеЗначение>КонечногоЗначения, то Оператор не выполнится ни разу.
{В некоторых языках программирования, например, Фортран, можно задавать шаг приращения счётчика, больший 1.
В некоторых языках программирования Шаг 3 делается иначе: безусловно увеличить Счётчик на 1. Такой вариант действует быстрее, но нехорош тем, что после окончания цикла переменная Счётчик на единицу больше КонечногоЗначения, это было бы очень неудобно.}
Пример:
k:=0;
for i:=1 to 100 do k:=k+i; {Просуммируются первые 100 натуральных чисел}
n:=0;
for i:=1 to 100 do begin
      if i mod 7 =0 then n:=n+i; {Просуммируются натуральные числа, кратные 7, не превышающие 100}
end;
Пример вычисления факториала (N!, например, 5!=1*2*3*4*5;    0!=1   ) в две строчки операторов:
var
N,NF,i: longint;
begin
readln(N);
NF:=1;
if N>=1 then for i:=1 to N do NF:=NF*i;
writeln(NF); readln;
end.

ЦИКЛ (оператор повторения) с УБЫВАЮЩИМ счётчиком:
{Переменная Счётчик должна быть одного из упорядоченных типов}
for Счётчик:=НачальноеЗначение downto КонечноеЗначение do Оператор;
{Шаг 1. Присвоить Счётчику НачальноеЗначение.
Шаг 2. ЕСЛИ Счётчик>=КонечногоЗначения, ТО выполнить Оператор, ИНАЧЕ выход.
Шаг 3. ЕСЛИ Счётчик >КонечногоЗначения, ТО уменьшить Счётчик на 1, ИНАЧЕ выход.
Шаг 4. Перейти на Шаг 2.}
Если НачальноеЗначение<КонечногоЗначения, то Оператор не выполнится ни разу.
{В некоторых языках программирования, например, Фортран, можно задавать шаг убывания счётчика, больший 1.
В некоторых языках программирования Шаг 3 делается иначе: безусловно уменьшить Счётчик на 1. Такой вариант действует быстрее, но нехорош тем, что после окончания цикла переменная Счётчик на единицу меньше КонечногоЗначения, это было бы очень неудобно.}
Пример:
for i:=10 downto 0 do begin
writeln('Осталось ',i,' секунд ...');
delay(1000);
end;
writeln('Пуск!');

Внимание! Внутри циклов со счётчиком изменять значение счётчика не рекомендуется (а структурное программирование это прямо запрещает); но можно; но осторожно. Короче говоря, не делайте так, и всё будет хорошо. Может быть.

ВЛОЖЕННЫЕ ЦИКЛЫ – удобное средство для изменения сразу двух или более параметров. И начало, и конец вложенного цикла должны располагаться внутри внешнего цикла. Пример вложенных циклов:
{Построение таблицы названий клеток шахматной доски}
var
x:char;           {буквы}
y:shortint;     {цифры}
begin
clrscr;
for y:=8 downto 1 do begin
for x:='a'  to 'h' do begin
write(x,y,'   ');
end; {внутреннего цикла – по  x}
writeln; writeln;
end; {внешнего цикла – по y}
readln;
end.
В этом примере многочисленные begin ... end оставлены для налядности. Вообще-то внутренный цикл точно так же работал бы, если там написать просто for x:='a'  to 'h' do write(x,y,'  ').

АРИФМЕТИЧЕСКИЕ и ЛОГИЧЕСКИЕ операторы Паскаля уже были рассмотрены выше.

Остальные операторы Паскаля рассмотрим в ряде следующих тем.

Тема 8. ПЕРЕЧИСЛИМЫЕ и ОГРАНИЧЕННЫЕ типы. Оператор ВАРИАНТА. Процедуры ВЫХОДА.

Рассмотрим ещё два скалярных упорядоченных типа данных – перечислимый и ограниченный.

Если приходится иметь дело с понятиями, каждое из которых состоит из конечного множества значений, т.е. своих частных случаев, то очень удобно ввести ПЕРЕЧИСЛИМЫЙ (перечисляемый) тип. Он задаётся так:
type НазваниеТипа=(СписокДопустимыхЗначений); {список значений приводится через запятую}
Примеры:
type       boolean=(false,true);  {так уже определён стандартный логический тип}
type
Rainbow=(Red,Orange,Yellow,Green,LightBlue,Blue,Violet);
DaysOfWeek=(Pn,Wt,Sr,Cht,Pt,Sb,Ws);
DniNedeli=DaysOfWeek;  {то же самое}
Перечислимый тип можно конструировать только из скалярных упорядоченных значений! Например, ошибочно было бы определять тип Friends=('Вася','Петя','Маша','Саша','Глаша','Даша'), т.к. строки не относятся к "упорядоченным (порядковым) типам" (хотя строки есть "упорядоченные наборы символов"), просто неудачное название для группы "упорядоченных (порядковых) типов". Подробнее о строках см. далее.
Пример использования перечислимого типа:
var
    Walking :boolean;
    day        :DaysOfWeek; {этот тип ДниНедели был определён выше}
begin
    for day:=Pn to Pt do writeln('Working Day...');
    {... допустим, что где-то здесь как-то задали значение переменной day.}
    if (day=Sb) or (day=Ws) then Walking:=true; {Ну, вообще-то мы работаем и в эти дни :-)  ха-ха }
    {... допустим, что где-то здесь идут какие-то ещё операторы}
end.
В модулях crt и graph определены 16 стандартных цветов Паскаля как значения перечислимого типа – и другие. Они соответствуют целым числам от 0 до 15. Самостоятельное упражнение: выясните, как называются остальные цвета. Подсказка: для этого удобно использовать циклы со счётчиком и процедуры задания цвета текста, фона и моргания модуля crt. Процедура TextColor(Цвет) задаёт цвет текста (от 0 до 15). Процедура TextBackGround(Цвет) задаёт цвет фона под текстом (от 0 до 7). Переменная TextAttr задаёт "атрибуты текста", то есть сочетание цвета текста, цвета фона и моргания; она может быть от 0 до 255. При этом если TextAttr >= константы Blink=128, то текст моргает.

Переменная ОГРАНИЧЕННОГО типа (он же тип-ДИАПАЗОН, тип-ИНТЕРВАЛ) может принимать только значения из указанной ограниченной области значений "своего базового" скалярного упорядоченного типа.
Меньшая граница должна быть указана левее большей:
type НазваниеТипа=МеньшаяГраница..БольшаяГраница;
Примеры объявления ограниченных типов:
type
    TeenAgers=11..19;            {базовый тип – integer}
    SibirskijMoroz=-70..-1;     {базовый тип – integer}
    DaysOfWeek=(Pn,Wt,Sr,Cht,Pt,Sb,Ws);
    WorkingDays=Pn..Pt;    {базовый тип – DaysOfWeek}
    WalkingDays=Sb..Ws;    {базовый – DaysOfWeek}
Для переменных ограниченного типа в Б- и О-Паскале есть функция High(x), она даёт БольшуюГраницу диапазона того типа, к которому относится аргумент, и функция Low(x), она даёт МеньшуюГраницу. Не путать эти функции с Hi(word) и Lo(word), см. выше.

ОПЕРАТОР ВАРИАНТА без явной альтернативы:
Он относится к выбирающим операторам, как и операторы условного перехода if  ... then, if ... then ... else.
Он может заменить собой сразу несколько условных операторов. Селектор варианта может быть переменной только скалярного типа (в т.ч. логическое условие). Вариант – константа того же типа, что и селектор.
case Селектор of
     Вариант1:Оператор1;
     Вариант2:Оператор2;
     Вариант3:Оператор3;
     Вариант4:Оператор4;
     {... и ещё много аналогичных строк ...}
end;  {case}
{обратите внимание: слова begin здесь нет , а слово end есть!}
Если значение Селектора равно одному из Вариантов, то выполняется соответствующий Оператор.
Если значение Селектора не равно ни одному из Вариантов, ничего здесь не делается, просто переход к следующему оператору программы.
Предусмотренные Варианты можно задавать 1) как отдельные значения, 2) как  перечисление, 3) как диапазон:
    Значение                {отдельное}
    Значение1,Значение2,Значение3                {перечисление}
    МинимальноеЗначение..МаксимальноеЗначение  {диапазон}

ОПЕРАТОР ВАРИАНТА С ЯВНОЙ АЛЬТЕРНАТИВОЙ:
Он отличается от оператора варианта без явной альтернативы тем, что если значение Селектора не равно ни одному из предусмотренных Вариантов, то выполнится АльтернативныйОператор.

case Селектор of
     Вариант1:Оператор1;
     Вариант2:Оператор2;
     Вариант3:Оператор3;
     Вариант4:Оператор4;
     {... и ещё много аналогичных строк}
     else АльтернативныйОператор;
end;  {case}
{Обратите внимание: здесь слово end стоит после слова else !}

Примеры операторов варианта:

case bukva of
           'A': writeln('Арбуз');
           'Б': writeln('Банан');
    'В'..'Э': writeln('Тоже неплохо.');
   'Ю','Я': writeln('Ой! А это съедобно?');
end;  {case}

case NumberPropuska of                {"Вахтёр или секретарь"}
           0:  writeln('А, Шарик ... на, "жуй-жуй, глотай". ');
           1:  writeln('Здравия Желаю !!!');
      2..5:  writeln('Ваша почта, сэр.');
 17,8,11: writeln('Зайдите-ка к начальнику, он вызывал и при этом был сердит.');
        else writeln('Заходите');          {для  остальных работников}
end;  {case}

case day of
    Pn..Pt:  writeln('Working');
    Sb,Ws: begin
   writeln('Walking');
   Beep;
   end;
end; {case}

ВЫХОДЫ И ОСТАНОВЫ, со значением и без
Подпрограмма или программа нормально завершаются по окончании исполнения их последнего оператора. Но иногда при написании программы бывает, вместо явных переходов на конец цикла, подпрограммы или конец программы, удобно указать "точки выхода" (они реализованы автоматически как переходы в концы, но выглядят как места выхода). Начиная с Т-Паскаля в модуле crt есть процедуры:
exit – если это место в подпрограмме, то происходит выход из подпрограммы в вызывавшую её программу, на следующий оператор в программе; но если это место в главной части программы, то прекращение исполнения  всей программы.
halt(КодОстанова) – прекращение исполнения всей программы с генерацией значения параметра КодОстанова. Он покажется в командной строке, также его можно узнать специальной функцией (об этом позже). Процедуру halt удобно использовать для простой "трассировки" программы – прослеживания, дошла ли она до этого места.
В О-Паскале предусмотрены ещё и подобные процедуры внутри циклов:
break – досрочный выход из оператора цикла на следующий за ним оператор;
continue – досрочное завершение очередного прохода цикла, т.е. передача управления в самый конец оператора этого цикла.
Досрочные выходы и остановы не противоречат структурному программированию, они сокращают, делают более наглядной запись программы.

Тема 9. НЕКОТОРЫЕ СОСТАВНЫЕ ТИПЫ: МАССИВЫ И СТРОКИ

К СОСТАВНЫМ ТИПАМ относят:
1. Структурированные
• Регулярные (Массивы)
• Строки
• Составные указатели
• Записи
• Множества
• Файловый тип (не путать с файлом – он неограниченной длины, а файловый тип ограничен по размеру; файл рассматривается как цепочка из данных файлового типа):
; Текстовый файловый тип
; Типизированный файловый тип
; Нетипизированный файловый тип
• Объекты, они же  Алгебры (в О-Паскале они относятся к составным, но не к структурированным)
2. Процедурный (это не процедуры, а тип данных такой!)
В Обжект-Паскале есть ещё и:
3. Варианты (это не оператор варианта, см. выше, а тип данных такой – "вариант". О нём – позже.)
4. Классы (можно рассматривать класс как объект, снабжённый ещё и свойствами; о классах – позже).

Структурированные типы в Т-Паскале и на 16-разрядных вариантах Б- и О-Паскаля не могли занимать более 64 КБайт (1 сегмент памяти), приходилось использовать для хранения больших данных только файлы (не путать с файловым типом переменных!), в 32-разрядных их версиях ограничение на объём переменных структурированных типов облегчено до 2 ГБайт. Обычно этого хватает "для полного счастья". Переменные большего размера приходится записывать в виде файла.
В Т-Паскале для размещения структурированных типов данных в упакованном виде (плотнее, но медленнее) использовалось в описании типа дополнительное слово packed. В О-Паскале упаковка предусмотрена автоматически даже без особого указания на это.

РЕГУЛЯРНЫЙ тип (МАССИВ)
Это УПОРЯДОЧЕННЫЙ набор ОДНОРОДНЫХ элементов. В математике такая вещь называется "тензор". нуль-мерный тензор называется "скаляр" (в программировании скаляры называют "простыми" типами; к сожалению, программисты – не математики, и они "скалярным типом" данных назвали лишь частный случай "простых" типов; математики этой неудачной терминологией возмущены), 1-мерный тензор в математике называется "вектор", 2-мерный тензор называется "матрица", 3-мерные и большей размерности тензоры просто так и называют – тензоры.
Объявление одномерного массива:   array [МинимальныйИндекс..МаксимальныйИндекс] of БазовыйТип;
Базовый тип – тип составляющих массива; базовый тип должен быть определённой длины, поэтому строки с нефикисрованной длиной (см. далее) и текстовые файловые переменные (см. далее) быть составляющими массива не могут.
Оба индекса должны относиться к одному и тому же упорядоченному типу – например, целому, символьному.
Индексы могут быть и отрицательные. Минимальный индекс должен быть меньше или равен максимального.
Объявление двумерного массива:   array [МинИнд1..МаксИнд1, МинИнд2..МаксИнд2] of БазТип;
{это то же самое, что объявить array [МинИнд1..МаксИнд1] of array [МинИнд2..МаксИнд2] of БазТип;}
Начиная с Т-Паскаль, возможны и массивы с размерностью больше 2-х координат (тензоры). В языке Фортран допускались 7-мерные массивы; в Т- , Б- и О-Паскале тоже есть разумные ограничения на размерность массивов.
Пример массивов:
const
        NumberOfStudents=10;
type
    DaysOfWeek=(Pn,Wt,Sr,Cht,Pt,Sb,Ws);
var
    Balls          :array[1..20] of integer;
    Stipa          :array[1..NumberOfStudents] of integer;  {константа в качестве индекса}
    Density     :array[-10..+10,0..100] of real;                {двумерный массив}
    Scalar       :array[7..7] of real;                {массив из одного элемента – по существу, это скаляр}
    Friquency :array[char] of integer;                {указано название упорядоченного типа, значит, индексы
пробегают всё множество его значений}
    Income      :array[Pn..Pt] of real;         {интервал из значений перечислимого типа DaysOfWeek}
    i,x,y           :integer;
    Chess         :array ['a'..'h',1..8] of string[2];                {массив из строк фиксированной длины, причём по разным
координатам индексы могут быть разных типов}
begin
    for i:=1 to NumberOfStudents do Stipa[i]:=55;           {советских рублей}
    for x:=-10 to 10 do begin
for y:=0 to 100 do Density[x,y]:=sin(x)*3*y;
writeln('Рассчитана функция 3y*sin(x) для x=',x);
    end;
    readln;
end.

Пример с двумя векторами a и b длиной по 10 чисел каждый:
const      dlina=10;
var
a,b,c: array [1..dlina] of real;
i: integer;
ab: real;
begin
{... задание значений массивов a и b}
ab:=0;
for i:=1 to dlina do ab:=ab+a[i]*b[i];          {здесь вычисляется скалярное произведение векторов a и b}
writeln('Скалярное произведение равно ',ab:0:3);
c:=a;            {а здесь целиком вектору c присваиваются те же значения, что и вектору a ;
то же самое можно было бы сделать так: for i:=1 to dlina do c[i]:=a[i];  но это громоздче }
readln;
end.

Чтобы передать массив в качестве параметра в процедуру или функцию, приходится сначала описать его тип в глобальном разделе типов, и затем объявить переменную этого типа. Пример:
const
        NumOfStudents=10;
type
    StipaType :array[1..NumOfStudents] of real;

procedure Stipendia(var Students:StipaType);                {формальный параметр Students}
var
        i:integer;
begin
        for i:=1 to NumOfStudents do Students[i]:=55.00;                {студентам дали по 55 рэ СССР}
end; {Stipendia}

procedure Nalog(var Grajdane:StipaType);                {формальный параметр Grajdane}
var
        i:integer;
begin
        for i:=1 to NumOfStudents do Grajdane[i]:=(1-0.1)*Grajdane[i];      {с граждан взяли по 10%  как налога СССР}
end; {Nalog}

var
        PhysTechGruppa:StipaType;
begin
        Stipendia(PhysTechGruppa);     {фактическому параметру PhysTechGruppa дали стипу}
       Nalog(PhysTechGruppa);         {с фактического параметра PhysTechGruppa взяли налог}
end.

АЗБУКА ВЫЧИСЛИТЕЛЬНОЙ МАТЕМАТИКИ (ЗАДАНИЕ)
Задание по теме "массивы" на самостоятельную работу повышенной трудности. Если вы, читатель, студент, то самостоятельно составьте для себя (пригодятся) такие очень полезные процедуры и функции. В этом кратком пособии нет возможности заменить собой толстые учебники академиков по вычислительной математике, которые изучают несколько лет в ВУЗах.
1. Операции с комплексными числами.
2. Сложение векторов.
3. Вычитание векторов.
4. Умножение вектора на число.
5. Сложение матриц.
6. Вычитание матриц.
7. Умножение матрицы на число.
8. Вычисление скалярного произведения двух векторов.
9. Умножение векторов слева и справа.
10. Умножение матриц слева и справа.
11. Вычисление определителя матрицы.
12. Вычисление матрицы Грама.
13. Вычисление векторного произведения.
14. Решение систем неособенных линейных уравнений методами Гаусса, Гаусса–Жордана.
15. Нахождение собственных значений неособенной матрицы.
16. Операции винтового исчисления.
17. Псевдорешение наименьших квадратов переопределённых несовместных систем линейных уравнений методом Гаусса.
18. Численное решение алгебраических нелинейных уравнений одной действительной переменной методом дихотомии с вычёркиванием корней.
19. Численное интегрирование функций одной переменной методами: прямоугольников справа, прямоугольников слева, прямоугольников посередине, трапеций, парабол.
20. Численное интегрирование функций одной переменной методом Монте-Карло.
21. Вычисление свёртки (интеграла Дюамеля).
22. Численные преобразования Фурье, Хартли, Котельникова, Уолша, экспоненциальные вейвлетные.
23. Численное дифференцирование первой степени первого порядка точности: двухточечное справа, двухточечное слева.
24. Численное дифференцирование первой степени первого порядка точности: трёхточечное.
25. Численное дифференцирование второй степени: трёхточечное.
26. Интерполяция функций одной переменной: линейная, параболическая, сплайнами 4-го порядка.
27. Вычисление оптимально приближающих многочленов Чебышёва.
28. Сглаживание функций одной переменной методом  окна с весами.
29. Сглаживание функций одной переменной методом  скользящего окна с весами.
30. Численное решение дифференциальных уравнений первой степени первого порядка точности (двухточечные одношаговые).
31. Численное решение дифференциальных уравнений первой степени методом Эйлера второго порядка точности (двухточечный с промежуточной точкой).
32. Численное решение дифференциальных уравнений первой степени методом стрельбы.
33. Численное решение дифференциальных уравнений первой степени методом прогонки Канторовича.
34. Псевдорешение переопределённой несовместной или недоопределённой системы линейных уравнений методом максимума энтропии Фридена.
35. Псевдорешение переопределённой несовместной или недоопределённой системы линейных уравнений методом максимума правдоподобия Тараско.
36. Псевдорешение переопределённой несовместной или недоопределённой системы линейных уравнений методами проекций Качмажа, Бочека, Танабе, Горшкова. Нахождение её же собственных значений этими же методами.
37. Псевдорешение переопределённой несовместной или недоопределённой системы линейных уравнений методом совмещения итерационных решения и ортогонализации Абрамова.
38. Решение неособенной или псевдорешение особенной системы нелинейных уравнений методом градиентного спуска.
39. Решение неособенной или псевдорешение особенной системы нелинейных уравнений методом наискорейшего дихотомического спуска.
40. Решение неособенной или псевдорешение особенной системы нелинейных уравнений методом  наискорейшего дихотомического спуска в направлении Монте-Карло.
41. Деконволюция свёртки методами: Фурье, Хартли, Котельникова, Уолша, экспоненциальным вейвлетным, Качмажа, Бочека, Танабе, Фридена, Тараско, Абрамова, Горшкова, методами спуска с регуляризацией Тихонова.
42. Решение классических разностных схем систем дифференциальных уравнений первой и высших степеней одной и многих переменных классическими методами (Эйлера, Рунге-Кутты, Годунова, Рябенького, Самарского и многих др.).
43. Решение классических разностных схем систем дифференциальных уравнений первой и высших степеней одной и многих переменных итерационным методом алгоритмами Качмажа, Бочека, Танабе, Фридена, Тараско, Абрамова, Горшкова.
44. Решение классических разностных схем систем дифференциальных уравнений первой и высших степеней одной и многих переменных методом крупных частиц Белоцерковского.
45. Решение классических разностных схем систем дифференциальных уравнений первой и высших степеней одной и многих переменных методом независимых частиц Монте-Карло.
46. Экстраполяция аналитических последовательностей классическими методами.
47. Экстраполяция аналитических последовательностей итерационным методом алгоритмами Качмажа, Бочека, Танабе, Фридена, Тараско, Абрамова, Горшкова.
48. Решение жёстких систем нелинейных уравнений химической кинетики методом Горшкова.
49. Сверхразрешение некогерентных сигналов до предела Косарева.
50. Сверхразрешение некогерентных изображений до предела Косарева.
51. Решение типовых математических задач реконструктивной томографии.

СТРОКИ
Строки – это упакованные массивы символов (знаков). В строке может быть от 0 (пустая строка) до 255 знаков.
Строки бывают:
1. с нефиксированным, переменным, занимаемым в памяти объёмом (объявляются просто string);
2. и с фиксированным занимаемым в памяти объёмом (объявляются  с указанием длины string[ДлинаЗначащих]).
Примечание: строки string[ДлинаЗначащих] , как и строки string , могут содержать значащие символы в переменном количестве, но всё-таки в пределах от 0  до максимально допустимого для них =ДлинаЗначащих.
Строки занимают в памяти на 1 байт больше, чем их длина, т.е. от 1 до 256 байт. По расположению этого "служебного" байта строки с нефиксированной длиной бывают:
• Борланд-строки –  служебный байт располагается в начале и его значение (0..255) определяет фактичекую длну строки. Борланд-строки есть в Т-, Б- и О-Паскале.
• Майкрософт-строки – в Б- и О-Паскале дополнительно есть ещё и тип PChar – "строки с нуль-окончанием" (ASCIIZ-strings), где символом с кодом #0 (т.е. chr($00) ) заканчивается значащая часть строки. Сие извращение введено с целью совместимости с MS Windows. Недостатком Майкрософт-строки является то, что символ chr($00) невозможно использовать в значащей части. Принципиальных достоинств у Майкрософт-строки нет.
Пример строки:
s:='Строка символов';
Может быть и "пустая строка" (обозначается двумя апострофами подряд):
s:='';
К отдельным элементам строки (символам) тоже можно обращаться, так же, как к элементам массива (символов), то есть по их индексам: ИмяСтроки[ИндексЭлементаСтроки].
В Т-Паскале строки объявляются словом string, а в О-Паскале тип длиной до 255 знаков называется ShortString. В О-Паскале тип string  обладает почти неограниченной ёмкостью (память распределяется динамически, а резервируется только 4 байта под указатель на её начало); есть ещё строки WideString (похож на String, но отличается тем, что для представления каждого символа используется не один, а 2 байта), которые введены для совместимости со "связываемыми и внедряемыми"  (OLE-) объектами Windows.
В Т-Паскале строки можно соединять оператором сложения.
В О-Паскале строки можно сравнивать между собой (сравниваются они посимвольно) обычными операторами сравнения (см. выше). В стандартных модулях Т-, Б- и О-Паскаля определены также часто используемые функции и процедуры для работы со строками: Concat (соединение), Copy (взять подстроку), Delete (удалить подстроку), Insert (вставить подстроку), Length (длина строки), Pos(найти место подстроки), SetLength, Str (преобразовать число в строку), Val (преобразовать строку в число), StrToDateTime, DateTimeToStr, FormatDateTime и многие другие.
Примеры строк Т-Паскаля:
var
        s                :string;
    help                :string[80];
    Name,Otch,Fam:string[10];
    Buk                :char;
begin
    help:='Караул !!! ';
     writeln(help, ' Введите фамилию, имя, отчество:');
     readln(Name);
     readln(Otch);
     readln(Fam);
    writeln('Первая буква имени - ',Name[1]);
    writeln('В милицию обращался гражданин ',Fam,'   , а точнее,  ',Name+' '+Otch+' '+Fam);
   readln;
end.

Обращаем внимание читателей на то, что в Delphi (О-Паскаль) оба противоположных типа – и String, и PChar – совместимы с символьными массивами с нулевой нижней границей array [0..N] of char. Функция PChar(Строка) преобразует строку типа String в тип PChar, а функция String(СтрокаСНульОкончанием) преобразует строку PChar в тип String.

Пример того, как переставить местами знаки в строке  задом наперёд:
uses
crt;
var
i,L:integer;
ch:char;
s:string;
begin
s:='Алексей';
writeln(s);
L:=length(s);
for i:=1 to (L div 2) do begin
ch:=s[i];
s[i]:=s[L-i+1];
s[L-i+1]:=ch;
end;
writeln(s);
repeat until keypressed;
end.

Примеры других процедур и функций работы со строками:


(продолжение следует)


Рецензии