Функции ОС, интерфейс пользователя

advertisement
Функции ОС, интерфейс пользователя.
Операционная система, ОС (англ. operating system) — базовый комплекс
компьютерных программ, обеспечивающий управление аппаратными средствами
компьютера, работу с файлами, ввод и вывод данных, а также выполнение прикладных
программ и утилит.
Операционная система – это комплект программ, правил и специальных данных,
которые совместно управляют ресурсами ЭВМ и процессами, использующими эти
ресурсы в своей работе.
Операционная система (ОС)
1.
это набор программ, обеспечивающих совместное функционирование всех
устройств компьютера и предоставляющий доступ к его ресурсам
2.
это системное программное обеспечение, т.е. программы, управляющие ОП,
процессором, внешними устройствами и файлами и прикладными программами, и
ведущие диалог с пользователем.
Состав ОС:
Программный модуль, управляющий файловой системой - Процесс работы
компьютера в сводится к обмену файлами между устройствами
Командный процессор – специальная программа, которая запрашивает у
пользователя команды и выполняет их. Пользователь может дать команду запуска
программы, выполнения какой-либо операции над файлами (копирование, удаление,
переименование), вывода документа на печать и так далее. Операционная система должна
эту команду выполнить.
Драйверы – программы, которые управляют работой устройств. Каждому
устройству соответствует свой драйвер. Технология «Plug and Play» (подключи и играй)
позволяет автоматизировать подключение новых устройств. В процессе установки
Windows определяет тип и конкретную модель установленного устройства и подключает
необходимый для его функционирования драйвер. При включении компьютера
производится загрузка драйверов в оперативную память. Пользователь имеет
возможность вручную установить или переустановить драйверы.
Программные модули графического интерфейса – программы, позволяющие
пользователю вводить команды с помощью мыши.
Утилиты – сервисные программы для обслуживания дисков (проверять, сжимать,
дефрагментировать и тд), выполнения операций с файлами (архивировать, копировать и
тд), и работы в компьютерных сетях.
Справочная система – получение информации о функционировании ОС в целом и о
работе её отдельных модулей.
Файлы ОС хранятся во внешней, долговременной памяти (на жестком, гибком или
лазерном диске). Но программы могут выполняться, только если они находятся в
оперативной памяти, поэтому файлы ОС необходимо загрузить в оперативную память.
При включении компьютера операционная система загружается в память раньше
остальных программ и затем служит платформой и средой для их работы. Помимо
вышеуказанных функций ОС может осуществлять и другие, например, предоставление
пользовательского интерфейса, сетевое взаимодействие и т. п.
С 1990-х наиболее распространёнными операционными системами для
персональных компьютеров и серверов являются ОС семейства Microsoft Windows и
Windows NT, Mac OS и Mac OS X, системы класса UNIX (особенно GNU/Linux).
По современным представлениям, ОС должна иметь следующие функции:
1
Обеспечивать загрузку пользовательских программ в оперативную память и их
исполнение.
Обеспечивать работу с устройствами долговременной памяти, такими как
магнитные диски, ленты, оптические диски и т.д. Как правило, ОС управляет
свободным пространством на этих носителях и структурирует пользовательские
данные.
Предоставлять более или менее стандартный доступ к различным устройствам
ввода/вывода, таким как терминалы, модемы, печатающие устройства.
Предоставлять некоторый пользовательский интерфейс. Слово некоторый здесь
сказано не случайно - часть систем ограничивается командной строкой, в то время
как другие на 90% состоят из средств интерфейса пользователя.




Важнейшими функциями ОС являются:
1.
2.
3.
4.
5.
Управление элементами, блоками и устройствами ПЭВМ. Выполняется с
помощью набора специальных управляющих программ – драйверов устройств.
Центральная часть операционной системы, так называемое ядро ОС, обязательно
содержит драйверы всех основных устройств ЭВМ. Дополнительные устройства
устанавливаются в вычислительную систему вместе со своим драйвером, обычно
поставляемым вместе с аппаратными средствами.
Обеспечение хранения и доступа к информации (файловая система). Сюда входят
правила организации и размещения наборов данных во внешней памяти и правила
обращения к внешним устройствам, через которые производится передача
данных. В основе лежит так называемая Базовая Система Ввода/Вывода (BIOS).
Выделение ресурсов ПЭВМ (памяти, процессорного времени, внешних
устройств) для выполняемых процессов (управление ресурсами). Это наиболее
сложная функция операционных систем. В зависимости от того, как
распределяются ресурсы ЭВМ, определяется тип ОС и ее возможности.
Организация взаимодействия между выполняемыми процессами (система
прерываний). Данная система позволяет с одной стороны достаточно
универсально обеспечивать все виды передач управления, с другой – управлять
работой компьютера в диалоговом режиме, независимо от выполняемых в
текущий момент программ.
Выполнение команд пользователя по управлению ЭВМ. Для этих целей в составе
операционной системы имеется "командный процессор" – резидентно
загруженная программа, интерпретирующая указания человека, вводимые в ЭВМ
в различной форме. Чаще всего эти указания являются набранной командой в
виде текста, или выбором команды из предлагаемого меню (графического или
текстового вида).
Более развитые ОС предоставляют также следующие возможности:






2
Параллельное (точнее, псевдопараллельное, если машина имеет только один
процессор) исполнение нескольких задач.
Распределение ресурсов компьютера между задачами.
Организация взаимодействия задач друг с другом.
Взаимодействие пользовательских программ с нестандартными внешними
устройствами.
Организация межмашинного взаимодействия и разделения ресурсов.
Защита системных ресурсов, данных и программ пользователя, исполняющихся
процессов и самой себя от ошибочных и зловредных действий пользователей и их
программ.




управление памятью, связанное с распределением оперативной памяти между
прикладными программами.
управление файлами; основными задачами при этом являются обеспечение
защиты, управление выборкой и сохранение секретности хранимой информации.
обработка исключительных условий во время выполнения задачи (появление
арифметической или машинной ошибки, прерываний, связанных с неправильной
адресацией или выполнением привилегированных команд.).
Разграничение прав доступа и многопользовательский режим работы
(аутентификация, авторизация).
Аутентификация (англ. Authentication) или подтверждение подлинности —
процедура проверки соответствия субъекта и того, за кого он пытается себя выдать, с
помощью некой уникальной информации, в простейшем случае — с помощью имени и
пароля.
Авторизация (англ. Authorization) — процесс, а также результат процесса проверки
необходимых параметров и предоставление определённых полномочий лицу или группе
лиц (прав доступа) на выполнение некоторых действий в различных системах с
ограниченным доступом.
Слово интерфейс (от англ. interface — поверхность раздела, перегородка) в общем
случае определяет место или способ соединения/соприкосновения/связи.
Интерфейс пользователя
Интерфейс пользователя — это совокупность средств, при помощи которых
пользователь общается с различными устройствами
1. Интерфейс командной строки: инструкции компьютеру даются путём ввода с
клавиатуры текстовых строк (команд).
2. Графический интерфейс пользователя: программные функции представляются
графическими элементами экрана.
3. Диалоговый интерфейс
4. Естественно-языковой интерфейс: пользователь «разговаривает» с программой на
родном ему языке.
Операционная система реализует связи между аппаратными средствами,
программами и пользователями. В информатике для описания таких связей используется
понятие "интерфейс".
Интерфейс – это средство сопряжения двух систем или частей системы, в котором
все физические и логические параметры отвечают предварительным соглашениям.
Интерфейс командной строки
Интерфейс командной строки — разновидность текстового интерфейса человека и
компьютера, в котором инструкции компьютеру даются только путём ввода с клавиатуры
текстовых строк (команд). Также известен под названием консоль.
Интерфейс командной строки противопоставляется системам управления
программой на основе меню, а также различным реализациям графического интерфейса.
Назначение:
На устройстве-консоли, которое печатало текст на бумаге, интерфейс командной
строки был единственным возможным. На видеотерминалах интерфейс командной строки
применяется по таким причинам:
1. Небольшой расход памяти по сравнению с системой меню.
2. В современном программном обеспечении имеется большое число команд, многие
из которых нужны крайне редко. Поэтому даже в некоторых программах с
графическим интерфейсом применяется командная строка: набор команды (при
условии, что пользователь знает эту команду) осуществляется гораздо быстрее,
чем, например, навигация по меню.
3
Естественное расширение интерфейса командной строки — пакетный интерфейс.
Его суть в том, что в файл обычного текстового формата записывается
последовательность команд, после чего этот файл можно выполнить в программе,
что возымеет такой же (не меньший) эффект, как если бы эти команды были по
очереди введены в командную строку.
Достоинства:
1. Любую команду можно вызвать небольшим количеством нажатий.
2. Пакетные файлы — это, по сути, простейшая программируемость.
3. Можно управлять программами, не имеющими графического интерфейса
(например, выделенным сервером).
4. Просмотрев содержимое консоли, можно повторно увидеть промелькнувшее
сообщение, которое вы не успели прочитать.
Недостатки:
1. Интерфейс командной строки не является дружественным для начинающих.
2. Искать неизвестную команду по справочникам не менее сложно, чем отыскивать в
меню нужную команду.
3. Ввод некоторых параметров с клавиатуры может быть затруднительным.
3.
Графический интерфейс пользователя (ГИП, англ. graphical user interface, GUI) в
вычислительной технике — система средств для взаимодействия пользователя с
компьютером, основанная на представлении всех доступных пользователю системных
объектов и функций в виде графических компонентов экрана (окон, значков, меню,
кнопок, списков и т. п.). При этом, в отличие от интерфейса командной строки,
пользователь имеет произвольный доступ (с помощью клавиатуры или устройства
координатного ввода типа "мышь") ко всем видимым экранным объектам.
4
Файловая структура. Диски, файлы, их имена.
Файловой структуры — способа однозначной адресации определённой совокупности
данных (файла) в ОС.
Файловой системы — физической организации дискового пространства,
соответствующей файловой структуре или её части (т.е. это порядок хранения и
организации файлов на диске).
Виды файловой структуры:
1. Одноуровневая ФС — линейная последовательность имен файлов, используется
для дисков с небольшим количеством файлов;
2. Многоуровневая иерархическая ФС — представляет собой древовидную
структуру, служит для хранения сотни и тысячи файлов. Каталог (Папка) верхнего
уровня содержит вложенные папки 1уровня, которые могут содержать папки 2
уровня и т.д.
Для хранения информации каждый диск разбивается на 2 области:
1. каталог (directory) или папка — содержит названия файлов и указание на начало их
размещения на диске;
2. область хранения файлов, содержит текст.
Широкое распространение на мини-ЭВМ и ПК, имеющих жесткие диски большой
емкости, получили так называемые файловые системы, представляющие собой
совокупность каталогов и файлов, хранимых на внешних носителях.
Файл — это поименованная область на внешнем носителе (диске или магнитной
ленте), в которой может храниться исходный текст программы, программы в машинном
коде, готовые к исполнению, или данные для ее работы. В файлах могут содержаться
любые текстовые документы и числовые данные, закодированная табличная графическая
и любая другая информация. Имя файла, как правило, содержит расширение,
указывающее на его тип (исходный текст, объектный модуль, исполнимая программа,
документ и т.п.).
Файл может иметь любое название. Название файла состоит из имени и
необязательного его расширения. Расширение отделяется от имени точкой. Разрешены
только буквы, цифры, а также символы &$#@!%(){}'~^. В операционной системе MSDOS имя файла не должно быть длиннее 8 символов. Расширение имени не должно быть
длиннее 3 символов. Расширение используется для удобства определения типа
информации, хранящейся в файле.
В операционной системе MS-DOS операции с файлами (копирование, удаление,
переименование, печать и т. д.) можно производить непосредственно из командной
строки с помощью команд (copy, delete, rename, print). Однако это неудобно для
пользователя, так как требует запоминания форматов команд операционной системы. Для
работы с файлами обычно используется программная оболочка Norton Commander,
которая представляет пользователю удобные возможности поиска файлов и операций над
ними с помощью функциональных клавиш и мыши.
Каталоги
Поскольку на диске может храниться несколько десятков тысяч файлов, чтобы
упорядочить работу с ними, файлы группируются в каталоги (папки). Внутри одного
каталога (папки) могут находиться другие вложенные каталоги.
Так же как и файл, каталог имеет название и атрибуты. На диске имеется корневой
каталог, в котором могут размещаться другие каталоги (подкаталоги) и файлы. Внутри
каждого каталога может быть множество других каталогов или файлов. Два одинаковых
имени не могут располагаться на одном иерархическом уровне.
Каталог (директория) — это оглавление, содержащее информацию о файлах (имя,
расширение, размеры в байтах, дату время создания и т.д.) и другие каталоги, называемые
5
подкаталогами (подчиненные каталоги). Так образуется иерархическая древовидная структура, в
основании которой находится корневой каталог.
Такая структура дает возможность выделить:
1. в отдельные группы логически однородные файлы;
2. отдельное пространство на диске для каждого из пользователей данной ЭВМ;
3. все файлы, относящиеся к какой-либо подсистеме, текстовому редактору, транслятору
языка и т.п.
Кроме перечисленного, каталоги обеспечивают защиту файлов и их быструю визуализацию,
исключив работу с очень большим списком в случае единого описания.
Диск и каталог, с которыми вы работаете в данный момент времени, называются
текущими.
Для точного указания места расположения файла используют его полное имя
(полный путь к файлу), которое складывается из названия диска, названий каталогов и
файла, разделенных символом"\". Например, B:\SERV\MOUSE\GMOUSE.COM. Если
диск B: в настоящее время является текущим, его название можно не указывать.
Аналогично, если текущим каталогом является каталог "SERV", предыдущую запись
можно представить в виде MOUSE\GMOUSE.COM.
Если название каталога начинается с символа "\", значит, отсчет ведется от корневого
каталога.
Символ "." вместо названия каталога в полном пути к файлу указывает на текущий
каталог, а символы ".." - на родительский для текущего каталог, то есть каталог,
расположенный на один уровень выше текущего.
6
Основные команды MS DOS. Команды работы с каталогами.
MS-DOS (сокр. от англ. Microsoft Disk Operating System — дисковая ОС от Microsoft)
— коммерческая операционная система для персональных компьютеров фирмы
Microsoft. MS-DOS — самая известная ОС из семейства DOS, ранее устанавливаемая на
большинство PC-совместимых компьютеров. Со временем она была вытеснена Microsoft
Windows, и позже Windows NT.
MS-DOS была выпущена в 1981 году и вышла в восьми версиях, пока Microsoft не
прекратила её разработку в 2000 году. Это был ключевой продукт фирмы, дававший ей
существенный доход и маркетинговый ресурс, в ходе развития Microsoft от разработчика
языка программирования до крупной компании, производящей самое разнообразное
программное обеспечение.
MS-DOS расшифровывается как дисковая операционная система. Операционная
система - это программа, координирующая действия вычислительной машины; под ее
управлением осуществляется выполнение программ. MS-DOS - операционная система,
расположенная на дисках. Разработчиком MS-DOS является Корпорация Microsoft.
Три основные функции операционной системы:
1. Обмен данными между компьютером и различными периферийными
устройствами (терминалами, принтерами, гибкими дисками, жесткими дисками и
т.д.). Такой обмен данными называется "ввод/вывод данных".
2. Обеспечение системы организации и хранения файлов.
3. Загрузка программ в память и обеспечение их выполнения.
Основные понятия
Вся информация, хранящаяся в ПК, размещается в файлах. Для обращения к файлу
используется имя файла.
ИМЯ ФАЙЛА: имя.тип
имя - может содержать латинские буквы, цифры и знаки подчеркивания, не более 8
символов;
тип - может содержать латинские буквы, цифры и знаки подчеркивания, не более 3
символов. Тип или расширение могут отсутствовать.
Стандартные типы файлов:
*.bat- командные файлы
*.exe - загрузочные файлы
*.com - загрузочные файлы
Прочие файлы:
*.txt - текстовые файлы
*.doc - текстовые файлы
*.dbf - файл базы данных
*.sys - системные файлы
*.bak - страховочный файл
Независимо от версий, работу DOS обеспечивают следующие 3 компонента:
1. базовая система ввода-вывода (BIOS) (или RIOS). Записанная в ПЗУ
программа поставляется производителями ЭВМ и выполняет функцию
обеспечения нормального функционирования: проверка комплектности,
тестирование различных устройств ПК, инициализация загрузки DOS и ряд других
функций. Эта программа не является файлом и фактически не входит в состав
QOS;
2. ядро DOS содержит в виде скрытых файлов: блок первоначальной загрузки
(bootstrap), располагаемый в первом секторе системного диска (считываемый с
помощью BIOS) и обеспечивающий загрузку в память машины операционной
системы — IO.SYS (или IBM BIO.COM), так называемую базовую систему вводавывода с программным обслуживанием периферийных устройств (расширение и
исправление BIOS), а также файл MS DOS.SYS (IBM D0S.COM), содержащий
программы управления файлами, памятью, запуском программ и т. д. Этот файл
7
иногда называется модулем управления прерываниями, поскольку обращение к
программным средствам (функциям DOS) из программы пользователя
осуществляется с помощью программных прерываний;
3. файл C0MMAND.COM, или командный процессор (интерпретатор), в
функции которого входит прием, проверка команд, вводимых пользователем с
клавиатуры, и их выполнение. Существует 3 категории команд DOS —
резидентные или внутренние, постоянно находящиеся в ОП, полурезидентные,
которые могут (по мере необходимости) «затираться» прикладными программами,
и внешние, вызываемые по мере необходимости из внешней памяти.
Команды MS DOS бывают двух типов:
1. Внутренние команды, их выполняет командый процессор COMMAND.COM
(например, dir, copy).
2. Внешние команды - программы, поставляемые вместе с ОС в виде отдельных
файлов. Они размещаются на диске и выполняют действия обслуживающего
характера (например, форматирование диска, очистка экрана, проверка диска).
Команды состоят из имени команды и, возможно, параметров, разделенных
пробелами. Скобками будут отмечены необязательные элементы команд.
Работа с файлами
Создание текстовых файлов copy con имя_файла. После ввода этой команды нужно
будет поочередно вводить строки файла. В конце каждой строки надо щелкать клавишей
Enter. А после ввода последней - одновременно нажать Ctrl и Z, а затем Enter.
Удаление файлов del (путь) имя_файла. Путь прописывается только тогда, когда
удаляемый файл находится в другом каталоге.
Переименование файлов ren (путь)имя_файла1 имя_файла2. Имя_файла1 - имя
файла, который вы хотите переименовать, имя_файла2 - новое имя файла, которое будет
ему присвоено после выполнения команды.
Копирование файлов copy имя_файла (путь)имя_файла1.
Copy games.txt games копировать файл games.txt в подкаталог GAMES текущего
диска.
Работа с каталогами
Команда смены текущего диска A: - переход на диск А.
Просмотр каталога dir (путь) (имя_файла) (/p) (/w).
Если не введены путь и имя файла, то на экран выведется информация о
содержимом каталога (имена файлов, их размер и дата последнего изменения).
Параметр /p задает вывод информации в поэкранном режиме, с задержкой до тех
пор, пока пользователь не щелкнет по какой-либо клавише. Это удобно для больших
каталогов, /w - задает вывод информации только об именах файлов в каталоге по пять
имен в строке.
Изменение текущего каталога cd путь.
Создание каталога md путь.
Удаление каталога rd путь.
Примеры:
dir - вывести оглавление текущего каталога;
dir*.exe - вывести сведения о всех файлах с расширением .exe из текущего каталога;
dir a: - вывести оглавление корневого каталога диска а:.
cd games - переход в каталог GAMES текущего диска;
cd.. - переход в предыдущий каталог;
cd - переход в корневой каталог текущего диска.
rd games - удаление подкаталога GAMES в текущем каталоге;
ВНИМАНИЕ! УДАЛИТЬ МОЖНО ТОЛЬКО ПУСТОЙ КАТАЛОГ!
Командная строка
Это строка, которую вы увидите на экране после загрузки MS DOS. Она называется
еще приглашением DOS и имеет вид, например, такой
C:\> ,
8
здесь C: - имя диска; > - символ приглашения, после которого мерцает курсор,
указывая место, куда надо ввести команду.
Другие команды.
Date - вывод информации о дате с возможностью настройки.
Time - вывод информации о времени с возможностью настройки.
Verify on - включить режим проверки записи на диск.
Verify of - выключить режим проверки записи на диск.
Verify - вывести информацию о том, включен ли режим проверки записи на диск.
Path - определяет порядок поиска наиболее часто запускаемых программ.
Ver - показывает версию операционной системы.
Cls - производит очистку экрана.
Label - выводит информацию о метке диска с возможностью её изменения.
9
Структура и общие принципы построения программы в Turbo
Pascal. Алфавит. Константы. Переменные.
Общая структура программ на языке Паскаль
Программы на Паскале имеют такой общий вид:
Program Имя программы
Раздел описаний
Begin
Раздел операторов
End.
Слова PROGRAM, BEGIN и END выделяют 2 части программы: раздел описаний и
раздел операторов. Такая структура обязательна. Любой объект, используемый в
программе, должен быть учтен в разделе описаний.
Программа, написанная по правилам стандартного языка Паскаль, должна иметь в
своем полном варианте следующую структуру:
Program имя программы;
Uses Список используемых модулей
Label Список меток из основного блока программы
Const Определение констант программы
Type Описание типов
Var Описание переменных
Procedure Текст процедуры
Function Текст функции
Begin
Основной блок программы
(раздел операторов)
End.
Синтаксис и семантика
Описание каждого элемента языка задается его синтаксисом и семантикой.
Синтаксические определения устанавливают правила построения элементов языка.
Семантика определяет смысл и правила использования тех элементов языка, для которых
были даны синтаксические определения.
Алфавит языка
Алфавит - это совокупность допустимых в языке символов. Алфавит Турбо Паскаль
включает следующий набор основных символов:

















