["Задания практикума на ЭВМ (1 курс)". Методическая разработка (составители Н.П.Трифонов и В.Н.Пильщиков). М.: МГУ, 1992.] ЗАДАНИЕ N4 "ИНТЕРФЕЙС ПРОГРАММЫ СОРТИРОВКИ" (язык Паскаль). ПОСТАНОВКА ЗАДАЧИ Требуется дополнить программу сортировки, реализованную в предыдущем задании, подсистемой диалогового взаимодействия (интерфейсом) с пользователем. Объединенная система должна предусматривать следующий сценарий работы: Этап 1. Выбор метода. На экран выдается перечень (меню) названий различных (5-7) методов сортировки. Пользователь выбирает для дальнейшей работы один из них либо прекращает работу с системой. Этап 2. Выбор режима. После выбора пользователем метода сортировки система запрашивает его о режиме дальнейшей работы - режиме отладки или режиме счета. (Режим отладки предназначен для демонстрации правильности работы выбранной процедуры сортировки, а режим счета - для экспериментального определения характеристик метода сортировки.) Пользователь выбирает нужный режим, но может и вернуться на предыдущий этап. Этап 3. 3а) Режим отладки. В этом режиме система прежде всего просит пользователя указать длину последовательности, подлежащей сортировке, а затем задать все ее элементы. Система упорядочивает эту последовательность выбранным методом, после чего выдает ее на экран. Далее пользователь может либо задать новую последовательность, либо вернуться на предыдущий этап. 3б) Режим счета. Если пользователь выбрал режим счета, то система запрашивает у него длину последовательностей, которые будут упорядочиваться, после чего сама генерирует несколько последовательностей заданной длины и сортирует каждую из них выбранным методом. Результатом является таблица, в которой для каждой последовательности указано число сравнений, число перемещений и время работы процедуры сортировки, а также усредненные значения этих характеристик. Далее пользователь может либо задать новую длину, либо вернуться на предыдущий этап. УТОЧНЕНИЕ ИНТЕРФЕЙСА 1. Перечень названий методов сортировки должен быть реализован в виде вертикального меню - в виде окна, в котором друг под другом выписаны названия методов. Вначале должно быть выделено первое из этих названий, т.е. оно должно быть высвечено особым цветом. При нажатии пользователем клавиши со стрелкой вниз или вверх система должна выделить следующее или предыдущее (по кругу) название, сняв, естественно, выделение с текущего названия. Нажатие клавиши Enter (Return) означает, что пользователь выбрал тот метод, название которого сейчас выделено. (Замечание: поскольку реально в системе реализовано лишь два метода сортировки, при выборе нереализованного метода система должна как-то сообщить об этом, например выдачей сообщения "Метод не реализован", и позволить пользователю выбрать иной метод.) При работе с меню система должна также учитывать клавишу Esc, нажатие которой означает конец работы с системой. На другие клавиши система в это время не должна реагировать. 2. Запрос режима работы системы (отладка или счет) должен быть реализован следующим образом. На экране появляется окно с текстом "РЕЖИМ: ОТЛАДКА". Если пользователь нажимает клавишу "пробел", тогда слово "ОТЛАДКА" должно замениться на слово "СЧЕТ". При новом нажатии этой клавиши на экране снова появляется слово "ОТЛАДКА" и т.д. Нажатие клавиши Enter означает выбор того режима, название которого указано сейчас в окне. Допустимо также нажатие клавиши Esc, что означает отказ от выбора режима и возврат на предыдущий этап. На иные клавиши система в это время не должна реагировать. 3. Запрос числа (длины последовательности) должен быть реализован следующим образом. На экране появляется окно, например, с текстом "ДЛИНА ПОСЛЕДОВАТЕЛЬНОСТИ: ", за которыми выделено тем же фоновым цветом, что и этот текст, "поле ввода" - 2-4 позиции, в которых пользователь и должен набрать число. Курсор устанавливается в начальную позицию поля, и пользователь набирает число (система не должна разрешать ему выходить за рамки этого поля). Нажатие клавиши Enter (при любом положении курсора) означает, что ввод числа окончен. Система вводит набранные цифры и переводит их в соответствующую числовую величину. Если число набрано верно и не выходит за определенный диапазон, система продолжает свою работу, иначе система каким-то образом сообщает об ошибке и дает пользователю возможность исправить набранный текст. Во время набора числа (до нажатия клавиши Enter) или в случае обнаружения ошибки в ранее набранном числе пользователь должен иметь возможность вносить изменения в набранный текст. Рекомендуется использовать следующие клавиши для редактирования вводимого текста: - движение курсора на одну позицию влево или вправо (не выходя за границы поля ввода) Del - удаление символа, на который показывает курсор (со сдвигом влево на одну позицию правой части текста) Backspace - удаление символа слева от курсора (если только курсор не в начале поля ввода) и перемещение курсора на одну позицию влево Ins - переключение с режима вставки на режим замены или наоборот (исходный режим - вставка) В режиме замены введенный обычный символ (цифра, буква и т.п.) заменяет на экране тот символ, на который указывает курсор. В режиме же вставки часть текста (от курсора и вправо) сдвигается на одну позицию вправо и в освободившееся место вставляется введенный символ. Далее (в любом режиме) курсор перемещается на позицию вправо, если только он не находится в конце поля ввода. При вводе числа система помимо указанных выше клавиш должна реагировать и на клавишу Esc, нажатие которой означает отказ от ввода и возврат системы на предыдущий этап. На нечисловые символы реакция системы может быть двоякой: либо она не реагирует на них (не высвечивает на экране), либо допускает их ввод, а проверку на правильность записи числа осуществляет лишь по окончании ввода. Рекомендуется использовать второй вариант как более универсальный. 4. В режиме отладки пользователь должен набрать заказанное им число элементов (дат) последовательности, подлежащей сортировке. Здесь рекомендуется поступить следующим образом. Система выделяет определенным цветом на экране нужное число небольших окон, размер которых должен допускать ввод самого "длинного" элемента. Вначале курсор устанавливается в первую позицию первого окна, и пользователь набирает первый элемент, после чего нажимает клавишу Enter. Далее система переносит курсор в начало второго окна, пользователь набирает следующий элемент и т.д. (Можно предоставить пользователю право вводить элементы не последовательно, а в любые указанные им окна и разрешить ему возвращаться к ранее набранным элементам с целью их изменения.) Ввод элементов должен осуществляться аналогично вводу длины последовательности (с возможностью редактирования). Формат записи элементов-дат может быть, например, таким: dd.mm.yy , где dd - число (1-2 цифры), mm - номер месяца (1-2 цифры) и yy - две последние цифры года. Анализ правильности записи даты следует проводить только после нажатия клавишы Enter. 5. Все другие аспекты работы системы (форматы вывода таблицы в режиме счета и отсортированной последовательности в режиме отладки и т.п.) определяются самостоятельно разработчиком системы. Он может также предусмотреть выдачу на экран (в верхней или нижней строке) подсказок - какие управляющие клавиши может сейчас нажимать пользователь и что они означают; он может очищать экран при переходе от одного этапа работы системы к другому, а может и уместить все нужные окна на одном экране, и т.д. СОДЕРЖАНИЕ ОТЧЕТА 1. Постановка задачи. 2. Описание правил работы с системой (инструкция пользователю). 3. Листинг интерфейсной части системы на языке Паскаль. ЛИТЕРАТУРА 1. Коутс Р., Влейминк И. Интерфейс "человек-компьютер" - М.: Мир, 1990. 2. Фаронов В.В. Программирование на персональных ЭВМ в среде ТУРБО ПАСКАЛЬ. - М.: изд-во МГТУ, 1990. МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ 1. Ниже перечислен, на примере системы программирования Турбо Паскаль (версия 5.0), набор простейших операций, необходимых для реализации интерфейсной части системы сортировки. Некоторые из этих процедур и функций входят в состав стандартного модуля CRT системы программирования, другие же (они помечены звездочкой) реализованы специально для данного задания и включены в модуль CRT1. При описании операций через x обозначен номер колонки экрана (окна), а через y - номер строки; в связи с этим запись (x,y) обозначает точку в x-й колонке y-й строки экрана (текущего окна). textmode(3) - установить цветной текстовый режим экрана из 25 строк по 80 позиций в каждой textcolor(n:byte) - установить цвет с номером n (от 0 до 15) как цвет символов (передний цвет) для всех последующих выдач на экран textbackground(n:byte) - установить цвет с номером n (от 0 до 7) как фоновый цвет для всех последующих выдач на экран * getcolors(var fc,bc:byte) - присвоить параметрам fc и bc номера текущих переднего и фонового цветов * window(x1,y1,x2,y2:byte) - объявить прямоугольную часть экрана с левым верхним углом в точке (x1,y1) и правым нижним углом в точке (x2,y2) текущим окном (Замечание: все последующие действия с экраном ведутся только в рамках окна, как будто бы нет иной части экрана; в частности, все координаты точек отсчитываются от левого верхнего угла окна, который (угол) имеет координаты (1,1); исключение составляет обращение к процедуре window, координаты для которой - всегда абсолютные, т.е. отсчитываются от верхнего левого угла экрана.) windcoord(var x1,y1,x2,y2:byte) - запрос координат текущего окна clrscr - очистка текущего окна текущим фоновым цветом (во все позиции окна заносятся пробелы) gotoxy(x,y:byte) - установить курсор в точку (x,y) окна * wherexy(var x,y:byte) - присвоить параметрам x и y координаты текущей позиции курсора * getch(x,y:byte):char - значением этой функции является символ, высвечиваемый в точке (x,y) окна * getattr(x,y:byte):byte - значением функции является цветовой атрибут точки (x,y) окна (Замечание: цветовой атрибут - это величина fc+16*bc+128*blink, где fc - номер переднего цвета, bc – номер фонового цвета, а blink равен 1, если символ мерцает, и равен 0 в противном случае.) * putch(x,y:byte; c:char) - записать символ c в точку (x,y) окна, не меняя цветовой атрибут в этой точке * putattr(x,y:byte; a:byte) - изменить цветовой атрибут точки (x,y) окна на новое значение a (сам символ в точке не меняется) * inkey(var c:char; var spec:boolean) - ввод без эха (без высвечивания на экране) символа первой из клавиш, нажатых на клавиатуре, и присваивание его параметру c (если клавиша еще не была нажата, процедура ждет нажатия любой клавиши); при нажатии "обычной" клавиши параметру spec присваивается значение false, при нажатии управляющей клавиши – значение true (значения параметра c для некоторых управляющих клавиш: Enter - #13, Esc - #27, Del - #83, Backspace - #8, - #75, - #77) Замечание: стандартные процедуры языка Паскаль write и writeln при выводе на экран всегда начинают вывод с позиции курсора и не выходят за рамки текущего окна; выдаваемый текст высвечивается цветами, установленными последними процедурами textcolor и textbackground. 2. На основе указанных процедур и функций рекомендуется реализовать более крупные операции для работы с экраном, перечисленные ниже (названия процедур и их параметры - примерные). Под "полем" понимается часть одной строки окна; поле задается тремя параметрами: x, y - координатами начальной точки поля, n - длиной поля. putfield(x,y,n:byte; s:string) - записать в поле, определяемое параметрами x, y и n, символы строки s; если длина s больше n, то лишние справа символы s не выводятся, если меньше - в конец поля дописываются пробелы (в частности, при пустой строке s происходит очистка поля) getfield(x,y,n:byte; var s:string) - присвоить параметру s все символы из поля, задаваемого параметрами x, y иn paintfield(x,y,n:byte; a:byte) - закрасить указанное поле цветами, определяемыми атрибутом a (не меняя символы этого поля) readfield(x,y,n:byte; stopkeys:string; var s:string; var key:char) - ввод любого текста (с возможностью редактирования) в рамках поля, заданного параметрами x, y и n (т.е. с запретом выходить за рамки поля) и присваивание введенного текста параметру s; в параметре stopkeys перечисляютя все управляющие клавиши (Enter, Esc, ...), нажатие которых означает конец ввода; та из них, которая была действительно нажата, присваивается параметру key. (Замечание: данная процедура должна вначале установить курсор в 1-ю позицию поля ввода, но не должна предварительно очищать это поле; если надо, очистку поля следует делать до обращения к процедуре.) На основе перечисленных процедур уже достаточно просто реализуется интерфейсная часть системы (если избегать "излишеств"). 3. Рекомендуется разделить всю систему на несколько модулей, в частности, выделить интерфейсную часть в отдельный модуль.