|
Вспомогательные типы и процедуры задачника
Описанные на данной странице типы и процедуры будут доступны в программе,
если к ней с помощью оператора uses подключен модуль PT4.
При выполнении заданий на языке PascalABC.NET можно также использовать
средства задачника, общие для всех реализаций языка Pascal. Эти средства
описаны в разделе «Pascal | Процедуры задачника»
Инициализация заданий, ввод-вывод данных
procedure Task(Name: string);
Процедура инициализирует задание с именем Name. Она должна вызываться в
начале программы, выполняющей это задание (до вызова методов ввода-вывода).
Если в программе, подключившей модуль задачника, не указана процедура
Task, то при запуске программы будет выведено окно с сообщением «Не
вызвана процедура Task с именем задания».
Имя задания Name должно включать имя группы заданий и порядковый номер в
пределах группы (например, 'Begin3' ). Регистр букв в имени группы может быть
произвольным. Если указана неверная группа, то программа выведет сообщение об
ошибке «Указана неверная тема задания»
(список всех доступных групп можно получить с помощью программных модулей PT4Demo и PT4Load). Если указан
недопустимый номер задания, то программа выведет сообщение, в котором будет
указан диапазон допустимых номеров для данной группы. Если после имени задания
в параметре Name указан суффикс «?» (например, 'Begin3?' ), то
программа будет работать в демонстрационном режиме.
Начиная с версии 4.8, процедура Task может также использоваться для
генерации и вывода на экран html-страницы с текстом задания или группы заданий.
Для этого необходимо указать в качестве параметра Name имя конкретного задания или группы
заданий и суффикс «#», например, 'Begin3#' или
'Begin#' . Дополнительные сведения о генерации html-страниц с описаниями заданий приводятся
в разделе, посвященном демонстрационному режиму задачника.
Начиная с версии 4.13, задачник обеспечивает автоматическое тестирование программы на нескольких
наборах исходных данных при ее однократном запуске. Для отключения этой возможности достаточно
указать в параметре Name после имени задания суффикс «!» (например, 'Begin3!' );
в этом случае при запуске программы она будет протестирована на единственном наборе исходных данных,
и для проверки правильности решения программу потребуется запустить несколько раз (как в предыдущих версиях
задачника).
Если процедура Task вызывается в программе несколько раз, то все
последующие ее вызовы игнорируются. Исключением является ситуация, когда
процедура используется для генерации html-страницы с описанием нескольких заданий или групп
заданий; в этом случае учитываются все вызовы данной процедуры.
Начиная с версии 4.12, параметр Name может содержать суффикс «_ru»
или «_en», позволяющий явным образом задать язык интерфейса
(русский или английский соответственно) для окна задачника и выполняемого задания.
В версиях 4.124.14 специальные суффиксы «?», «#» и «!» должны указываться перед данным суффиксом,
например, 'Begin3#_en' ; начиная с версии 4.15, суффиксы могут указываться в любом порядке.
В случае нескольких вызовов процедуры Task (для генерации
html-страницы) учитывается только суффикс, указанный при первом вызове процедуры.
При отсутствии суффикса используется язык интерфейса, определенный в качестве основного для данного рабочего каталога
(в варианте задачника для среды PascalABC.NET основной язык интерфейса совпадает с языком интерфейса,
установленным для этой среды с помощью команды «Сервис | Настройки»).
function ReadBoolean: boolean;
function ReadInteger: integer;
function ReadReal: real;
function ReadChar: char;
function ReadString: string;
function ReadNode: Node;
Каждая функция возвращает значение очередного элемента исходных данных.
Эти функции должны вызываться после вызова процедуры Task; в случае их
вызова до вызова процедуры Task при запуске программы будет выведено сообщение
об ошибке «В начале программы не вызвана процедура Task с именем
задания».
Используемая функция ввода должна соответствовать типу очередного
элемента исходных данных; в противном случае выводится сообщение об ошибке
«Неверно указан тип при вводе исходных данных» (такое сообщение
будет выведено, например, если очередной элемент данных является символом, а для
его ввода используется функция ReadInteger).
При попытке ввести больше исходных данных, чем это предусмотрено в
задании, выводится сообщение об ошибке «Попытка ввести лишние исходные
данные». Если исходные данные, необходимые для решения задания, введены
не полностью, то выводится сообщение «Введены не все требуемые исходные
данные».
Функции ввода удобно вызывать непосредственно при описании инициализируемых переменных, что позволяет
осуществлять автоматический вывод типа, например:
var n := ReadInteger;
var a := ReadReal;
Предусмотрены варианты этих функций, возвращающие кортежи исходных данных указанного типа, состоящие из
2, 3 и 4 элементов. Например, для ввода вещественных чисел
можно использовать не только функцию ReadReal, но и функции ReadReal2, ReadReal3 и ReadReal4:
var (a, b, c) := ReadReal3;
В версии 4.19 набор методов ввода был дополнен методами,
упрощающими ввод линейных и двумерных структур данных. Каждая группа методов обеспечивает
чтение структур с элементами одного из трех основных типов T: integer, real и string. Реализованы шесть групп
методов, описанных ниже.
Методы ввода линейных структур представлены группами ReadArr..., ReadSeq... и ReadList...
(например, ReadArrInteger, ReadSeqReal, ReadListString).
Они могут вызываться без параметров (и в этом случае вначале выполняют чтение целого числа размера структуры,
после чего считывают все ее элементы) или с одним параметром целого типа count, определяющим размер структуры
(и в этом случае считывают только сами элементы).
Методы группы ReadArr... возвращают одномерный массив array of T, методы группы ReadSeq...
последовательность sequence of T, методы группы ReadList... список на базе массива List<T>.
Методы ввода двумерных структур представлены группами ReadMatr..., ReadArrArr... и ReadListList...
(например, ReadMatrInteger, ReadArrArrReal, ReadListListString).
Они могут вызываться без параметров и в этом случае вначале выполняют чтение двух целых чисел,
определяющих размеры структуры по первому (число строк) и по второму индексу (число столбцов),
после чего считывают все элементы по строкам. При указании одного целочисленного параметра m он определяет и число строк,
и число столбцов (т. е. структура соответствует квадратной матрице порядка m); метод считывает только элементы
структуры. При указании двух целочисленных параметров m и n первый из них определяет число строк, второй число
столбцов, в этом случае метод считывает только элементы структуры.
Методы группы ReadMatr... возвращают двумерный массив array [,] of T, методы группы ReadArrArr...
массив массивов array of array of T, методы группы ReadListList... список списков List<List<T>>.
Для вывода результатов в среде PascalABC.NET можно использовать
стандартные процедуры Write и Print с любым количеством параметров. При этом в качестве параметров
можно указывать как скалярные данные, так и кортежи, а также линейные и двумерные структуры данных.
Кроме того, для вывода структур данных можно использовать методы Write и Print
(например, для вывода массива a можно использовать оператор a.Print). Для вывода линейных структур
предусмотрены дополнительные методы WriteAll и PrintAll, при вызове которых вначале выводится размер
структуры, а затем ее элементы.
Как и функции ввода, процедуры вывода должны вызываться после
вызова процедуры Task; в противном случае при запуске программы будет выведено
сообщение «В начале программы не вызвана процедура Task с именем
задания».
Типы выводимых данных должны совпадать с требуемыми в задании типами,
в противном случае выводится
сообщение об ошибке «Неверно указан тип при выводе результатов».
Как и в случае функций ввода, при вызовах процедур вывода
программа осуществляет контроль за соответствием количества требуемых и
выведенных результирующих данных. Если программа выведет недостаточное или
избыточное количество результирующих данных, то после проверки этих данных
появится сообщение «Выведены не все результирующие данные» или,
соответственно, «Попытка вывести лишние результирующие данные».
Работа с динамическими структурами
type
Node = class(IDisposable)
public
// Конструкторы:
constructor Create;
constructor Create(aData: integer);
constructor Create(aData: integer; aNext: Node);
constructor Create(aData: integer; aNext,aPrev: Node);
constructor Create(left,right: Node; data: integer);
constructor Create(left,right: Node; data: integer; parent: Node);
// Метод, освобождающий ресурсы, используемые объектом:
procedure Dispose;
// Свойства (доступны для чтения и для записи):
property Next: Node;
property Prev: Node;
property Left: Node;
property Right: Node;
property Parent: Node;
property Data: integer;
end;
Класс Node используется в заданиях групп ObjDyn, GCDyn
и ObjTree, GCTree. В заданиях групп ObjDyn и GCDyn на
стеки и очереди (128) при работе с классами Node
используются только свойства Data и Next; в заданиях на двусвязные списки
(2980) используются свойства Data, Next и Prev. В большинстве заданий на
бинарные деревья (группы ObjTree и GCTree) используются свойства Data, Left и Right;
в заданиях на обработку бинарных деревьев с обратной связью
(4856 и 7071) дополнительно используется поле Parent.
Метод Dispose, освобождающий ресурсы,
требуется использовать только в заданиях групп ObjDyn и ObjTree.
В заданиях групп GCDyn и GCTree предполагается, что ресурсы освобождаются автоматически
с помощью сборщика мусора (Garbage Collector), поэтому использовать в них метод Dispose не требуется
(хотя и не запрещается). На эту особенность указывает прификс данных групп GC
(от англ. Garbage Collector сборщик мусора).
Все исходные и результирующие объекты в заданиях имеют тип
Node; их ввод должен осуществляться с помощью функций ReadNode, ReadNode2, ReadNode3, ReadNode4,
а вывод с помощью стандартных процедур Write/Writeln или Print/Pringln.
В учебных программах не следует повторно описывать класс Node.
Вывод отладочной информации
Описываемые далее отладочные средства реализованы для среды PascalABC.NET,
начиная с версии 4.19 задачника. При работе с предыдущими версиями задачника следует
использовать отладочные средства, описанные
в разделе «Pascal | Процедуры задачника»
С помощью средств отладки можно выводить отладочную информацию
непосредственно в окно задачника (в специальный раздел отладки).
procedure Show(params args: array of object);
procedure ShowLine(params args: array of object);
procedure HideTask;
procedure SetWidth(w: integer);
procedure SetPrecision(p: integer);
Процедура Show отображают данные в разделе отладки окна задачника,
они могут принимать произвольное число параметров любого типа. Выводимые данные отделяются
от предшествующих отладочных данных (и друг от друга) пробелом. При необходимости
они переносятся на следующую экранную строку (ширина области вывода в разделе отладки
фиксирована и равна 80 позициям).
Составные данные, в том числе вложенные (например, числовые массивы или массивы кортежей),
отображаются в наглядном виде, с применением
вспомогательных форматирующих элементов.
При оформлении выводимых наборов данных используются следующие обозначения:
кортежи обрамляются круглыми скобками; для большинства типов, реализующих интерфейс Enumerable
(в частности, массивов и списков List), используются квадратные скобки;
исключение составляют множества (HashSet и SortedSet)
и словари (в частности, Dictionary и SortedDictionary), для которых применяются
фигурные скобки. Элементы словарей, как и кортежи, обрамляются круглыми скобками, кроме того, ключи (key)
и значения (value) этих элементов разделяются двоеточием.
После вывода любого Enumerable-объекта
выполняется автоматический переход на следующую экранную строку в разделе отладки.
При наличии нескольких вложенных Enumerable-объектов уровень
их вложенности оформляется с помощью дополнительных отступов.
Элементы любых наборов данных разделяются запятыми
(за исключением элементов, которые реализуют интерфейс Enumerable,
после которых запятая не указывается, поскольку, как было отмечено выше,
такие элементы разделяются разрывами строк).
Процедура ShowLine является модификацией процедуры Show; она
дополнительно осуществляют автоматический переход на следующую экранную строку
после вывода указанных данных в раздел отладки.
Если процедура ShowLine вызывается без параметров, то она
просто обеспечивает переход на новую экранную строку.
Процедура ShowLine выполняет дополнительный переход на следующую строку только в случае,
если последним выводимым элементом данных не является Enumerable-объект,
поскольку после вывода подобных объектов всегда выполняется переход на новую строку.
Переход на новую экранную строку можно выполнить и в процедуре Show; для этого
достаточно указать в наборе выводимых данных символ с кодом 13 («возврат каретки»),
или символ с кодом 10 («переход на новую строку»), или их комбинацию в
указанном порядке (#13#10 ).
Вызов процедуры HideTask обеспечивает автоматическое скрытие всех разделов окна
задачника, кроме раздела отладки. Если раздел отладки в окне задачника
не отображается (в частности, если программа запущена в
демонстрационном режиме), то вызов процедуры HideTask игнорируется.
Игнорируются также все повторные вызовы данной процедуры.
Скрыть/восстановить основные разделы окна
задачника после его отображения на экране можно также с помощью клавиши
пробела или соответствующей команды контекстного меню раздела
отладки.
Процедура SetWidth(w) задает минимальную ширину w (w >= 0) поля вывода для элементов
данных, выводимых процедурами Show и ShowLine; по умолчанию минимальная ширина полагается равной 0.
Действие указанной настройки распространяется на все последующие вызовы процедур Show и ShowLine.
Числовые данные выравниваются по правой границе, прочие данные по левой.
Процедура SetPrecision(d) устанавливает количество d дробных знаков при выводе вещественных чисел
(при d <= 0 используется формат с плавающей точкой; число дробных знаков в этом случае равно d
или 6, если d равно 0); по умолчанию d = 2. В качестве десятичного разделителя используется точка.
Действие указанной настройки распространяется на все последующие вызовы процедур Show и ShowLine.
Ниже приводятся примеры использования процедуры Show для вывода различных наборов данных.
Фрагмент программы, обеспечивающий отладочный вывод, имеет следующий вид
(было использовано задание Matrix80, в котором дается вещественная квадратная матрица):
Task('Matrix80');
HideTask;
ShowLine('Матрица вещественных чисел (width = 5):');
var a := ReadMatrReal(ReadInteger);
SetWidth(5);
ShowLine(a);
ShowLine('Словарь строк (width = 0):');
var b1 := new Dictionary<integer, string>();
b1[1] := 'ABCD';
b1[3] := '123';
b1[10] := '!*****!';
SetWidth(0);
ShowLine(b1);
ShowLine('Словарь строковых массивов (width = 3):');
var b2 := new Dictionary<integer, array of string>();
b2[1] := new string[] ( 'ab', 'd' );
b2[2] := new string[] ( '123', '45', '7' );
b2[22] := new string[] ( '**', '#', '@@@' );
SetWidth(3);
ShowLine(b2);
ShowLine('Список списков, содержащих числовые строки (width = 6):');
var c1 := new List<List<string>>();
c1.Add(new List<string>());
c1[0].Add('ABCD'); c1[0].Add('123'); c1[0].Add('!****!');
c1.Add(new List<string>());
c1[1].Add('abcd'); c1[1].Add('56789');
SetWidth(6);
ShowLine(c1);
ShowLine('Массив массивов, содержащих числовые массивы (width = 2):');
var c2 : array of array of array of integer;
SetLength(c2, 3);
SetLength(c2[0], 2);
c2[0][0] := new integer[] ( 1, 2, 3 );
c2[0][1] := new integer[] ( 4, 5, 6 );
SetLength(c2[1], 3);
c2[1][0] := new integer[] ( 7, 8, 9 );
c2[1][1] := new integer[] ( 10, 11, 12 );
c2[1][2] := new integer[] ( 60, 61, 62 );
SetLength(c2[2], 2);
c2[2][0] := new integer[] ( 13, 14, 15, 50 );
c2[2][1] := new integer[] ( 16, 17, 18, 19, 20 );
SetWidth(2);
ShowLine(c2);
В приведенном далее образце содержимого раздела отладки следует обратить
внимание на то, что при выводе скалярных элементов или элементов-кортежей
они разделяются запятыми, тогда как после каждого элемента, реализующего интерфейс Enumerable
(массива или списка List),
выполняется переход на новую строку. Кроме того, следует обратить внимание
на использование отступов при выводе многомерных списков, а также на
настройку ширины области вывода с помощью процедуры SetWidth.
1> Матрица вещественных чисел (width = 5):
2> [ [ 2.07 , 4.75 , 4.15 , 6.20 , 0.59 ]
3> [ 4.47 , 3.12 , 7.51 , 7.98 , 9.45 ]
4> [ 5.50 , 8.67 , 2.51 , 2.64 , 5.90 ]
5> [ 2.45 , 6.45 , 4.24 , 4.35 , 4.51 ]
6> [ 2.87 , 1.46 , 6.67 , 5.57 , 5.00 ]
7> ]
8> Словарь строк (width = 0):
9> { ( 1 : ABCD ) , ( 3 : 123 ) , ( 10 : !*****! ) }
10> Словарь строковых массивов (width = 3):
11> { ( 1 : [ ab , d ]
12> ) ( 2 : [ 123 , 45 , 7 ]
13> ) ( 22 : [ ** , # , @@@ ]
14> ) }
15> Список списков, содержащих числовые строки (width = 6):
16> [ [ ABCD , 123 , !****! ]
17> [ abcd , 56789 ]
18> ]
19> Массив массивов, содержащих числовые массивы (width = 2):
20> [ [ [ 1 , 2 , 3 ]
21> [ 4 , 5 , 6 ]
22> ]
23> [ [ 7 , 8 , 9 ]
24> [ 10 , 11 , 12 ]
25> [ 60 , 61 , 62 ]
26> ]
27> [ [ 13 , 14 , 15 , 50 ]
28> [ 16 , 17 , 18 , 19 , 20 ]
29> ]
30> ]
|