10
строчные и прописные латинские буквы: A B C D E F G H I J K L M N O P Q R S T
U V W X Y Z; a b c d e f g h i j k l m n o p q r s t u v w x y z;
пробел
подчеркивание: _
арабские цифры: 0 1 2 3 4 5 6 7 8 9
знаки операций: + - * / = <> < > <= >= := @
ограничители: . , ' ( ) [ ] (. .) { } (* *) .. : ;
спецификаторы: ^ # $
служебные (зарезервированные) слова:
ABSOLUTE
ASSEMBLER
AND
ARRAY
ASM
ASSEMBLER
BEGIN
CASE
CONST
EXPORTS
EXTERNAL
FAR
FILE
FOR
FORWARD
FUNCTION
GOTO
IF
LIBRARY
MOD
NAME
NIL
NEAR
NOT
OBJECT
OF
OR
SET
SHL
SHR
STRING
THEN
TO
TYPE
UNIT
UNTIL








CONSTRUCTOR
DESTRUCTOR
DIV
DO
DOWNTO
ELSE
END
EXPORT
IMPLEMENTATION
IN
INDEX
INHERITED
INLINE
INTERFACE
INTERRUPT
LABEL
PACKED
PRIVATE
PROCEDURE
PROGRAM
PUBLIC
RECORD
REPEAT
RESIDENT
USES
VAR
VIRTUAL
WHILE
WITH
XOR
Элементарные конструкции
Элементарные конструкции языка Паскаль включают в себя имена, числа и строки.
Имена (идентификаторы) называют элементы языка - константы, метки, типы,
переменные, процедуры, функции, модули, объекты.
Идентификатор в Турбо Паскале может включать в себя:
1. буквы латинского алфавита,
2. цифры
3. символ подчеркивания.
Строчные и прописные буквы не. Цифра не может стоять на первом месте в
идентификаторе, а символ подчеркивания может находиться в любой позиции (например,
name1 и name2item являются допустимыми идентификаторами, а 5name - нет; _name,
name_, name_item - тоже допустимые названия). Длина идентификатора может быть
любой, но значимыми являются только первые 63 символа. В качестве имен не
допускается использовать служебные слова.
Для отделения друг от друга идентификаторов, чисел, зарезервированных слов
используются разделители. В качестве них можно использовать:
1. пробел и табуляцию;
2. перевод строки;
3. комментарий.
В любом месте программы, где можно поместить один разделитель, их можно
поместить любое количество и в любом сочетании, что позволяет наглядно представить
структуру программы.
Комментарии заключаются либо в скобки { ... }, либо в скобки вида (* ... *) и могут
занимать любое число строк.
Числа в языке Паскаль обычно записываются в десятичной системе счисления. Они
могут быть целыми и действительными. Положительный знак числа может быть опущен.
Целые числа записываются в форме без десятичной точки, например:
217
-45
8954
+483
Действительные числа записываются в форме с десятичной точкой:
28.6
0.65
-0.018
4.0
Возможна также запись с использованием десятичного порядка, который изображается
буквой Е:
5Е12
-1.72Е9
73.1Е-16
В "переводе" такую запись следует понимать соответственно как:
5x1012
-1.72x109
73.1x10-16
Паскаль допускает запись целых чисел и фрагментов действительных чисел в форме с
порядком в шестнадцатеричной системе счисления:
$7F
$40
$ABC0
Строки в языке Паскаль - это последовательность символов, записанная между
апострофами. Если в строке в качестве содержательного символа необходимо употребить
сам апостроф, то следует записать два апострофа. Примеры строк: 'СТРОКА' 'STRING'
'ПРОГРАММА'.
Переменной называют элемент программы, который предназначен для хранения,
коррекции и передачи данных внутри программы. Все переменные программы в Турбо
Паскаль должны быть объявлены в разделе описания переменных (см. далее).
Наряду с переменными в программах используются и константы. Константа - это
идентификатор, обозначающий некоторую неизменную величину определенного типа.
11
Константы, как и переменные, должны объявляться в соответствующем разделе
программы.
В Турбо Паскаль применяется несколько стандартных видов констант:





12
Целочисленные константы. Могут быть определены посредством чисел,
записанных в десятичном или шестнадцатеричном формате данных. Это число не
должно содержать десятичной точки.
Вещественные константы. Могут быть определены числами, записанными в
десятичном формате данных с использованием десятичной точки.
Символьные константы. Могут быть определены посредством некоторого
символа (заключенного в апострофы).
Строковые константы. Могут быть определены последовательностью
произвольных символов (заключенных в апострофы).
Типизированные константы. Представляют собой инициализированные
переменные, которые могут использоваться в программах наравне с обычными
переменными. Каждой типизированной константе ставится в соответствие имя, тип
и начальное значение. Например: year: integer = 2001; symb: char = '?';money: real =
57.23;
Типы данных в Turbo Pascal. Порядковый, вещественный,
структурированный. Совместимость и преобразование типов.
Типы данных
Для обработки ЭВМ данные представляются в виде величин и их совокупностей. С
понятием величины связаны такая важная характеристика, как ее тип.
Тип определяет:



возможные значения переменных, констант, функций, выражений, принадлежащих
к данному типу;
внутреннюю форму представления данных в ЭВМ;
операции и функции, которые могут выполняться над величинами,
принадлежащими к данному типу.
В языке Паскаль тип величины задают заранее. Все переменные, используемые в
программе, должны быть объявлены в разделе описания с указанием их типа.
Обязательное описание типа приводит к избыточности в тексте программ, но такая
избыточность является важным вспомогательным средством разработки программ и
рассматривается как необходимое свойство современных алгоритмических языков
высокого уровня.
Иерархия типов в языке Паскаль такая:



Простые
o Порядковые
 Целые
 Логические
 Символьные
 Перечисляемые
 Интервальные
o Вещественные
Структуированные
o Массивы
o Строки
o Множества
o Записи
o Файлы
Указатели
Простые типы данных
В таблице приведены простые типы данных Турбо Паскаль, объем памяти,
необходимый для хранения одной переменной указанного типа, множество допустимых
значений и применимые операции.
Идентификатор Длина (байт)
Диапазон значений
Операции
Целые типы
+, -, /, *, Div, Mod,
integer
2
-32768..32767
>=, <=, =, <>, <, >
+, -, /, *, Div, Mod,
byte
1
0..255
>=, <=, =, <>, <, >
+, -, /, *, Div, Mod,
word
2
0..65535
>=, <=, =, <>, <, >
13
+, -, /, *, Div, Mod,
>=, <=, =, <>, <, >
+, -, /, *, Div, Mod,
longint
4
-2147483648..2147483647
>=, <=, =, <>, <, >
Вещественные типы
+, -, /, *,
real
6
2,9x10-39 - 1,7x1038
>=, <=, =, <>, <, >
+, -, /, *,
single
4
1,5x10-45 - 3,4x1038
>=, <=, =, <>, <, >
+, -, /, *,
double
8
5x10-324 - 1,7x10308
>=, <=, =, <>, <, >
+, -, /, *,
extended
10
3,4x10-4932 - 1,1x104932
>=, <=, =, <>, <, >
Логический тип
Not, And, Or, Xor,
boolean
1
true, false
>=, <=, =, <>, <, >
Символьный тип
+,
char
1
все символы кода ASCII
>=, <=, =, <>, <, >
Порядковые типы, выделяемые из группы простых типов, характеризуются
следующими свойствами:
shortint




