
- •Технология программирования
- •Технология программирования
- •Оглавление
- •§1. Классификация и эволюция программного обеспечения
- •§2. Модульное и объектно-ориентированное программирование
- •Основные понятия ооп
- •Составные части объектного подхода
- •Инкапсуляция. Свойства
- •Наследование. Методы
- •Полиморфизм
- •§3. Визуальная среда программирования Структура проекта Delphi
- •Библиотека компонентов Delphi
- •Класс tButton (кнопки)
- •Класс tShape (фигуры)
- •§4. Основные типы данных в языке Паскаль
- •Класс tLabel (надписи)
- •Класс tEdit
- •Класс tMemo
- •Класс tMainMenu
- •Стандартные диалоги
- •Классы tOpenDialog и tSaveDialog
- •Класс tFontDialog
- •Инструкция case
- •§6. Программирование циклических алгоритмов
- •Цикл с параметром. Инструкция for
- •Цикл с предусловием. Инструкция while
- •Цикл с постусловием. Инструкция repeat … until
- •§7. Простейшие вычислительные методы
- •Метод прямоугольников
- •Метод Монте-Карло
- •Метод деления пополам
- •§8. Процедуры и функции
- •§9. Одномерные массивы
- •Класс tListBox
- •Класс tComboBox
- •§10. Двумерные и многомерные массивы
- •Класс tStringGrid
- •Алгоритмы поиска наименьшего и наибольшего элемента
- •§11. Алгоритмы поиска и сортировки. Понятие вычислительной сложности алгоритма
- •Алгоритм простого перебора
- •Алгоритм бинарного поиска
- •Алгоритм сортировки методом «пузырька»
- •Алгоритм сортировки включением
- •Понятие вычислительной сложности алгоритма
- •§12. Обработка исключительных ситуаций
- •§13. Программирование процессов реального времени
- •Класс tTimer
- •§14. Графическая подсистема Delphi Класс tImage
- •Класс tCanvas
- •§15. Динамическое создание компонентов. Конструкторы и деструкторы
- •§16. Тестирование и отладка программ
- •Методы тестирования программ
- •Средства отладки программ в Delphi
- •Трассировка программы
- •Точки останова программы
- •Наблюдение значений переменных
- •§17. Жизненный цикл программного обеспечения
- •Последовательный (каскадный) тип
- •Эволюционный (спиральный) тип
- •Библиографический список
- •Технология программирования
- •Редактор с.В.Пилюгина
- •620034, Екатеринбург, ул. Колмогорова, 66, УрГупс Редакционно-издательский отдел
Алгоритм сортировки включением
Из сказанного выше ясно, что в информационных системах большие массивы данных должны быть упорядочены. При добавлении новых данных упорядоченность должна сохраняться. Можно, конечно, добавив одну запись в конец массива, произвести сортировку методом пузырька. Однако есть более рациональный путь, называемый сортировкой включением.
Идея метода заключается в том, чтобы найти для элемента нужную позицию в массиве, поместить его туда, а оставшийся «хвост» массива сдвинуть вниз на одну позицию.
Рассмотрим этот метод на примере такой задачи: пусть в переменной new_stud хранится фамилия студента, которую нужно добавить в упорядоченный по алфавиту массив stud, не нарушая алфавитного порядка. Количество студентов в списке n.
Фрагмент программы может выглядеть примерно так:
i:=1; {начинаем просмотр с первого элемента списка}
while new_stud > stud[i] do i:=i+1;
{просматриваем список студентов, пропуская стоящих по алфавиту раньше вновь введенного, в позиции i должен стоять новый студент}
for j:=n downto i do
stud[j+1] := stud[j];{сдвигаем «хвост»}
stud[i] := new_stud;{помещаем нового студента в нужную позицию}
Отметим, что массив должен быть рассчитан на добавления, т. е. его размер должен позволять добавлять новые элементы.
Этот алгоритм дает линейную зависимость времени работы от длины массива.
Понятие вычислительной сложности алгоритма
Рассматривая
различные алгоритмы обработки массивов,
мы каждый раз обсуждали характер
зависимости времени работы от количества
элементов в массиве (линейная, квадратичная,
логарифмическая и т.п.). Эта зависимость
и называется вычислительной
сложностью алгоритма.
Так, поиск наибольшего и наименьшего
значения и вычисление суммы элементов
имеют линейную сложность, простые методы
сортировки – квадратичную. Существует
более эффективный, но и более сложный
для программирования метод сортировки,
имеющий вычислительную сложность
(больше линейной, но меньше квадратичной).
При решении более сложных задач
встречаются алгоритмы с кубической и
с большей сложностью.
Итак, вычислительная сложность алгоритма отражает характер зависимости времени выполнения алгоритма от количества обрабатываемых данных.
§12. Обработка исключительных ситуаций
При работе любой не слишком примитивной программы может возникнуть ситуация, при которой дальнейшая работа становится невозможной. Например, преобразование строки в число не удается выполнить, поскольку строка содержит не цифры, а буквы, или не удается выполнить запись файла на диск, так как недостаточно свободного места, и т. п. Можно решить эту проблему введением многочисленных проверок, предотвращающих некорректные действия в случае возникновения нештатной ситуации. Но это сильно запутывает программу, затемняя четкую структуру основного алгоритма.
В языке Object Pascal предложен красивый выход из положения: вынести всю обработку исключительных ситуаций (ИС) из основной части, выделив в составе блока кода:
собственно реализацию алгоритма,
обработчик ИС,
заключительную часть, выполняющую необходимые действия по корректному завершению вне зависимости от того, возникали ИС или нет.
Для этого в языке существуют конструкции try…finally и try … except.
Синтаксис блока try…finally таков:
try
<оператор>
<оператор>
…
finally
<оператор>
…
end;
Следующие за try операторы выполняются в обычном порядке. Если за это время не произошло никаких ИС, далее выполняются те операторы, которые стоят после finally. В случае, если между try и finally произошла ИС, управление немедленно передается на оператор(ы) после finally. Например, следующий фрагмент кода
a:=StrToInt(Edit1.Text); может привести к аварийному завершению программы, если в окно ввода Edit1 введено «1,2». Можно исправить ситуацию таким способом:
try
a:=StrToInt(Edit1.Text);
finally
Edit2.Text:=’OK’;
end;
Если преобразование происходит нормально, ИС не возникает. Если же ИС возникает, никаких сбоев в работе программы не наблюдается. В любом случае в окне Edit2 появляется надпись OK. Этот пример собственно обработки ИС не содержит, здесь важен только факт ее возникновения. Для реакции на конкретный тип ситуации применяется блок try … except. Синтаксис его следующий:
try
<оператор>
<оператор>
…
except
on Exception1 do <оператор>
on Exception2 do <оператор>
…
else {может отсутствовать}
<оператор> {обработчик ИС по умолчанию}
end;
Здесь, как и в предыдущем случае, выполнение блока начинается с секции try. В случае отсутствия исключительных ситуаций только она и выполняется. Секция except получает управление в случае возникновения ИС. Обработчик ИС состоит из набора директив on … do, задающих реакцию приложения на определенную ситуацию. Каждая директива связывает ситуацию (on…), заданную своим именем, с группой операторов (do…). При возникновении ИС директивы просматриваются последовательно, в порядке их появления. Если возникла ситуация, не определенная ни одной из директив, вызывается обработчик ИС по умолчанию. После обработки происходит выход из блока, и управление обратно в секцию try не передается.
Вернемся к предыдущему примеру. Для корректной работы программы следовало бы в случае возникновения ИС выдать сообщение об этом, а не бессмысленное в данном случае OK. Сделать это можно следующим образом:
try
a:=StrToInt(Edit1.Text);
except
on EConvertError do Edit1.Text:='Ошибка ввода';
end;
Программные коды всех исключительных ситуаций включены в объектный тип Exception и содержатся в модуле SysUtils.
Приведем некоторые важные ИС:
Ситуация |
Возникает при условии |
EConvertError |
Невозможность преобразования данных |
EOutOfResources |
Нехватка системных ресурсов |
ИС целочисленной математики | |
EDivByZero |
Попытка деления на ноль |
ERangeError |
Число или выражение выходит за допустимый диапазон |
EIntOverflow |
Целочисленное переполнение |
ИС математики с плавающей точкой | |
EInvalidOp |
Неверная операция |
EZeroDivide |
Попытка деления на ноль |
EOverflow |
Переполнение с плавающей точкой |
Отметим, что обработка ИС, описанная в блоке try, будет выполняться должным образом только при запуске exe-файла приложения прямо из Windows. При запуске из среды Delphi обработка ИС будет перехвачена, и вы увидите сообщение Delphi. В этом сообщении, кстати, можно узнать имя возникшей ИС.