1
-128..127
все возможные значения порядкового типа представляют собой ограниченное
упорядоченное множество;
к любому порядковому типу может быть применена стандартная функция Ord,
которая в качестве результата возвращает порядковый номер конкретного значения
в данном типе;
к любому порядковому типу могут быть применены стандартные функции Pred и
Succ, которые возвращают предыдущее и последующее значения соответственно;
к любому порядковому типу могут быть применены стандартные функции Low и
High, которые возвращают наименьшее и наибольшее значения величин данного
типа.
В языке Паскаль введены понятия эквивалентности и совместимости типов. Два типа
Т1 и Т2 являются эквивалентными (идентичными), если выполняется одно из двух
условий:






Т1 и Т2 представляют собой одно и то же имя типа;
тип Т2 описан с использованием типа Т1 с помощью равенства или
последовательности равенств. Например:
type
T1 = Integer;
T2 = T1;
T3 = T2;
Менее строгие ограничения накладываются на совместимость типов. Так, типы
являются совместимыми, если:



14
они эквивалентны;
являются оба либо целыми, либо действительными;
один тип - интервальный, другой - его базовый;


оба интервальные с общим базовым;
один тип - строковый, другой - символьный.
В Турбо Паскаль ограничения на совместимость типов можно обойти с помощью
приведения типов. Приведение типов позволяет рассматривать одну и ту же величину в
памяти ЭВМ как принадлежащую разным типам. Для этого используется конструкция
Имя_Типа(переменная или значение)
Напрмер, Integer('Z') представляет собой значение кода символа 'Z' в двухбайтном
представлении целого числа, а Byte(534) даст значение 22, поскольку целое число 534
имеет тип Word и занимает два байта, а тип Byte занимает один байт, и в процессе
приведения старший байт будет отброшен.
15
Имена и доступ к файлам в Turbo Pascal.
Под файлом понимается либо именованная область внешней памяти ПК (жесткого
диска, гибкой дискеты, электронного «виртуального» диска), либо логическое устройство
- потенциальный источник или приемник информации.
Любой файл имеет три характерные особенности. Во-первых, у него есть имя, что
дает возможность программе работать одновременно с несколькими файлами. Во-вторых,
он содержит компоненты одного типа. Типом компонентов может быть любой тип Турбо
Паскаля, кроме файлов. Иными словами, нельзя создать «файл файлов». В-третьих, длина
вновь создаваемого файла никак не оговаривается при его объявлении и ограничивается
только емкостью устройств внешней памяти.
Имя каждого файла хранится в каталоге диска (в оглавлении диска). Полное имя
файла состоит из 2-х частей: основного имени и расширения. Расширение отделяется от
основного имени точкой: основное имя.расширение
например, "myfile.txt"
Основное имя может состоять не более чем из 8-ми. Расширение может состоять не
более чем из 3-х символов, оно указывает на тип информации, хранимой в файле. Если
расширение используется, то лучше давать ему общепринятое название:
.ASM - в файле хранится текст программы, написанной на Ассемблере;
.BAS - текст программы на Бэйсике;
.PAS - текст программы на Паскале;
.C - текст программы на языке "Си".
.TXT, .DOC - текстовые файлы произвольной тематики;
.DAT - файл данных (исходные данные для программы, либо результаты расчета);
.BAK - резервная копия файла, старая версия модифицированного файла (если файл
записывается на диск, на котором уже хранится записанный ранее одноименный файл,
то старая версия файла не стирается, вместо этого в ее имени расширение
автоматически меняется на ".bak");
.BAT - пакетный файл - программа, состоящая из команд DOS;
.EXE, .COM - файлы, содержащие программы, представленные в машинных кодах
(результат трансляции программ, написанных на алгоритмических языках).
В основном имени файла и в расширении допускается использовать латинские
буквы, цифры и некоторые символы - тире, подчеркивание, скобки, русские буквы и
пробелы. Нет различия между строчными и прописными буквами.
В каталог диска кроме имен файлов могут также входить другие каталоги
(подкаталоги первого уровня), которые в свою очередь могут включать в себя как файлы,
так и каталоги (подкаталоги 2-го уровня). Таким образом формируется "древовидная"
структура каталогов, имеющая на самом верхнем уровне единственный главный каталог
(корневой каталог), к которому сходятся многочисленные ветви подкаталогов. Каталогам,
как и файлам, даются имена (корневой каталог остается безымянным). Требования к
именам каталогов предъявляются те же, что и к именам файлов, но расширение обычно не
используется.
Файловый тип или переменную файлового типа можно задать одним из трех
способов:
<имя> = FILE OF <тип>;
16
<имя> = TEXT;
<имя> = FILE;
Здесь <имя> - имя файлового типа (правильный идентификатор);
FILE, OF - зарезервированные слова (файл, из);
TEXT - имя стандартного типа текстовых файлов;
<тип> - любой тип Турбо Паскаля, кроме файлов.
Например:
type
product = record
name : String;
code : Word;
cost : comp
end;
textSO = file of String [80] ;
var
fl : file of char;
f2 : text;
f3 : file;
f4 : text80;
f5 : file of product;
В зависимости от способа объявления можно выделить три вида файлов:



типизированные файлы (задаются предложением FILE OF...);
текстовые файлы (определяются типом TEXT);
нетипизированные файлы (определяются типом FILE).
В наших примерах F1, F4 и F5- типизированные файлы, F2 - текстовый файл, F3 нетипизированный файл. Вид файла, вообще говоря, определяет способ хранения
информации в файле. При объявлении уже существующих файлов программист должен
сам следить за соответствием вида объявления характеру файла.
17
Доступ к файлам.
Любой программе доступны два предварительно объявленных файла со
стандартными файловыми переменными: INPUT - для чтения данных с клавиатуры и
OUTPUT - для вывода на экран. Стандартный Паскаль требует обязательного упоминания
этих файлов в заголовке программы, например, так:
PROGRAM NameOfProgram(input,output) ;
В Турбо Паскале это необязательно, вот почему заголовок программы можно
опускать.
Любые другие файлы, а также логические устройства становятся доступны
программе только после выполнения особой процедуры открытия файла (логического
устройства). Эта процедура заключается в связывании ранее объявленной файловой
переменной с именем существующего или вновь создаваемого файла, а также в указании
направления обмена информацией: чтение из файла или запись в него.
Файловая переменная связывается с именем файла в результате обращения к
стандартной процедуре ASSIGN:
ASSIGN (<ф.п.>, <имя файла или л.у.>); .
Здесь <ф.п.> - файловая переменная (правильный идентификатор, объявленный в
программе как переменная файлового типа);
<имя файла или л.у.> - текстовое выражение, содержащее имя файла или логическое
устройство.
Если имя файла задается в виде пустой строки, например, ASSIGN(f, ' '), то в
зависимости от направления обмена данными файловая переменная связывается со
стандартным файлом INPUT или OUTPUT.
Имена файлов
Имя файла - это любое выражение строкового типа, которое строится по правилам
определения имен в MS-DOS (операционной системе ПК):

имя содержит до восьми разрешенных символов; разрешенные символы - это
прописные и строчные латинские буквы, цифры, и символы:
! @ # $ % ^ & ( ) ' ~ - _


имя начинается с любого разрешенного символа;
за именем может следовать расширение - последовательность до трех разрешенных
символов; расширение, если оно есть, отделяется от имени точкой. Перед именем
может указываться так называемый путь к файлу: имя диска и/или имя текущего
каталога и имена каталогов вышестоящих уровней.
Имя диска - это один из символов A...Z, после которого ставится двоеточие. Имена
А: и В: относятся к дисковым накопителям на гибких дискетах, имена С:, D: и т.д. - к
жестким дискам. За именем диска может указываться имя каталога, содержащего файл.
Весь путь к файлу отделяется от имени файла обратной косой чертой.
var
finp: text;
fout:file of String;
const
18
name = 'c:\dir\subdir\out.txt';
begin
assign(finp,'123.dat') ;
assign(fout,name);
end.
Инициация файла
Инициировать файл означает указать для этого файла направление передачи данных.
В Турбо Паскале можно открыть файл для чтения, для записи информации, а также для
чтения и записи одновременно.
Для чтения файл инициируется с помощью стандартной процедуры RESET:
RESET (<ф.п.>);
Здесь <ф.п.> - файловая переменная, связанная ранее процедурой ASSIGN с уже
существующим файлом или логическим устройством-приемником информации.
При выполнении этой процедуры дисковый файл или логическое устройство
подготавливается к чтению информации. В результате специальная переменная-указатель,
связанная с этим файлом, будет указывать на начало файла, т.е. на компонент с
порядковым номером 0.
Если делается попытка инициировать чтение из несуществующего файла или из
логического устройства PRN, возникает ошибка периода исполнения, которая может быть
сообщена программе ненулевым значением встроенной функции IORESULT типа WORD.
Например, следующий фрагмент программы позволяет установить, существует ли
требуемый файл на диске:
var
f : file of char;
begin
assign(f,'myfile.dat');
{$I-} {Отключаем контроль ошибок ввода-вывода}
reset(f);
{$I+} {Включаем контроль ошибок ввода-вывода}
if IOResult <> 0 then
..... {Файл не существует}
else
..... {Файл существует}
19
end.
В этом фрагменте с помощью директивы компилятора {$I-} отключается
автоматический контроль ошибок ввода-вывода. Если этого не сделать, то отсутствие
файла приведет к аварийному завершению программы.
В Турбо Паскале разрешается обращаться к типизированным файлам, открытым
процедурой RESET (т.е. для чтения информации), с помощью процедуры WRITE (т.е. для
записи информации). Такая возможность позволяет легко обновлять ранее созданные
типизированные файлы и при необходимости расширять их. Для текстовых файлов,
открытых процедурой RESET, нельзя использовать процедуру WRITE или WRITELN.
Стандартная процедура REWRITE (<ф.п.>).
инициирует запись информации в файл или в логическое устройство, связанное
ранее с файловой переменной <ф.п.>. Процедурой REWRITE нельзя инициировать запись
информации в ранее существовавший дисковый файл: при выполнении этой процедуры
старый файл уничтожается и никаких сообщений об этом в программу не передается.
Новый файл подготавливается к приему информации и его указатель принимает значение
0.
Стандартная процедура APPEND (<ф.п.>) инициирует запись в ранее
существовавший текстовый файл для его расширения, при этом указатель файла
устанавливается в его конец. Процедура APPEND применима только к текстовым файлам,
т.е. их файловая переменная должна иметь тип TEXT (см. выше). Процедурой APPEND
нельзя инициировать запись в типизированный или нетипизированный файл. Если
текстовый файл ранее уже был открыт с помощью RESET или REWRITE, использование
процедуры APPEND приведет к закрытию этого файла и открытию его вновь, но уже для
добавления записей.
Процедуры и функции для работы с файлами
Ниже описываются процедуры и функции, которые можно использовать с файлами
любого вида.
Процедура Close. Закрывает файл, однако связь файловой переменной с именем файла,
установленная ранее процедурой ASSIGN, сохраняется. Формат обращения:
CLOSE (<ф.п.>)
При создании нового или расширении старого файла процедура обеспечивает
сохранение в файле всех новых записей и регистрацию файла в каталоге.
Процедура RENAME. Переименовывает файл. Формат обращения:
RENAME (<ф.п.>, <новое имя>)
Здесь <новое имя> - строковое выражение, содержащее новое имя файла. Перед
выполнением процедуры необходимо закрыть файл, если он ранее был открыт.
Процедура ERASE. Уничтожает-файл. Формат обращения:
ERASE (<ф.п.>)
Перед выполнением процедуры необходимо закрыть файл, если он ранее был открыт
процедурами RESET, REWRITE или APPEND.
Следующий фрагмент программы показывает, как можно использовать процедуры
RENAME и CLOSE при работе с файлами. Предположим, что требуется отредактировать
20
файл, имя которого содержит переменная NAME. Перед редактированием необходимо
убедиться, что нужный файл имеется на диске, и переименовать его - заменить
расширение этого файла на ВАК (страховочная копия). Если файл с таким расширением
уже существует, его надо стереть.
var
fi : text; {Исходный файл}
fo : text; {Отредактированный файл}
name : String;
name_bak: String;
k, i: Word;
const
bak = '.bak';
Процедура FLUSH. Очищает внутренний буфер файла и, таким образом, гарантирует
сохранность всех последних изменений файла на диске. Формат обращения:
FLUSH (<ф.п.>)
Любое обращение к файлу в Турбо Паскале осуществляется через некоторый буфер,
что необходимо для согласования внутреннего представления файлового компонента
(записи) с принятым в ДОС форматом хранения данных на диске. В ходе выполнения
процедуры FLUSH все новые записи будут действительно записаны на диск. Процедура
игнорируется, если файл был инициирован для чтения процедурой RESET.
Функция EOF (<ф. п. >) : BOOLEAN. Логическая функция, тестирующая конец
файла. Возвращает TRUE, если файловый указатель стоит в конце файла. При записи это
означает, что очередной компонент будет добавлен в конец файла, при чтении -что файл
исчерпан.
Текстовые файлы
Текстовые файлы связываются с файловыми переменными, принадлежащими
стандартному типу TEXT. Текстовые файлы предназначены для хранения текстовой
информации. Именно в такого типа файлах хранятся, например, исходные тексты
программ. Компоненты (записи) текстового файла могут иметь переменную длину, что
существенно влияет на характер работы с ними.
Текстовый файл трактуется в Турбо Паскале как совокупность строк переменной
длины. Доступ к каждой строке возможен лишь последовательно, начиная с первой. При
создании текстового файла в конце каждой записи (строки) ставится специальный признак
EOLN (End OfLiNe - конец строки), а в конце всего файла - признак EOF (End Of File конец файла). Эти признаки можно протестировать одноименными логическими
функциями (см. ниже). При формировании текстовых файлов используются следующие
системные соглашения:
EOLN- последовательность кодов ASCII #13 (CR) и #10 (LF);
EOF - код #26 стандарта ASCII.
21
Для доступа к записям применяются процедуры READ, READLN, WRITE,
WRITELN. Они отличаются возможностью обращения к ним с переменным числом
фактических параметров, в качестве которых могут использоваться символы, строки и
числа. Первым параметром в любой из перечисленных процедур может стоять файловая
переменная. В этом случае осуществляется обращение к дисковому файлу или
логическому устройству, связанному с переменной процедурой ASSIGN. Если файловая
переменная не указана, происходит обращение к стандартным файлам INPUT к OUTPUT.
Процедура READ. Обеспечивает ввод символов, строк и чисел. Формат обращения:
READ (<ф.п.>,<сп.ввода>) или READ (<сп.ввода>)
Здесь <сп.ввода> - список ввода: последовательность из одной или более
переменных типа CHAR, STRING, а также любого целого или вещественного типа.
При вводе переменных типа CHAR выполняется чтение одного символа из файла и
присваивание считанного значения переменной. Если перед выполнением чтения
указатель файла достиг конца очередной строки, то результатом чтения будет символ CR
(ASCII код #13), а если достигнут конец файла, то - символ EOF (код #26). При вводе с
клавиатуры символ CR вводится при нажатии на клавишу Enter, а символ EOF - при
одновременном нажатии клавиш CTRL и Z.
При вводе переменных типа STRING количество считанных процедурой и
помещенных в строку символов равно максимальной длине строки, если только раньше не
встретились символы CR или EOF. В этом случае сами символы CR и EOF в строку не
помещаются. Если количество символов во входном потоке данных больше максимальной
длины строки, «лишние» символы до конца строки отбрасываются, а новое обращение к
READ возвращает пустую строку.
При вводе числовых переменных процедура READ вначале выделяет подстроку во
входном потоке по следующему правилу: все ведущие пробелы, символы табуляции и
маркеры конца строк EOLN пропускаются; после выделения первого значащего символа,
наоборот, любой из перечисленных символов или символ EOF служат признаком конца
подстроки. Выделенная таким образом подстрока затем рассматривается как символьное
представление числовой константы соответствующего типа и преобразуется во
внутреннее представление, а полученное значение присваивается переменной. Если в
подстроке был нарушен требуемый формат представления численной константы,
возникает ошибка ввода-вывода. Если при пропуске ведущих пробелов встретился символ
EOF, переменная получает значение 0. Отметим, что в Турбо Паскале не предусмотрен
ввод шестнадцатеричных констант.
При использовании процедуры READ применительно к стандартному файлу INPUT,
т.е. при вводе с клавиатуры, символьные строки запоминаются в буфере, который
передается процедуре только после нажатия на клавишу Enter. Это позволяет
редактировать данные при их вводе. Для редактирования используются следующие
клавиши:



22
Backspace, Ctrl-H, перевод курсора влево - стирают символ слева от курсора;
перевод курсора вправо - восстанавливает символ за символом предыдущую
строку ввода;
Ctrl-Z Enter - завершает ввод по процедуре READ; оставшиеся «лишние»
символьные параметры принимают значение CHR(26), строки возвращаются
пустыми, а численные переменные остаются без изменения.
Максимальная длина буфера ввода при работе с клавиатурой составляет 127
символов. Ввод с клавиатуры по процедуре READ сопровождается эхо-повтором
вводимых символов на экране ПК.
Процедура READ прекрасно приспособлена к вводу чисел. При обращении к ней за
вводом очередного целого или вещественного числа процедура «перескакивает» маркеры
конца строк, т.е. фактически весь файл рассматривается ею как одна длинная строка,
содержащая текстовое представление чисел. В сочетании с проверкой конца файла
функцией EOF процедура READ позволяет организовать простой ввбд массивов данных,
например, так:
const
N = 1000; {Максимальная длина ввода}
var
f : text;
m : array [1..N] of real;
i : Integer;
begin
assign(f, 'prog.dat') ;
reset(£); i := 1;
while not EOF(f) and (i <= N) do
begin
read(f ,m[i] ) ;
inc(i)
end;
close(f);
.......
end.
Процедура READLN. Обеспечивает ввод символов, строк и чисел. Эта процедура
идентична процедуре READ за исключением того, что после считывания последней
переменной оставшаяся часть строки до маркера EOLN пропускается, поэтому следующее
обращение к READLN или READ начинается с первого символа новой строки. Кроме
того, эту процедуру можно вызвать без параметра <cn.вводa> (см. процедуру READ), что
приведет к пропуску всех символов текущей строки вплоть до EOLN.
Если процедура используется для чтения с клавиатуры, нажатие на клавишу Enter
отобразится на экране как последовательность CR + LF и курсор будет помещен в начало
23
следующей строки, в то время как в процедуре READ эхо-повтором клавиши Enter
является символ CR и курсор помещается в начало текущей строки.
Процедура WRITE. Обеспечивает вывод информации в текстовый файл или передачу ее
на логическое устройство. Формат обращения:
WRITE (<ф.п.>, <сп.вывода>) или WRITE (<сп.вывода>)
Здесь <сп.вывода> - список вывода: последовательность из одного или более
выражений типа CHAR, STRING, BOOLEAN, a также любого целого или вещественного
типа.
Файловая переменная <ф.п.>, если она указана, должна быть предварительно
описана как переменная типа TEXT и связана с именем файла или логическим
устройством процедурой.
Процедура WRITELN. Эта процедура полностью идентична процедуре WRITE за
исключением того, что выводимая строка символов завершается кодами CR и LF. При
вызове WRITELN можно опускать параметр <сп.вывода>: в этом случае в файл
передается маркер EOLN, что при выводе на экран приведет к переводу курсор» в начало
следующей строки.
Логическая функция EOLN. Возвращает TRUE, если во входном текстовом файле
достигнут маркер конца строки. Формат обращения:
EOLN<ф.п.>
Если параметр <ф.п.> опущен, функция проверяет стандартный файл INPUT.
Существует некоторое отличие в работе функций EOLN и EOF с дисковыми
файлами и логическими устройствами. Дело в том, что для логического устройства
невозможно предвидеть, каким будет результат чтения очередного символа. Поэтому при
работе с логическим устройством функция EOLN возвращает TRUE, если последним
считанным с устройства символом был EOLN или EOF, в то время как при чтении с диска
TRUE возвращается в случае, если следующим считываемым символом будет EOLN или
EOF.
Типизированные файлы
Длина любого компонента типизированного файла строго постоянна, что дает
возможность организовать прямой доступ к каждому из них (т.е. доступ к компоненту по
его порядковому номеру).
Перед первым обращением к процедурам ввода-вывода указатель файла стоит в его
начале и указывает на первый компонент с номером 0. После каждого чтения или записи
указатель сдвигается к следующему компоненту файла. Переменные в списках вводавывода должны иметь тот же тип, что и компоненты файла. Если этих переменных в
списке несколько, указатель будет смещаться после каждой операции обмена данными
между переменными и дисковым файлом.
Процедура READ. Обеспечивает чтение очередных компонентов типизированного файла.
Формат обращения:
READ (<ф.п.>,<сп.ввода>)
Здесь <cn.вводa> - список ввода, содержащий одну или более переменных такого же
типа, что и компоненты файла.
24
Файловая переменная <ф.п.> должна быть объявлена предложением FILE OF... и
связана с именем файла процедурой ASSIGN. Файл необходимо открыть процедурой
RESET. Если файл исчерпан, обращение к READ вызовет ошибку ввода-вывода.
Процедура WRITE. Используется для записи данных в типизированный файл. Формат
обращения:
WRITE (<ф.п.>,<сп.вывода>)
Здесь <сп.вывода> - список вывода, содержащий одно или более выражений того же
типа, что и компоненты файла.
Процедура SEEK. Смещает указатель файла к требуемому компоненту. Формат
обращения:
SEEK (<ф.п.>,<N компонента>)
Здесь <N компонента> - выражение типа LONGINT, указывающее номер компонента
файла.
Первый компонент файла имеет номер 0. Процедуру нельзя применять к текстовым
файлам.
Функция FILESIZE. Возвращает значение типа LONGINT, которое содержит количество
компонентов файла. Формат обращения: '
FILESIZE (<ф.п.>)
Функцию нельзя использовать для текстовых файлов. Чтобы переместить указатель в
конец типизированного файла, можно написать:
seek (FileVar, FileSize(FileVar));
где FILEVAR - файловая переменная.
Функция.FILEPOS. Возвращает значение типа LONGINT, содержащее порядковый номер
компонента файла, который будет обрабатываться следующей операцией ввода-вывода.
Формат обращения:
FILEPOS (<ф.п.>)
Функцию нельзя использовать для текстовых файлов. Первый компонент файла
имеет порядковый номер 0.
Нетипизированные файлы
Нетипизированные файлы объявляются как файловые переменные типа FILE и
отличаются тем, что для них не указан тип компонентов. Отсутствие типа делает эти
файлы, с одной стороны, совместимыми с любыми другими файлами, а с другой позволяет организовать высокоскоростной обмен данными между диском и памятью.
При инициации нетипизированного файла процедурами RESET или REWRITE
можно указать длину записи нетипизированного файла в байтах. Например, так:
var
25
f: file;
begin
.......
assign(f, 'myfile.dat')
reset(f,512);
.......
end.
Длина записи нетипизированного файла указывается вторым параметром при
обращении к процедурам RESET или REWRITE, в качестве которого может
использоваться выражение типа WORD. Если длина записи не указана, она принимается
равной 128 байтам.
Турбо Паскаль не накладывает каких-либо ограничений на длину записи
нетипизированного файла.
При работе с нетипизированными файлами могут применяться все процедуры и
функции, доступные типизированным файлам, за исключением READ и WRITE, которые
заменяются соответственно высокоскоростными процедурами BLOCKREAD и
BLOCKWRITE . Для вызова этих процедур используются следующие предложения:
BLOCKREAD (<ф .п . >, <буф>, < [, <NN>] )
26
Операторы вводы/ вывода в Turbo Pascal.
Операторы вывода данных на экран Write("список_переменных"); или
Writeln("список_переменных ")
Например, операторы Write(a, b, c); или Write(a); Write(b); Write(c); или Writeln(a, b,
c); - выводят значения переменных "a", "b", "c" начиная с текущей позиции курсора.
После вывода данных оператором Write("сп"); курсор остается за последним
выведенным символом.
Оператор Writeln("сп"); после вывода данных переводит курсор на первую позицию
следующей строки.
Оператор Writeln; переводит курсор на начало следующей строки экрана.
Оператор Write('Моя первая программа !'); выводит на экран указанный текст.
В операторах вывода допускается производить арифметические действия, например,
оператор Writeln(32*a+Sin(x));
При выводе данных можно задавать формат вывода.
Для этого после имени переменной ставится знак двоеточие " : " , например:
Writeln(a:5:2); - при выводе значения переменной вещественного типа отводится 5
позиций (включая отрицательный знак и точку), из них 2 позиции отводится для вывода
цифр в дробной части. При выводе значения переменной целого типа задается количество
позиций для числа (включая отрицательный знак), например: Writeln(i:8);
При выводе значений символьных и строковых переменных формат определяет
число позиций для вывода значения переменной (текста).
При выводе число или текст выравниваются по правому краю отведенного поля,
например: если а:=5. 02;, то оператор Writeln('а=', a:6:2); выведет на экран: а= _ _ 5. 02,
если n:= '116'; s:= 'Школа N';, то оператор Writeln(s:7, n:6); выведет на экран надпись:
Школа N _ _ _ 116 .
Для выравнивания числа или текста по левому краю отведенного поля первый знак
формата задается отрицательным, например: оператор Writeln('а=', a:-8:2); выведет на
экран надпись: а=5. 02. При недостатке количества позиций для вывода число или текст
выводятся полностью, а формат игнорируется, кроме формата вывода дробной части
числа. Если формат вывода не задавать, то значения целых и строковых переменных
выводятся полностью, а вещественных - в экспоненциальной форме с количеством цифр,
соответствующих типу переменной.
Операторы ввода данных с клавиатуры Read("сп"); или Readln("сп");
Оператор Readln(a); будет ждать ввода данных. Следует набрать на клавиатуре
значение переменной "а", например, число и нажать клавишу Enter.
Для ввода значений нескольких переменных, например, a, b, c применяются
конструкции вида: Readln(a); Readln(b); Readln(c); или Readln(a, b, c);
При вводе нескольких числовых данных, например, оператором Readln(a, b, c);
необходимо после набора каждого значения переменной нажимать клавишу SpaceBar или
Enter, а в конце ввода - Enter.
При вводе значений символьных переменных нажатие клавиши Enter приводит к
присвоению символьной переменной значения кода клавиши Enter (#13), поэтому
значения символьных переменных вводятся одна за другой без нажатия Enter или
SpaceBar (#32).
Например, оператор: Readln(с1, с2, с3, c4); ожидает ввода значений символьных
переменных с1, с2, с3, c4, т. е. набора на клавиатуре символов, например: "У", "Р", "А", "!"
и нажатия Enter. Тогда оператор Writeln(с1, с2, с3, c4); выведет на экран надпись: УРА!
27
Оператор Readln; без параметров служит для приостановки выполнения программы
и ожидает нажатия клавиши Enter, т. е. применяется с целью приостановки вывода
информации на экран для просмотра результатов. При вводе данных предпочтительнее
использовать оператор Readln, поскольку оператор Read после срабатывания не считывает
управляющий код (#13), который остается в буфере клавиатуры.
28
Операции в Turbo Pascal.
Математические операции
В таблице приведены основные математические операции Турбо Паскаль.
Символ операции Название операции
Пример
*
умножение
2*3 (результат: 6)
/
деление
30/2 (результат: 1.5E+01)
+
сложение
2+3 (результат: 5)
вычитание
5-3 (результат: 2)
div
целочисленное деление 5 div 2 (результат: 2)
mod
остаток от деления
5 mod 2 (результат: 1)
Логические операции
Над логическими аргументами в Турбо Паскаль определены следующие операции:
1. NOT - логическое отрицание ("НЕ")
2. AND - логическое умножение ("И")
3. OR - логическое сложение ("ИЛИ")
4. XOR - логическое "Исключающее ИЛИ"
Результаты выполнения этих операций над переменными А и В логического типа
приведены в таблице истинности.
A
B not A A and B A or B A xor B
true true false
true
true
false
true false
false
true
true
false true true
false
true
true
false false
false
false
false
Операции отношения
К операциям отношения в Турбо Паскаль относятся такие операции, как:
1. > - больше
2. < - меньше
3. = - равно
4. <> - не равно
5. >= - больше или равно
6. <= - меньше или равно
В операциях отношения могут принимать участие не только числа, но и символы,
строки, множества и указатели.
Приоритет операций
Порядок вычисления выражения определяется старшинством (приоритетом)
содержащихся в нем операций. В языке Паскаль принят следующий приоритет операций:
1. унарная операция not, унарный минус -, взятие адреса @
2. операции типа умножения: * / div mod and
29
3. операции типа сложения: + - or xor
4. операции отношения: = <> < > <= >= in
Порядок выполнения операций переопределить можно с помощью скобок. Например
2*5+10 равно 20, но 2*(5+10) равно 30.
30
Условный оператор. Оператор выбора в Turbo Pascal.
В языке Паскаль используется два оператора для реализации условных переходов IF и CASE, а также оператор безусловного перехода GOTO.
Оператор условного перехода в Турбо Паскаль имеет вид:
if условие then оператор 1 else оператор 2;
условие - это логическое выражение, в зависимости от которого выбирается одна из
двух альтернативных ветвей алгоритма.
Если значение условия истинно (TRUE), то будет выполняться оператор 1,
записанный после ключевого слова then. В противном случае будет выполнен оператор 2,
следующий за словом else, при этом оператор 1 пропускается.
После выполнения указанных операторов программа переходит к выполнению
команды, стоящей непосредственно после оператора if.
Необходимо помнить, что перед ключевым словом else точка с запятой никогда не
ставится!
else - часть в операторе if может отсутствовать:
if условие then оператор 1;
Тогда в случае невыполнения логического условия управление сразу передается
оператору, стоящему в программе после конструкции if.
Следует помнить, что синтаксис языка допускает запись только одного оператора после
ключевых слов then и else, поэтому группу инструкций обязательно надо объединять в
составной оператор (окаймлять операторными скобками begin ... end).
if x > 0 then modul := x else modul := -x;
if k > 0 then WriteLn('k - число положительное');
if min > max then begin
t := min;
min := max;
max := t;
end;
Оператор выбора
Часто возникают ситуации, когда приходится осуществлять выбор одного из
нескольких альтернативных путей выполнения программы. Несмотря на то, что такой
выбор можно организовать с помощью оператора if .. then, удобнее воспользоваться
специальным оператором выбора. Его формат:
case <ключ_выбора> of
<константа_выбора> : <оператор>;
...
<константа_выбора> : <оператор2>;
end;
или
case <ключ_выбора> of
<список_выбора>
else <оператор3>
end;
Вначале вычисляется значение <ключ_выбора>, а затем в последовательности
операторов <список_выбора> отыскивается такой, которому предшествует константа,
равная вычисленному значению. Найденный оператор выполняется, после чего оператор
выбора завершает свою работу. Если в списке выбора не будет найдена константа,
соответствующая вычисленному значению ключа выбора, управление передается
31
операторам, стоящим за словом else. Часть else <оператор3> можно опускать. Тогда при
отсутствии нужной константы, оператор завершит свою работу.
Пример:
case ch of
'A'..'Z', 'a'..'z' : WriteLn('Буква');
'0'..'9'
: WriteLn('Цифра');
'+', '-', '*', '/' : WriteLn('Оператор');
else WriteLn('Специальный символ')
end;
32
Метки и оператор перехода.
Оператор безусловного перехода
Помимо операторов условного перехода существует также оператор безусловного
перехода goto. Формат:
goto <метка>
Оператор goto переходит при выполнении программы к определенному оператору
программы, перед которым находится метка. Метка должна быть описана в разделе
описания меток той программы (процедуры или функции), в которой она используется.
Необходимо, чтобы в программе существовал оператор, отмеченный указанной
меткой. Она записывается перед оператором и отделяется от него двоеточием.
Пример:
label 1;
begin
...
goto 1;
...
1: WriteLn('Переход к метке 1');
end.
При
При использовании меток необходимо руководствоваться следующими правилами:
1.
метка, на которую ссылается оператор goto, должна быть описана в разделе
описаний и она обязательно должна встретиться где-нибудь в теле программы;
2.
метки, описанные в процедуре (функции), локализуются в ней. Поэтому
передача управления извне процедуры (функции) на метку внутри нее невозможна.
Учтите! Само понятие структурного программирования и общепринятый стиль
программирования на структурных языках НЕ ПРИВЕТСТВУЕТ применение меток и
операторов перехода в программах. Это затрудняет понимание программы, как автором,
так и потребителями, кроме того, применение меток отрицательно сказывается на
эффективности генерируемого кода.
33
Операторы циклов с предусловием, постусловием и с параметром в
Turbo Pascal.
Циклы
В большинстве задач, встречающихся на практике, необходимо производить
многократное выполнение некоторого действия. Такой многократно повторяющийся
участок вычислительного процесса называется циклом.
Если заранее известно количество необходимых повторений, то цикл называется
арифметическим. Если же количество повторений заранее неизвестно, то говорят об
итерационном цикле.
В итерационных циклах производится проверка некоторого условия, и в зависимости
от результата этой проверки происходит либо выход из цикла, либо повторение
выполнения тела цикла. Если проверка условия производится перед выполнением блока
операторов, то такой итерационный цикл называется циклом с предусловием (цикл
"пока"), а если проверка производится после выполнения тела цикла, то это цикл с
постусловием (цикл "до").
Особенность этих циклов заключается в том, что тело цикла с постусловием всегда
выполняется хотя бы один раз, а тело цикла с предусловием может ни разу не
выполниться. В зависимости от решаемой задачи необходимо использовать тот или иной
вид итерационных циклов.
Арифметические циклы (циклы с параметром)
Синтаксис:
for <пар_цикла> := <нач_значение> to <кон_значение> do <оператор>
или
for <пар_цикла> := <нач_значение> downto <кон_значение> do <оператор>
Оператор for вызывает оператор, находящийся после слова do, по одному разу для
каждого значения в диапазоне от значения 1 до значения 2.
Переменная цикла, начальное и конечное значения должны иметь порядковый тип.
Со словом to, значение переменной цикла увеличивается на 1 при каждой итерации цикла.
Со словом downto, значение переменной цикла уменьшается на 1 при каждой итерации
цикла. Не следует самостоятельно изменять значение управляющей переменной внутри
цикла.
Как и в случае использования оператора условного перехода, следует помнить, что
синтаксис языка допускает запись только одного оператора после ключевого слова do,
поэтому, если вы хотите в цикле выполнить группу операторов, обязательно надо
объединить их в составной оператор (окаймить операторными скобками begin ... end).
Пример 2. Латинский алфавит.
for ch:='A' to 'Z' do Writeln(ch);
Пример 3. Использование цикла с downto.
for i:=10 downto 1 do WriteLn(i);
Пример 4. Использование составного оператора.
for x:=1 to 10 do begin
y:=2*x+3;
WriteLn('f(',x,')=',y);
end;
Итерационные циклы с предусловием
Синтаксис:
while <условие> do <оператор>
34
Оператор после do будет выполняться до тех пор, пока логическое выражение
принимает истинное значение (True). Логическое выражение является условием
возобновления цикла. Его истинность проверяется каждый раз перед очередным
повторением оператора цикла, который будет выполняться лишь до тех пор, пока
логическое выражение истинно. Как только логическое выражение принимает значение
ложь (False), осуществляется переход к оператору, следующему за while.
Выражение оценивается до выполнения оператора, так что если оно с самого начала
было ложным (False), то оператор не будет выполнен ни разу.
Пример.
eps:=0.001;
while x > eps do x:=x/2;
Итерационные циклы с постусловием
Синтаксис:
repeat
<оператор>;
<оператор>;
...
<оператор>
until <условие>
Операторы между словами repeat и until повторяются, пока логическое выражение
является ложным (False). Как только логическое выражение становится истинным (True),
происходит выход из цикла.
Так как выражение оценивается после выполнения операторов, то в любом случае
операторы выполнятся хотя бы один раз.
Пример.
repeat
WriteLn('Введите положительное число');
ReadLn(x);
until x>0;
Операторы завершения цикла
Для всех операторов цикла выход из цикла осуществляется как вследствие
естественного окончания оператора цикла, так и с помощью операторов перехода и
выхода.
В версии Турбо Паскаль 7.0 определены стандартные процедуры:
Break
Continue
Процедура Break выполняет безусловный выход из цикла. Процедура Continue
обеспечивает переход к началу новой итерации цикла.
Заметим, что хотя и существует возможность выхода из цикла с помощью оператора
безусловного перехода goto, делать этого не желательно. Во всех случаях можно
воспользоваться специально предназначенными для этого процедурами Break и Continue.
35
Процедуры и функции в Turbo Pascal. Локализация переменных.
Формальные и фактические параметры в Turbo Pascal.
Процедуры и функции
В языке Паскаль предусмотрены средства, позволяющие оформлять
вспомогательный алгоритм как подпрограмму. Это бывает необходимо тогда, когда
какой-либо подалгоритм неоднократно повторяется в программе или имеется
возможность использовать некоторые фрагменты уже разработанных ранее алгоритмов.
Кроме того, подпрограммы применяются для разбиения крупных программ на отдельные
смысловые части в соответствии с модульным принципом в программировании.
Для использования подалгоритма в качестве подпрограммы ему необходимо
присвоить имя и описать алгоритм по правилам языка Паскаль. В дальнейшем, при
необходимости вызвать его в программе, делают вызов подпрограммы упоминанием в
нужном месте имени и списка входных и выходных данных. Такое упоминание приводит
к выполнению входящих в подпрограмму операторов, работающих с указанными
данными. После выполнения подпрограммы работа продолжается с той команды, которая
непосредственно следует за вызовом подпрограммы.
В языке Паскаль имеется два вида подпрограмм - процедуры и функции.
Процедуры и функции помещаются в раздел описаний программы. Для обмена
информацией между процедурами и функциями и другими блоками программы
существует механизм входных и выходных параметров. Входными параметрами
называют величины, передающиеся из вызывающего блока в подпрограмму (исходные
данные для подпрограммы), а выходными - передающиеся из подпрограммы в
вызывающий блок (результаты работы подпрограммы).
Одна и та же подпрограмма может вызываться неоднократно, выполняя одни и те же
действия с разными наборами входных данных. Параметры, использующиеся при записи
текста подпрограммы в разделе описаний, называют формальными, а те, что
используются при ее вызове - фактическими.
Описание и вызов процедур и функций
Структура описания процедур и функций до некоторой степени похожа на структуру
программы: у них также имеются заголовок, раздел описаний и исполняемая часть. Раздел
описаний содержит те же подразделы, что и раздел описаний программы: описания
констант, типов, меток, процедур, функций, переменных. Исполняемая часть содержит
собственно операторы процедур.
Формат описания процедуры имеет вид:
procedure имя процедуры (формальные параметры);
раздел описаний процедуры
begin
исполняемая часть процедуры
end;
Формат описания функции:
function имя функции (формальные параметры):тип результата;
раздел описаний функции
begin
исполняемая часть функции
end;
Формальные параметры в заголовке процедур и функций записываются в виде:
var имя праметра: имя типа
и отделяются друг от друга точкой с запятой. Ключевое слово var может
отсутствовать (об этом далее). Если параметры однотипны, то их имена можно
36
перечислять через запятую, указывая общее для них имя типа. При описании параметров
можно использовать только стандартные имена типов, либо имена типов, определенные с
помощью команды type. Список формальных параметров может отсутствовать.
Вызов процедуры производится оператором, имеющим следующий формат:
имя
процедуры(список фактических параметров);
Список фактических параметров - это их перечисление через запятую. При вызове
фактические параметры как бы подставляются вместо формальных, стоящих на тех же
местах в заголовке. Таким образом происходит передача входных параметров, затем
выполняются операторы исполняемой части процедуры, после чего происходит возврат в
вызывающий блок. Передача выходных параметров происходит непосредственно во
время работы исполняемой части.
Вызов функции в Турбо Паскаль может производиться аналогичным способом,
кроме того, имеется возможность осуществить вызов внутри какого-либо выражения. В
частности имя функции может стоять в правой части оператора присваивания, в разделе
условий оператора if и т.д.
Для передачи в вызывающий блок выходного значения функции в исполняемой
части функции перед возвратом в вызывающий блок, необходимо поместить следующую
команду:
имя функции := результат;
При вызове процедур и функций необходимо соблюдать следующие правила:
1.
количество фактических параметров должно совпадать с количеством
формальных;
2.
соответствующие фактические и формальные параметры должны совпадать
по порядку следования и по типу.
Заметим, что имена формальных и фактических параметров могут совпадать. Это не
приводит к проблемам, так как соответствующие им переменные все равно будут
различны из-за того, что хранятся в разных областях памяти.
Кроме того, все формальные параметры являются временными переменными - они
создаются в момент вызова подпрограммы и уничтожаются в момент выхода из нее.
Локальные и глобальные переменные в Turbo Pascal.
Вложенные процедуры. Если блок какой-либо процедуры Р1 содержит внутри
процедуру Р2, то говорят, что Р2 вложена в Р1.
Пример:
PROCEDURE P1(X: REAL; VAR Y: REAL);
VAR C: INTEGER;
PROCEDURE P2(VAR Z: REAL);
......................
END;
BEGIN
................
END;
Любые идентификаторы, введённые внутри какого-либо блока (процедуры,
функции) для описания переменных, констант, типов, процедур, называются локальными
для данного блока. Такой блок вместе с вложенными в него подпрограммами называется
областью действия этих локальных переменных, констант, типов и процедур.
Пример:
PROCEDURE T1;
VAR Y1,Y2:REAL;
PROCEDURE SQ1;
VAR A,B,C,D:REAL;
BEGIN
(*Переменные A,B,C,D являются локальными для SQ1,
37
область их действия - процедура SQ1*)
.................
END;
BEGIN
(*Переменные Y1,Y2 -нелокальные переменные для SQ1 область их действия процедуры T1 и SQ1*)
.................
END;
Константы, переменные, типы, описанные в блоке PROGRAM, называют
глобальными. Использование локальных переменных позволяет системе лучше
оптимизировать программы, делает их более наглядными и уменьшает вероятность
появления ошибок.
При написании программ, имеющих вложенные подпрограммы, необходимо
придерживаться следующих правил:
1. Описывать идентификаторы в том блоке, где они используются, если это
возможно.
2. Если один и тот же объект (переменная, тип, константа) используется в двух и
более блоках, то описать этот объект надо в самом внешнем из них, содержащем
все остальные блоки, использующие данный объект.
3. Если переменная, используемая в процедуре, должна сохранить свое значение до
следующего вызова этой процедуры, то такую переменную надо описать во
внешнем блоке, содержащем данную процедуру.
Локализация переменных дает программисту большую свободу в выборе
идентификаторов. Так, если две процедуры А и В полностью отделены друг от друга (то
есть не вложены одна в другую), то идентификаторы в них могут быть выбраны
совершенно произвольно, в частности, могут повторяться. В этом случае совпадающим
идентификаторам соответствуют разные области памяти, совершенно друг с другом не
связанные.
Пример:
PROGRAM T2; VAR K: INTEGER;
PROCEDURE A;
VAR X,Z: REAL;
BEGIN (*Начало А*)
(* Через X, Z обозначены две величины - локальные переменные для А;
К- глобальная переменная для А*)
:::::::..
END;(*Конец А*)
PROCEDURE В;
VAR X,Z: REAL;
BEGIN (*Начало В*)
(* Через X, Z обозначены две другие величины - локальные переменные для В;
К- глобальная переменная для В*)
.................
END;(*Конец В*)
BEGIN(*Начало работы PROGRAM T2*)
(*К - единственная переменная, которую можно использовать в Т2*)
..............
END.
Если один и тот же идентификатор описан в блоке В и второй раз описан во
вложенном блоке С, то надо помнить, что эти два одинаковых идентификатора
соответствуют разным ячейкам памяти.
Пример:
PROGRAM T3;
VAR I: INTEGER; A: REAL;
Procedure P(VAR D: REAL);
38
VAR I: INTEGER;
BEGIN (*Начало Р*)
I:=3;
D:=I+10*D;
END;(*Конец Р*)
BEGIN
A:=2.0; I:=15; P(A); WRITELN(' I=',I,' A=',A)
END.
Глобальным переменным I и A отводятся две ячейки памяти. Первыми выполняются
операторы А:=2.0 и I:=15. Затем вызывается процедура Р(А).
В процессе работы Р отводится ячейка для локальной переменной I и туда
засылается число 3. После окончания работы процедуры Р эта ячейка I программой
"забывается". После возврата на оператор WRITELN программа знает только одну ячейку
I - глобальную, то есть ту, которая содержит число 15. Поэтому программа T3 выдаст на
печать I=15, A=23.0, так как А=3+10*2.
Если локальная и глобальная переменные принадлежит к одному и тому же
сложному типу, то этот тип надо описать в разделе TYPE, а сами переменные описывать
через этот общий тип.
Пример:
PROGRAM T1;
TYPE AB=ARRAY[1..3] OF REAL;
VAR A: AB;
PROCEDURE Q;
VAR B: AB;.......
END.
В этом примере переменные А и В описаны через общий тип АВ. Если же локальная
и глобальная переменные описаны одинаково, но не через общий тип, то транслятор
может "не понять", что эти переменные принадлежат одному типу.
Замечание редактора. Две переменные принадлежат одному типу только в том
случае, если они описаны с помощью одного идентификатора типа или, если они описаны
в одной строке:
var a,b: array[1..3] of real;
В противном случае переменные принадлежат разным типам. Указанное правило
относится к любым переменным, а не только в сравнении глобальных и локальных
переменных.
Пример:
var a: 1..3;
b: 1..3;
В этом случае переменные a и b относятся к разным типам.
Пример:
PROGRAM T2;
VAR A: ARRAY [1..3] OF REAL;
PROCEDURE Q;
VAR B: ARRAY [1..3] OF REAL;
....................................
END.
В этом примере переменные А и В - одинаковые массивы, то есть типы переменных
одинаковы, но транслятор, тем не менее, не считает, что А и В - принадлежат одному
типу.
39
Переход в графический режим в Turbo Pascal. Масштабирование экрана.
Процедуры и функции для работы с экраном в графическом режиме.
Модуль Graph представляет собой мощную библиотеку графических подпрограмм
универсального назначения, рассчитанную на работу с наиболее распространенными
графическими адаптерами IBM-совместимых ПК. Подпрограммы модуля Graph
обеспечивают различные режимы работы многорежимных адаптеров, полностью
используют их цветовые возможности и разрешающую способность.
При исполнении графических программ требуется автономный драйвер
графического адаптера (BGI-файл). Если программа использует штриховые шрифты, то
кроме того нужен один или несколько шрифтовых файлов (CHR-файлы). При
необходимости драйвер и шрифты могут быть включены в тело программы еще на этапе
компиляции.
Графические драйверы поддерживают следующие графические адаптеры (и
полностью совместимые с ними):
CGA
Hercules
MCGA
AT&T 400
EGA
3270 PC
VGA
IBM-8514
Для поддержки этих аппаратных средств используются следующие драйверы:
CGA.BGI
Драйвер для CGA, MCGA
EGAVGA.BGI Драйвер для EGA, VGA
HERC . BGI
Драйвер для монохромного Hercules
ATT . BGI
Драйвер для AT&T 6300 (400 строк)
PC3270.BGI
Драйвер для IBM 3270 PC
IBM8514.BGI Драйвер для IBM 8514
Во время выполнения программы процедура InitGraph автоматически распознает
графический адаптер, установленный на ПК, загружает и инициализирует
соответствующий графический драйвер, переводит адаптер в графический режим и
возвращает управление вызывающей программе. Процедура CloseGraph выгружает
драйвер из памяти и восстанавливает текстовый режим работы адаптера.
Подпрограммы модуля Graph позволяют адресоваться к любому элементу (пикселю)
растрового графического экрана и управлять светимостью этого элемента. Для указания
пикселя используется следующая система координат: верхний левый угол графического
экрана имеет координаты 0,0; горизонтальная координата X увеличивается слева направо,
вертикальная координата У увеличивается сверху вниз.
Некоторые графические подпрограммы используют понятие текущего указателя.
Указатель содержит координаты того пикселя, начиная с которого будет строиться
изображение подпрограммами LineTo, LineRel, OutText и др.
В модуле Graph имеется несколько процедур для рисования элементарных
графических фигур - точек, линий, окружностей, дуг и т.п. При необходимости замкнутые
фигуры могут быть закрашены различными цветами и стилями (образцами закраски).
Процедура SetViewPort создает на экране графическое окно. Если окно определено,
весь дальнейший графический вывод осуществляется относительно координат этого окна
и отсекается его границами.
В модуле имеются средства сохранения и выдачи изображений, работы с
несколькими графическими страницами, установки необходимых цветов.
40
Значения ошибок, возвращаемые GraphResult
const
grOk = 0;{Нет ошибок}
grNoInitGraph = -1;{Графика не инициализирована}
grNotDetected = -2;{Графическое устройство не обнаружено}
grFileNotFound = -3;{Файл драйвера устройства не найден}
grInvalidDriver= -4;{Неправильный файл драйвера устройства}
grInvalidMode =-10;{Недопустимый графический режим}
grError =-11;{Общая ошибка}
grIOerror =-12;{Ошибка графического ввода/вывода}
Константы цвета
const
Black =
Blue
=
Green =
Cyan
=
Red
=
Magenta =
Brown =
0;{Черный}
1;{Синий}
2;{Зеленый}
3;{Голубой}
4;{Красный}
5;{Фиолетовый}
6;{Коричневый}
Константы типов и толщины линий
const
SolidLn=0;{Сплошная}
DottedLn=1;{Точечная}
NormWidth=1;{Нормальная толщина}
ThickWidth= 3;{Тройная толщина}
Константы управления шрифтом
const
DefaultFont = 0;{Матричный шрифт 8x8}
TriplexFont = 1;{Шрифт триплекс; файл TRIP.CHR}
41
SmallFont = 2;{Мелкий шрифт; файл LITT.CHR}
SansSerifFont= 3;{Прямой шрифт; файл SANS.CHR}
RightText = 2;{Указатель справа от текста}
BottomText = 0;{Указатель снизу от текста}
CenterText = 1;{Указатель по центру текста}
TopText = 2;{Указатель сверху от текста}
Константы отсечения
const
ClipOn = True;{Отсекать изображение}
ClipOf£= False;{Игнорировать окно (не отсекать изображение)}
Процедуры
Procedure Arc(X, Y: Integer; StAngle, EndAngle, Radius: Word) Рисует дугу радиусом
Radius от начального угла StAngle к конечному EndAngle, используя X, Y как координаты
центра.
Procedure Bar (X1, Y1, X2, Y2 : Integer) Рисует полосу заданного размера, используя
текущий стиль и цвет.
Procedure Bar3D(X1, Y1, X2, Y2: Integer; Depth: Word; Top: Boolean) Рисует трехмерную
полосу, используя текущий стиль и цвет.
Procedure Circle (X, Y: Integer; R: word) Рисует окружность радиуса R, используя X,Y как
координаты центра.
Procedure ClearDevice Очищает экран.
Procedure ClearViewPort Очищает окно.
Procedure CloseGraph Закрывает графический режим.
Procedure DetectGraph (var Driver, Mode: Integer) Возвращает тип Driver установленного
драйвера и текущий режим Mode его работы.
Procedure DrawPoly (NumPoints: Word; var PolyPoints) Рисует многоугольник из
NumPoints вершин с координатами в PolyPoints текущим цветом и типом линии.
Procedure Ellipse (X, Y; Integer; StAngle, EndAngle, XR, YR: Word) Рисует эллиптическую
дугу от начального угла StAngle к конечному углу EndAngle, используя X, Y как
координаты центра и XR. YR - как горизонтальный и вертикальный радиусы.
42
Procedure FillEllipse(X, Y; Integer; XR, YR: Word) Рисует заштрихованный эллипс,
используя X, Y как центр uXR, YR как горизонтальный и вертикальный радиусы.
Procedure FloodFill (X, Y; Integer; Border; Word) Штрихует замкнутую область,
содержащую внутреннюю точку с координатами X, Y и ограниченную линией с цветом
Border. Используется текущий образец штриховки и цвет.
Procedure GetDefaultPalette(var Palette; PaletteType) Возвращает текущую палитру в
записи PaletteType.
Procedure GetLineSettings (var LineInfo; LineSettingsType) Возвращает текущий стиль,
шаблон и толщину линии.
Procedure GetViewSettings (var viewport: NiewPortType) Возвращает координаты и
признак отсечки текущего окна.
Procedure GraphDefaults Устанавливает стандартные параметры графического режима.
Procedure InitGraph(var Driver, Mode; Integer; Path: String) Инициализирует графический
режим. Переменные Driver и Mode должны содержать тип графического драйвера и его
режим работы. Допускается указать Driver = 0 для автоматического определения этих
параметров по результатам тестирования аппаратуры. Параметр Path определяет маршрут
поиска файла графического драйвера.
Procedure Line (X1, Y1, Х2, Y2: Integer) Рисует линию от точки X1, Y1 до точки Х2, Y2.
Procedure LineRel(DX, DY: Integer) Рисует линию от текущего указателя к точке,
заданной приращением координат.
Procedure LineTo(X, Y: Integer) Рисует линию от текущего указателя к точке X, Y.
Procedure MoveTo(X, Y: Integer) Смещает текущий указатель к точкеX,Y.
Procedure OutText (TextString: String) Выводит текстовую строку на экран.
Procedure OutTextXY(X, Y: Integer; TextString: String) Выводит текст в заданное место
экрана.
Procedure PieSlice(X, Y: Integer; StAngle, EndAngle, Radius: Word) Рисует и штрихует
сектор окружности радиусом Radius с центром в X.Y от начального угла StAngle к
конечному углу EndAngle.
Procedure Rectangle (XI, Yl, X2, Y2: Integer) Рисует прямоугольник, используя текущий
цвет и тип линии.
Procedure SetBkColor (Color: Word) Устанавливает цвет фона.
Procedure SetColor (Color: Word) Устанавливает основной цвет, которым будет
осуществляться рисование.
Procedure SetFillPattern (Pattern: FillPatternType; Color: Word) Устанавливает
произвольный образец штриховки.
43
Procedure SetFillStyle (Pattern, Color: Word) Устанавливает образец штриховки и цвет.
Procedure SetGraphBuf Size (Size: Word) Позволяет изменить размер буфера для функций
штриховки.
Procedure SetGraphMode(Mode: Integer) Устанавливает новый графический режим и
очищает экран.
Procedure SetLineStyle(LineStyle, Pattern, Thickness: Word) Устанавливает толщину и
стиль линии.
Procedure SetPalette(ColorNum, Color: Word) Заменяет цвет палитры с номером ColorNum
на цвет Color.
Функции
Procedure GetBkColor; Word Возвращает текущий фоновый цвет.
Procedure GetColor; Word Возвращает текущий цвет.
Procedure GetDriverName; String Возвращает строку с именем текущего драйвера.
Procedure GetGraphMode: Integer Возвращает текущий графический режим.
Procedure GetMaxColor; Word Возвращает максимальный цвет, который можно задать в
SetColor.
Procedure GetMaxMode: Integer Возвращает номер максимального режима текущего
загруженного драйвера.
Procedure GetMaxX: Integer Возвращает максимальную горизонтальную координату
графического экрана.
Procedure GetMaxY; Integer Возвращает максимальную вертикальную координату
графического экрана.
Procedure GetModeName(ModeNum; Word) ; String Возвращает строку с именем
указанного графического режима.
Procedure GetPaletteSize: Integer Возвращает размер таблицы палитры.
Procedure GetPixel (X, Y; Integer) : Word Возвращает цвет пикселя с координатами X,Y.
Procedure GetX: Integer Возвращает координату X текущего указателя.
Procedure GraphResult: Integer Возвращает код ошибки для последней графической
операции.
44
Понятие алгоритма и его свойства. Линейные, разветвляющиеся,
циклические алгоритмы.
Алгоритм – описание последовательности действий (план), строгое исполнение
которых приводит к решению поставленной задачи за конечное число шагов.
Свойства алгоритмов:
1. Дискретность (алгоритм должен состоять из конкретных действий, следующих в
определенном порядке);
2. Детерминированность (любое действие должно быть строго и недвусмысленно
определено в каждом случае);
3. Конечность (каждое действие и алгоритм в целом должны иметь возможность
завершения);
4. Массовость (один и тот же алгоритм можно использовать с разными исходными
данными);
5. Результативность (отсутствие ошибок, алгоритм должен приводить к правильному
результату для всех допустимых входных значениях).
Виды алгоритмов:
1. Линейный алгоритм (описание действий, которые выполняются однократно в
заданном порядке);
2. Циклический алгоритм (описание действий, которые должны повторятся указанное
число раз или пока не выполнено задание);
3. Разветвляющий алгоритм (алгоритм, в котором в зависимости от условия
выполняется либо одна, либо другая последовательность действий);
4. Вспомогательный алгоритм (алгоритм, который можно использовать в других
алгоритмах, указав только его имя).
Алгоритм, записанный на «понятном» компьютеру языке программирования,
называется программой.
Программирование - процесс составления программы для компьютера. Для первых
ЭВМ программы записывались в виде последовательности элементарных операций. Это
была очень трудоемкая и неэффективная работа. Поэтому в последствии были
разработанные специальные языки программирования. В настоящее время существует
множество искусственных языков для составления программ. Однако, так и не удалось
создать идеальный язык, который бы устроил бы всех.
45
Алгоритмы поиска элементов из массивов данных.
Двоичный (бинарный) поиск элемента в массиве
Если у нас есть массив, содержащий упорядоченную последовательность данных, то
очень эффективен двоичный поиск.
Переменные Lb и Ub содержат, соответственно, левую и правую границы отрезка
массива, где находится нужный нам элемент. Мы начинаем всегда с исследования
среднего элемента отрезка. Если искомое значение меньше среднего элемента, мы
переходим к поиску в верхней половине отрезка, где все элементы меньше только что
проверенного. Другими словами, значением Ub становится (M – 1) и на следующей
итерации мы работаем с половиной массива. Таким образом, в результате каждой
проверки мы вдвое сужаем область поиска. Так, в нашем примере, после первой итерации
область поиска – всего лишь три элемента, после второй остается всего лишь один
элемент. Таким образом, если длина массива равна 6, нам достаточно трех итераций,
чтобы найти нужное число.
Двоичный поиск - очень мощный метод. Если, например, длина массива равна 1023,
после первого сравнения область сужается до 511 элементов, а после второй - до 255.
Легко посчитать, что для поиска в массиве из 1023 элементов достаточно 10 сравнений.
Интерполяционный поиск элемента в массиве
Представьте себе, что Вы ищете слово в словаре. Если нужное слово начинается с
буквы 'А', вы наверное начнете поиск где-то в начале словаря. Когда найдена отправная
точка для поиска, ваши дальнейшие действия мало похожи на рассмотренные выше
методы.
Если Вы заметите, что искомое слово должно находиться гораздо дальше открытой
страницы, вы пропустите порядочное их количество, прежде чем сделать новую попытку.
Это в корне отличается от предыдущих алгоритмов, не делающих разницы между 'много
больше' и 'чуть больше'.
Мы приходим к алгоритму, называемому интерполяционным поиском: Если
известно, что К лежит между Kl и Ku, то следующую пробу делаем на расстоянии (u-l)(KKl)/(Ku-Kl) от l, предполагая, что ключи являются числами, возрастающими
приблизительно в арифметической прогрессии.
Интерполяционный поиск работает за log N операций, если данные распределены
равномерно. Как правило, он используется лишь на очень больших таблицах, причем
делается несколько шагов интерполяционного поиска, а затем на малом подмассиве
используется бинарный или последовательный варианты.
46
Алгоритмы выборки элементов из массивов данных.
Алгоритмы сортировки данных.
Алгоритм сортировки — это алгоритм для упорядочения элементов в списке. В
случае, когда элемент списка имеет несколько полей, поле, служащее критерием порядка,
называется ключом сортировки. На практике, в качестве ключа часто выступает число, а в
остальных полях хранятся какие-либо данные, никак не влияющие на работу алгоритма.
Критерии Эффективности
Единственного эффективнейшего алгоритма сортировки нет, ввиду множества
параметров оценки эффективности:
Время — основной параметр, характеризующий быстродействие алгоритма.
Называется также вычислительной сложностью. Для упорядочения важны худшее,
среднее и лучшее поведение алгоритма в терминах размера списка (n). Для типичного
алгоритма хорошее поведение — это O(n log n) и плохое поведение — это O(n²).
Идеальное поведение для упорядочения — O(n). Алгоритмы сортировки, использующие
только абстрактную операцию сравнения ключей всегда нуждаются по меньшей мере в
O(n log n) сравнениях в среднем;
Память — ряд алгоритмов требует выделения дополнительной памяти под
временное хранение данных. При оценке используемой памяти не будет учитываться
место, которое занимает исходный массив и независящие от входной последовательности
затраты, например, на хранение кода программы.
Устойчивость (stability) — устойчивая сортировка не меняет взаимного
расположения равных элементов.
Естественность поведения — эффективность метода при обработке уже
упорядоченных, или частично упорядоченных данных. Алгоритм ведёт себя естественно,
если учитывает эту характеристику входной последовательности и работает лучше.
Необходимо подчеркнуть, что степень роста наихудшего времени выполнения — не
единственный или самый важный критерий оценки алгоритмов и программ. Приведем
несколько соображений, позволяющих посмотреть на критерий времени выполнения с
других точек зрения:
1. Если создаваемая программа будет использована только несколько раз, тогда
стоимость написания и отладки программы будет доминировать в общей
стоимости программы, т.е. фактическое время выполнения не окажет
существенного влияния на общую стоимость. В этом случае следует
предпочесть алгоритм, наиболее простой для реализации.
2. Если программа будет работать только с «малыми» входными данными, то
степень роста времени выполнения будет иметь меньшее значение, чем
константа, присутствующая в формуле времени выполнения. Вместе с тем и
понятие «малости» входных данных зависит от точного времени
выполнения конкурирующих алгоритмов. Существуют алгоритмы, такие
как алгоритм целочисленного умножения, асимптотически самые
эффективные, но которые никогда не используют на практике даже для
больших задач, так как их константы пропорциональности значительно
превосходят подобные константы других, более простых и менее
«эффективных» алгоритмов.
3. Эффективные, но сложные алгоритмы могут быть нежелательными, если
готовые программы будут поддерживать лица, не участвующие в написании
этих программ. Будем надеяться, что принципиальные моменты технологии
47
создания эффективных алгоритмов широко известны, и достаточно сложные
алгоритмы свободно применяются на практике. Однако необходимо
предусмотреть возможность того, что эффективные, но «хитрые» алгоритмы
не будут востребованы из-за их сложности и трудностей, возникающих при
попытке в них разобраться.
4. Известно несколько примеров, когда эффективные алгоритмы требуют таких
больших объемов машинной памяти (без возможности использования более
медленных внешних средств хранения), что этот фактор сводит на нет
преимущество «эффективности» алгоритма.
5. В численных алгоритмах точность и устойчивость алгоритмов не менее важны,
чем их временная эффективность.
Сортировка выбором
Идея метода состоит в том, чтобы создавать отсортированную
последовательность путем присоединения к ней одного элемента за другим в правильном
порядке.
Будем строить готовую последовательность, начиная с левого конца массива.
Алгоритм состоит из n последовательных шагов, начиная от нулевого и заканчивая (n-1)м.
На i-м шаге выбираем наименьший из элементов a[i] ... a[n] и меняем его местами с
a[i]. Последовательность шагов при n=5 изображена на рисунке ниже.
Вне зависимости от номера текущего шага i, последовательность a[0]...a[i] (выделена
курсивом) является упорядоченной. Таким образом, на (n-1)-м шаге вся
последовательность, кроме a[n] оказывается отсортированной, а a[n] стоит на последнем
месте по праву: все меньшие элементы уже ушли влево.
template<class T>
void selectSort(T a[], long size) {
long i, j, k;
T x;
for( i=0; i < size; i++) {
k=i; x=a[i];
// i - номер текущего шага
for( j=i+1; j < size; j++) // цикл выбора наименьшего элемента
if ( a[j] < x ) {
k=j; x=a[j];
// k - индекс наименьшего элемента
}
a[k] = a[i]; a[i] = x;
// меняем местами наименьший с a[i]
}
}
Для нахождения наименьшего элемента из n+1 рассматримаемых алгоритм
совершает n сравнений. С учетом того, что количество рассматриваемых на очередном
шаге элементов уменьшается на единицу, общее количество операций:
n + (n-1) + (n-2) + (n-3) + ... + 1 = 1/2 * ( n2+n ) = Theta(n2).
48
Таким образом, так как число обменов всегда будет меньше числа сравнений, время
сортировки растет квадратично относительно количества элементов.
Алгоритм не использует дополнительной памяти: все операции происходят "на
месте".
Устойчив ли этот метод ? Прежде, чем читать далее, попробуйте получить ответ
самостоятельно.
Рассмотрим последовательность из трех элементов, каждый из которых имеет два
поля, а сортировка идет по первому из них.
Результат ее сортировки можно увидеть уже после шага 0, так как больше обменов
не будет. Порядок ключей 2a, 2b был изменен на 2b, 2a, так что метод неустойчив.
Если входная последовательность почти упорядочена, то сравнений будет столько
же, значит алгоритм ведет себя неестественно.
49
Сортировка пузырьком
Расположим массив сверху вниз, от нулевого элемента - к последнему.
Идея метода: шаг сортировки состоит в проходе снизу вверх по массиву. По пути
просматриваются пары соседних элементов. Если элементы некоторой пары находятся в
неправильном порядке, то меняем их местами.
После нулевого прохода по массиву "вверху" оказывается самый "легкий" элемент отсюда аналогия с пузырьком. Следующий проход делается до второго сверху элемента,
таким образом второй по величине элемент поднимается на правильную позицию...
Делаем проходы по все уменьшающейся нижней части массива до тех пор, пока в
ней не останется только один элемент. На этом сортировка заканчивается, так как
последовательность упорядочена по возрастанию.
template<class T>
void bubbleSort(T a[], long size) {
long i, j;
T x;
for( i=0; i < size; i++) {
for( j = size-1; j > i; j-- ) {
if ( a[j-1] > a[j] ) {
x=a[j-1]; a[j-1]=a[j]; a[j]=x;
}
}
// i - номер прохода
// внутренний цикл прохода
}
}
Среднее число сравнений и обменов имеют квадратичный порядок роста: Theta(n2),
отсюда можно заключить, что алгоритм пузырька очень медленен и малоэффективен.
Тем не менее, у него есть громадный плюс: он прост.
50
На практике метод пузырька, даже с улучшениями, работает, увы, слишком
медленно. А потому - почти не применяется.
51
Сортировка простыми вставками
Сортировка вставками (англ. insertion sort) — простой алгоритм сортировки. Хотя этот
метод сортировки намного менее эффективен, чем более сложные алгоритмы (такие как
быстрая сортировка), у него есть ряд преимуществ:
1. прост в реализации
2. эффективен на небольших наборах данных
3. эффективен на наборах данных, которые уже частично отсортированы
4. это устойчивый алгоритм сортировки (не меняет порядок элементов, которые уже
отсортированы)
5. может сортировать список по мере его получения
Сортировка простыми вставками в чем-то похожа на вышеизложенные методы.
Аналогичным образом делаются проходы по части массива, и аналогичным же
образом в его начале "вырастает" отсортированная последовательность...
Однако в сортировке пузырьком или выбором можно было четко заявить, что на i-м
шаге элементы a[0]...a[i] стоят на правильных местах и никуда более не переместятся.
Здесь же подобное утверждение будет более слабым: последовательность a[0]...a[i]
упорядочена. При этом по ходу алгоритма в нее будут вставляться (см. название метода)
все новые элементы.
Будем разбирать алгоритм, рассматривая его действия на i-м шаге. Как говорилось
выше, последовательность к этому моменту разделена на две части: готовую a[0]...a[i] и
неупорядоченную a[i+1]...a[n].
На следующем, (i+1)-м каждом шаге алгоритма берем a[i+1] и вставляем на нужное
место в готовую часть массива.
Поиск подходящего места для очередного элемента входной последовательности
осуществляется путем последовательных сравнений с элементом, стоящим перед ним.
В зависимости от результата сравнения элемент либо остается на текущем месте(вставка
завершена), либо они меняются местами и процесс повторяется.
Таким образом, в процессе вставки мы "просеиваем" элемент x к началу массива,
останавливаясь в случае, когда
1. Hайден элемент, меньший x или
2. Достигнуто начало последовательности.
template<class T>
void insertSort(T a[], long size) {
T x;
long i, j;
for ( i=0; i < size; i++) {
x = a[i];
// цикл проходов, i - номер прохода
// поиск места элемента в готовой последовательности
52
for ( j=i-1; j>=0 && a[j] > x; j--)
a[j+1] = a[j];
// сдвигаем элемент направо, пока не дошли
// место найдено, вставить элемент
a[j+1] = x;
}
}
Аналогично сортировке выбором, среднее, а также худшее число сравнений и
пересылок оцениваются как Theta(n2), дополнительная память при этом не используется.
Хорошим показателем сортировки является весьма естественное поведение: почти
отсортированный массив будет досортирован очень быстро. Это, вкупе с устойчивостью
алгоритма, делает метод хорошим выбором в соответствующих ситуациях.
Алгоритм можно слегка улучшить. Заметим, что на каждом шаге внутреннего цикла
проверяются 2 условия. Можно объединить из в одно, поставив в начало массива
специальный сторожевой элемент. Он должен быть заведомо меньше всех остальных
элементов массива.
Тогда при j=0 будет заведомо верно a[0] <= x. Цикл остановится на нулевом
элементе, что и было целью условия j>=0.
Таким образом, сортировка будет происходить правильным образом, а во
внутреннем цикле станет на одно сравнение меньше. С учетом того, что оно
производилось Theta(n2) раз, это - реальное преимущество. Однако, отсортированный
массив будет не полон, так как из него исчезло первое число. Для окончания сортировки
это число следует вернуть назад, а затем вставить в отсортированную последовательность
a[1]...a[n].
// сортировка вставками со сторожевым элементом
template<class T>
inline void insertSortGuarded(T a[], long size) {
T x;
long i, j;
T backup = a[0];
// сохранить старый первый элемент
setMin(a[0]);
// заменить на минимальный
// отсортировать массив
for ( i=1; i < size; i++) {
x = a[i];
for ( j=i-1; a[j] > x; j--)
a[j+1] = a[j];
a[j+1] = x;
}
// вставить backup на правильное место
for ( j=1; j<size && a[j] < backup; j++)
a[j-1] = a[j];
// вставка элемента
a[j-1] = backup;
}
Функция setmin(T& x) должна быть создана пользователем. Она заменяет x на
элемент, заведомо меньший(меньший или равный, если говорить точнее) всех элементов
массива.
53
Сортировка Шелла.
Сортировка Шелла является довольно интересной модификацией алгоритма
сортировки простыми вставками.
Рассмотрим следующий алгоритм сортировки массива a[0].. a[15].
1. Вначале сортируем простыми вставками каждые 8 групп из 2-х элементов (a[0],
a[8[), (a[1], a[9]), ... , (a[7], a[15]).
2. Потом сортируем каждую из четырех групп по 4 элемента (a[0], a[4], a[8], a[12]),
..., (a[3], a[7], a[11], a[15]).
В нулевой группе будут элементы 4, 12, 13, 18, в первой - 3, 5, 8, 9 и т.п.
3. Далее сортируем 2 группы по 8 элементов, начиная с (a[0], a[2], a[4], a[6], a[8],
a[10], a[12], a[14]).
4. В конце сортируем вставками все 16 элементов.
Очевидно, лишь последняя сортировка необходима, чтобы расположить все
элементы по своим местам. Так зачем нужны остальные ?
Hа самом деле они продвигают элементы максимально близко к соответствующим
позициям, так что в последней стадии число перемещений будет весьма невелико.
Последовательность и так почти отсортирована. Ускорение подтверждено
многочисленными исследованиями и на практике оказывается довольно существенным.
Единственной характеристикой сортировки Шелла является приращение расстояние между сортируемыми элементами, в зависимости от прохода. В конце
приращение всегда равно единице - метод завершается обычной сортировкой вставками,
но именно последовательность приращений определяет рост эффективности.
Использованный в примере набор ..., 8, 4, 2, 1 - неплохой выбор, особенно, когда
количество элементов - степень двойки. Однако гораздо лучший вариант предложил
Р.Седжвик. Его последовательность имеет вид
При использовании таких приращений среднее количество операций: O(n7/6), в
худшем случае - порядка O(n4/3).
Обратим внимание на то, что последовательность вычисляется в порядке,
противоположном используемому: inc[0] = 1, inc[1] = 5, ... Формула дает сначала меньшие
числа, затем все большие и большие, в то время как расстояние между сортируемыми
54
элементами, наоборот, должно уменьшаться. Поэтому массив приращений inc
вычисляется перед запуском собственно сортировки до максимального расстояния между
элементами, которое будет первым шагом в сортировке Шелла. Потом его значения
используются в обратном порядке.
При использовании формулы Седжвика следует остановиться на значении inc[s-1], если
3*inc[s] > size.
int increment(long inc[], long size) {
int p1, p2, p3, s;
p1 = p2 = p3 = 1;
s = -1;
do {
if (++s % 2) {
inc[s] = 8*p1 - 6*p2 + 1;
} else {
inc[s] = 9*p1 - 9*p3 + 1;
p2 *= 2;
p3 *= 2;
}
p1 *= 2;
} while(3*inc[s] < size);
return s > 0 ? --s : 0;
}
template<class T>
void shellSort(T a[], long size) {
long inc, i, j, seq[40];
int s;
// вычисление последовательности приращений
s = increment(seq, size);
while (s >= 0) {
// сортировка вставками с инкрементами inc[]
inc = seq[s--];
for (i = inc; i < size; i++) {
T temp = a[i];
for (j = i-inc; (j >= 0) && (a[j] > temp); j -= inc)
a[j+inc] = a[j];
a[j+inc] = temp;
}
}
}
Часто вместо вычисления последовательности во время каждого запуска процедуры,
ее значения рассчитывают заранее и записывают в таблицу, которой пользуются, выбирая
начальное приращение по тому же правилу: начинаем с inc[s-1], если 3*inc[s] > size.
55
Сортировка быстрая
Алгоритм
Быстрая сортировка использует стратегию «разделяй и властвуй». Шаги алгоритма
таковы:
 Выбираем в массиве некоторый элемент, который будем называть опорным
элементом.
 Операция разделения массива: реорганизуем массив таким образом, чтобы все
элементы, меньшие или равные опорному элементу, оказались слева от него, а все
элементы, большие опорного — справа от него.
 Рекурсивно упорядочиваем подсписки, лежащие слева и справа от опорного
элемента.
"Быстрая сортировка", хоть и была разработана более 40 лет назад, является
наиболее широко применяемым и одним их самых эффективных алгоритмов.
Метод основан на подходе "разделяй-и-властвуй". Общая схема такова:
1. из массива выбирается некоторый опорный элемент a[i],
2. запускается процедура разделения массива, которая перемещает все ключи,
меньшие, либо равные a[i], влево от него, а все ключи, большие, либо равные a[i] вправо,
3. теперь массив состоит из двух подмножеств, причем левое меньше, либо равно
правого,
4. для обоих подмассивов: если в подмассиве более двух элементов, рекурсивно
запускаем для него ту же процедуру.
В конце получится полностью отсортированная последовательность.
На входе массив a[0]...a[N] и опорный элемент p, по которому будет производиться
разделение.
1. Введем два указателя: i и j. В начале алгоритма они указывают, соответственно, на
левый и правый конец последовательности.
2. Будем двигать указатель i с шагом в 1 элемент по направлению к концу массива,
пока не будет найден элемент a[i] >= p. Затем аналогичным образом начнем
двигать указатель j от конца массива к началу, пока не будет найден a[j] <= p.
3. Далее, если i <= j, меняем a[i] и a[j] местами и продолжаем двигать i,j по тем же
правилам...
4. Повторяем шаг 3, пока i <= j.
Рассмотрим работу процедуры для массива a[0]...a[6] и опорного элемента p = a[3].
56
Теперь массив разделен на две части: все элементы левой меньше либо равны p, все
элементы правой - больше, либо равны p. Разделение завершено.
Общий алгоритм
Псевдокод.
quickSort ( массив a, верхняя граница N ) {
Выбрать опорный элемент p - середину массива
Разделить массив по этому элементу
Если подмассив слева от p содержит более одного элемента,
вызвать quickSort для него.
Если подмассив справа от p содержит более одного элемента,
вызвать quickSort для него.
}
Реализация на Си.
template<class T>
void quickSortR(T* a, long N) {
// На входе - массив a[], a[N] - его последний элемент.
long i = 0, j = N;
T temp, p;
// поставить указатели на исходные места
p = a[ N>>1 ];
// центральный элемент
// процедура разделения
do {
while ( a[i] < p ) i++;
while ( a[j] > p ) j--;
if (i <= j) {
temp = a[i]; a[i] = a[j]; a[j] = temp;
i++; j--;
}
} while ( i<=j );
// рекурсивные вызовы, если есть, что сортировать
if ( j > 0 ) quickSortR(a, j);
if ( N > i ) quickSortR(a+i, N-i);
}
Каждое разделение требует, очевидно, Theta(n) операций. Количество шагов
деления(глубина рекурсии) составляет приблизительно log n, если массив делится на
57
более-менее равные части. Таким образом, общее быстродействие: O(n log n), что и имеет
место на практике.
Однако, возможен случай таких входных данных, на которых алгоритм будет
работать за O(n2) операций. Такое происходит, если каждый раз в качестве центрального
элемента выбирается максимум или минимум входной последовательности. Если данные
взяты случайно, вероятность этого равна 2/n. И эта вероятность должна реализовываться
на каждом шаге... Вообще говоря, малореальная ситуация.
Метод неустойчив. Поведение довольно естественно, если учесть, что при частичной
упорядоченности повышаются шансы разделения массива на более равные части.
Сортировка использует дополнительную память, так как приблизительная глубина
рекурсии составляет O(log n), а данные о рекурсивных подвызовах каждый раз
добавляются в стек.
if ( j > CUTOFF )
58
quickSortR(a, j);
Сортировка поразрядная
Пусть имеем максимум по k байт в каждом ключе (хотя за элемент сортировки
вполне можно принять и что-либо другое, например слово - двойной байт, или буквы,
если сортируются строки). k должно быть известно заранее, до сортировки.
Разрядность данных (количество возможных значений элементов) - m - также
должна быть известна заранее и постоянна. Если мы сортируем слова, то элемент
сортировки - буква, m = 33. Если в самом длинном слове 10 букв, k = 10. Обычно мы
будем сортировать данные по ключам из k байт, m=256.
Пусть у нас есть массив source из n элементов по одному байту в каждом.
Для примера можете выписать на листочек массив source = <7, 9, 8, 5, 4, 7, 7>, и
проделать с ним все операции, имея в виду m=9.
1. Составим таблицу распределения. В ней будет m (256) значений и заполняться она
будет так:
for i := 0 to Pred(255) Do distr[i]:=0;
for i := 0 to Pred(n) Do distr[source[i]] := distr[[i]] + 1;
Для нашего примера будем иметь distr = <0, 0, 0, 0, 1, 1, 0, 3, 1, 1>, то есть i-ый
элемент distr[] - количество ключей со значением i.
2. Заполним таблицу индексов:
index: array[0 .. 255] of integer;
index[0]:=0;
for i := 1 to Pred(255) Do index[i]=index[i-1]+distr[i-1];
В index[ i ] мы поместили информацию о будущем количестве символов в
отсортированном массиве до символа с ключом i.
Hапример, index[8] = 5 : имеем <4, 5, 7, 7, 7, 8>.
3. А теперь заполняем новосозданный массив sorted размера n:
for i := 0 to Pred(n) Do Begin
sorted[ index[ source[i] ] ]:=source[i];
{
попутно изменяем index уже вставленных
символов, чтобы
одинаковые ключи шли один за другим:
}
index[ source[i] ] := index[ source[i] ] +1;
End;
Итак, мы научились за O(n) сортировать байты. А от байтов до строк и чисел - 1 шаг.
Пусть у нас в каждом числе - k байт.
Будем действовать в десятичной системе и сортировать обычные числа ( m = 10 ).
сначала они в сортируем по младшему на один беспорядке: разряду: выше: и еще
раз:
523 523 523 088
153 153 235 153
59
088 554 153 235
554 235 554 523
235 088 088 554
Hу вот мы и отсортировали за O(k*n) шагов. Если количество возможных различных
ключей ненамного превышает общее их число, то 'поразрядная сортировка' оказывается
гораздо быстрее даже 'быстрой сортировки'!
Пример:
Const
n = 8;
Type
arrType = Array[0 .. Pred(n)] Of Byte;
Const
m = 256;
a: arrType =
(44, 55, 12, 42, 94, 18, 6, 67);
Procedure RadixSort(Var source, sorted: arrType);
Type
indexType = Array[0 .. Pred(m)] Of Byte;
Var
distr, index: indexType;
i: integer;
begin
fillchar(distr, sizeof(distr), 0);
for i := 0 to Pred(n) do
inc(distr[source[i]]);
index[0] := 0;
for i := 1 to Pred(m) do
index[i] := index[Pred(i)] + distr[Pred(i)];
for i := 0 to Pred(n) do
begin
sorted[ index[source[i]] ] := source[i];
index[source[i]] := index[source[i]]+1;
end;
end;
var
b: arrType;
begin
RadixSort(a, b);
end.
Сортировка подсчетом
Пусть у нас есть массив source из n десятичных цифр ( m = 10 ).
Например, source[7] = { 7, 9, 8, 5, 4, 7, 7 }, n=7. Здесь положим const k=1.
1. Создать массив count из m элементов(счетчиков).
60
2. Присвоить count[i] количество элементов source, равных i. Для этого:
a. проинициализовать count[] нулями,
b. пройти по source от начала до конца, для каждого числа увеличивая элемент
count с соответствующим номером.
c.
for( i=0; i<n; i++)
count [ source[i] ]++
В нашем примере count[] = { 0, 0, 0, 0, 1, 1, 0, 3, 1, 1 }
3. Присвоить count[i] значение, равное сумме всех элементов до данного:
count[i] = count[0]+count[1]+...count[i-1].
В нашем примере count[] = { 0, 0, 0, 0, 1, 2, 2, 2, 5, 6 }
Эта сумма является количеством чисел исходного массива, меньших i.
4. Произвести окончательную расстановку.
Для каждого числа source[i] мы знаем, сколько чисел меньше него - это значение
хранится в count[ source[i] ]. Таким образом, нам известно окончательное место
числа в упорядоченном массиве: если есть K чисел меньше данного, то оно должно
стоять на на позиции K+1.
Осуществляем проход по массиву source слева направо, одновременно заполняя
выходной массив dest:
for ( i=0; i<n; i++ ) {
c = source[i];
dest[ count[c] ] = c;
count[c]++; // для повторяющихся чисел
}
Таким образом, число c=source[i] ставится на место count[c]. На этот случай, если
числа повторяются в массиве, предусмотрен оператор count[c]++, который увеличивает
значение позиции для следующего числа c, если таковое будет.
Циклы занимают (n + m) времени. Столько же требуется памяти.
Итак, мы научились за (n + m) сортировать цифры. А от цифр до строк и чисел - 1
шаг. Пусть у нас в каждом ключе k цифр ( m = 10 ). Аналогично случаю со списками
отсортируем их в несколько проходов от младшего разряда к старшему.
Общее количество операций, таким образом, ( k(n+m) ), при используемой
дополнительно памяти (n+m). Эта схема допускает небольшую оптимизацию. Заметим,
что сортировка по каждому байту состоит из 2 проходов по всему массиву: на первом
шаге и на четвертом. Однако, можно создать сразу все массивы count[] (по одному на
каждую позицию) за один проход. Неважно, как расположены числа - счетчики не
меняются, поэтому это изменение корректно.
Таким образом, первый шаг будет выполняться один раз за всю сортировку, а значит,
общее количество проходов изменится с 2k на k+1.
61
Download