Programming Taskbook


E-mail:

Пароль:

Регистрация пользователя   Восстановление пароля

 

ЮФУ SMBU

Электронный задачник по программированию

©  М. Э. Абрамян (Южный федеральный университет, Университет МГУ-ППИ в Шэньчжэне), 1998–2024

 

Teacher Pack | Конструктор учебных заданий | Основные компоненты

PrevNext


Основные компоненты

Если процедура имеет необязательные параметры, то в списке параметров они заключаются в квадратные скобки.

Определение общих характеристик группы заданий

При создании новой группы заданий требуется определить следующие характеристики этой группы:

  • имя группы (GroupName) — текстовая строка, содержащая от 1 до 25 символов — цифр и латинских букв, причем последний символ не может быть цифрой (если имя группы содержит более 9 символов, то она считается особой библиотечной группой, работа с которой отличается от работы с обычной группой); запрещается использовать имена стандартных групп задачника (Begin, Integer и т. д.); имена, различающиеся только регистром букв, считаются совпадающими;
  • описание группы (GroupDescription) — непустая текстовая строка с кратким описанием данной группы; при генерации полного описания группы в виде html-страницы данная строка указывается в качестве заголовка этого описания;
  • сведения об авторе (GroupAuthor) — текстовая строка с информацией о разработчике данной группы (фамилия, инициалы, год разработки, e-mail и т. п.; строка может быть пустой);
  • ключ группы (GroupKey) — непустая текстовая строка с произвольным набором символов, позволяющая в дальнейшем идентифицировать в файле результатов results.dat и results.abc те выполненные задания, которые относятся к данной группе;
  • количество заданий в группе (TaskCount) — целое число в диапазоне от 1 до 999, определяющее количество заданий в группе;
  • основная процедура группы заданий (InitTaskProc) — процедура с одним целочисленным параметром, обеспечивающая инициализацию всех заданий данной группы (параметр данной процедуры определяет номер задания в пределах группы).

Из перечисленных характеристик в дополнительном комментарии нуждается ключ группы. Если не использовать подобную характеристику, то становится невозможной идентификация группы, к которой относятся задания, выполненные учащимся. Действительно, имя задания, сохраненное в файле результатов, не позволяет однозначно его идентифицировать, поскольку ничто не мешает разработать другую группу с тем же именем и совершенно другими заданиями, после чего «подменить» ею исходную группу. Проблему решает использование ключа группы, который сложно подделать, так как он известен только разработчику группы. При успешном выполнении задания в файл результатов дополнительно записывается идентификатор группы, вычисляемый на основе ее ключа и позволяющий однозначно определить группу, к которой относится выполненное задание. Поскольку информация, связанная с идентификаторами групп, представляет интерес только для преподавателя, ознакомиться с ней можно только с помощью программы «Контрольный центр преподавателя» (см. команду «Check-файлы | Просмотреть файл check.inf»).

В версии 4.13 в конструктор была добавлена возможность скрытия раздела с примером правильных результатов для создаваемой группы заданий. Эта возможность усложняет процесс выполнения заданий, так как не позволяет сравнить ошибочные результаты, полученные программой учащегося, с правильным вариантом решения. Она может оказаться полезной при подготовке наборов заданий, предназначенных для проведения контрольных работ. Для того чтобы обеспечить скрытие раздела с правильными результатами, достаточно добавить в любую позицию строкового параметра GroupKey процедуры CreateGroup следующую подстроку (регистр символов учитывается): #HideExamples# (например, параметр GroupKey может иметь вид 123rkidpsj449#HideExamples#werx34). Раздел с правильными результатами скрывается для всех заданий созданной группы, в том числе и заданий, импортированных из других групп.

В версии 4.14 в конструктор была добавлена возможность обязательной проверки наличия файла дополнений для создаваемой группы заданий. Файлы дополнений, появившиеся в версии 4.14, могут связываться с любыми группами заданий; по умолчанию их отсутствие не препятствует успешному подключению группы к задачнику. Однако в некоторых ситуациях наличие файла дополнений является обязательным (например, если файл дополнений обеспечивает генерацию специального шаблона для выполняемого задания). Для того чтобы включить режим обязательной проверки наличия файла дополнений достаточно добавить в любую позицию строкового параметра GroupKey процедуры CreateGroup следующую подстроку (регистр символов учитывается): #UseAddition# (например, параметр GroupKey может иметь вид 13rsdkh3hids9#UseAddition#dfgt4g2)..

В версии 4.22 в конструктор была добавлена возможность указания альтернативного описания группы на английском языке. При наличии такого описания оно используется в программах PT4Demo и PT4Load, если для них установлен английский языковой интерфейс. Это позволяет избежать появления фрагментов русского текста в окнах программ PT4Demo и PT4Load при отображении информации о группах заданий, реализованных только на русском языке. Альтернативное английское описание группы должно указываться в строковом параметре GroupKey в следующем формате: #EnTopic<Текст описания># (например, параметр GroupKey может иметь вид 13rshids9#EnTopic<English group description>#dfgt2).

Примечание. При выводе краткого описания группы в программных модулях PT4Demo и PT4Load первый символ этого описания преобразуется к нижнему регистру (поскольку текст описания располагается в этих модулях после двоеточия). Если понижать регистр первого символа не следует (в случае, если этот символ является началом фамилии или некоторой аббревиатуры, например, «ЕГЭ»), то в начале краткого описания группы надо указать дополнительный символ-метку «^» (шапочка). Пример использования символа «^» приводится в разделе «Разработка групп заданий, связанных с ЕГЭ по информатике».

Для определения характеристик новой группы необходимо вызвать процедуру CreateGroup, указав эти характеристики в качестве параметров:

[Pascal]

procedure CreateGroup(GroupName, GroupDescription, GroupAuthor,
  GroupKey: string; TaskCount: integer; InitTaskProc: TInitTaskProc);

[C++]

void CreateGroup(const char* GroupName, const char* GroupDescription,
  const char* GroupAuthor, const char* GroupKey, int TaskCount,
  TInitTaskProc InitTaskProc);

[C#, class PT4.TaskMaker]

protected static void CreateGroup(string GroupName, string GroupDescription,
  string GroupAuthor, string GroupKey, int TaskCount, TInitTaskProc InitTaskProc);

Тип TInitTaskProc определяется следующим образом:

[Pascal]

type TInitTaskProc = procedure(n: integer); stdcall;

[C++]

typedef void (_stdcall *TInitTaskProc)(int);

[C#, class PT4.TaskMaker]

protected delegate void TInitTaskProc(int N);

Процедуру CreateGroup необходимо вызывать в процедуре inittaskgroup, которая должна экспортироваться библиотекой, содержащей данную группу. Основная процедура группы (типа TInitTaskProc) при ее описании в библиотеке на языке Pascal, разработанной в среде Delphi или Lazarus, должна иметь модификатор stdcall, а при описании в библиотеке на языке C++ — модификатор _stdcall. В библиотеках, разработанных на языке C# или в среде PascalABC.NET, дополнительные модификаторы для основной процедуры группы не требуются.

Процедура CreateGroup контролирует правильность переданных ей параметров и в случае ошибки выводит на экран информационное окно с ее описанием. В подобной ситуации все последующие действия, связанные с определением данной группы, игнорируются, и группа не включается в список доступных для использования групп заданий. Перечислим некоторые из возможных ошибок:

  • в процедуре inittaskgroup определяется более одной группы заданий (в этом случае определения всех групп, кроме первой, игнорируются);
  • имя группы не соответствует имени dll-файла, в котором данная группа определяется (напомним, что имя dll-файла должно иметь вид PT4<имя группы> или PT4<имя группы><маркер локали>); при реализации группы в виде pcu-файла данное ограничение отсутствует;
  • к задачнику Programming Taskbook уже подключена группа с указанным именем;
  • имя группы не является допустимым (в частности, совпадает с именем одной из базовых групп задачника);
  • не указано краткое описание группы;
  • не указан ключ группы;
  • количество заданий не принадлежит диапазону 1–999;
  • процедурная переменная InitTaskProc содержит нулевую ссылку (nil для языка Pascal, NULL для языка C++, null для языка C#).

Базовые константы и процедуры для создания новых заданий


[Pascal]

const
  xCenter = 0;
  xLeft = 100;
  xRight = 200;

[C++]

#define xCenter 0
#define xLeft 100
#define xRight 200

[C#, class PT4.TaskMaker]

protected const int xCenter = 0,
  xLeft = 100,
  xRight = 200;

Эти константы, отвечают за выравнивание данных по горизонтали: константа xCenter центрирует текст, связанный с элементом данных, относительно всей экранной строки, константы xLeft и xRight центрируют текст в пределах левой и правой половины экранной строки соответственно. Используются в качестве параметра X в процедурах групп Data и Result, а также в процедуре TaskText.


[Pascal]

procedure CreateTask([SubgroupName: string]);

[C++]

void CreateTask([const char* SubgroupName]);

[C#, class PT4.TaskMaker]

protected static void CreateTask([string SubgroupName]);

Данная процедура должна быть вызвана первой при инициализации нового задания; в качестве необязательного параметра SubgroupName указывается заголовок подгруппы, в которую включается задание (задания целесообразно разбивать на подгруппы, если их количество в группе является достаточно большим; в случае деления группы на подгруппы каждое задание рекомендуется связывать с какой-либо подгруппой). Если параметр является пустой строкой или отсутствует, то задание не связывается с какой-либо подгруппой. В окне задачника заголовок подгруппы выводится над именем задания; если подгруппа для данного задания не указана, то выводится краткое описание всей группы (определенное в параметре GroupDescription процедуры CreateGroup). При выводе краткого описания группы или заголовка подгруппы в окне задачника его текст преобразуется к верхнему регистру.

В версии 4.9 конструктора учебных заданий к первоначальным двум вариантам процедуры CreateTask были добавлены еще два варианта, предназначенные для инициализации задания по параллельному MPI-программированию.


[Pascal]

procedure TaskText(S: string[; X, Y: integer]);

[C++]

void TaskText(const char* S[, int X , int Y]);

[C#, class PT4.TaskMaker]

protected static void TaskText(string S[, int X, int Y]);

Данная процедура добавляет к формулировке задания строку S, которая располагается в строке Y (от 1 до 5) раздела формулировки задания, начиная с позиции X. Позиции нумеруются от 1; при указании параметра X следует учитывать, что ширина раздела формулировок (как и разделов исходных и результирующих данных) равна 78 символам. Кроме явного указания значения позиции X можно использовать специальные константы xCenter, xLeft и xRight; в частности, если параметр X равен 0, то строка центрируется. Рекомендуется всегда центрировать строки в формулировках заданий (как это делается в базовых группах, входящих в задачник); явное указание позиции X следует использовать лишь при выводе многострочных формул и в других случаях специального выравнивания текста. Все строки должны добавляться к формулировке последовательно; при этом если формулировка содержит 1 строку, то ее следует располагать на экранной строке с номером 3, если 2 строки — на экранных строках 2 и 4, если 3 строки — на экранных строках 2, 3 и 4, если 4 строки — на экранных строках с номерами от 2 до 5 (именно так оформляются задания в базовых группах задачника). Нарушение порядка добавления строк не проявится при отображении формулировки в окне задачника, однако приведет к неверному выводу формулировки в html-описании группы.

Кроме пяти строк с основным текстом формулировки, который отображается на экране при выводе задания, можно указывать дополнительные строки, отображаемые на экране при прокрутке текста задания (связанные с прокруткой кнопки отображаются в окне задачника справа от раздела формулировок, если в формулировке текущего задания имеются дополнительные строки). Все дополнительные строки, как и основные, должны добавляться к формулировке последовательно, причем параметр Y для таких строк надо положить равным 0. Максимальное количество дополнительных строк равно 200.

В строке S можно использовать управляющие последовательности.

Если при выводе строки S часть ее не умещается на экранной строке, то выводится сообщение об ошибке «Ошибочное позиционирование по горизонтали». Если ошибка произошла при выводе основной строки, то лишняя часть строки S отображается на следующей строке (или на первой строке, если ошибочной является пятая строка в разделе формулировок).

Определенный с помощью процедур TaskText текст формулировки задания используется также при формировании html-описания группы. В этом случае деление на строки, указанное для экранного вывода, игнорируется, однако учитываются дополнительные управляющие последовательности, позволяющие разбивать текст на абзацы с различным способом выравнивания (на отображение текста в окне задачника эти дополнительные последовательности не влияют).

Если при определении задания не указана его формулировка, то выводится сообщение об ошибке.

Вариант процедуры TaskText с единственным параметром S добавлен в версию 4.11 конструктора. В этом варианте строка S должна содержать весь текст формулировки, причем строки формулировки должны разделяться символами #13 (\r), #10 (\n) или их комбинациями #13#10 (\r\n). Начальные и конечные пробелы в каждой строке формулировки удаляются; если в результате какая-либо строка окажется пустой, то она не учитывается. Все строки формулировки автоматически центрируются по горизонтали; их вертикальное расположение определяется количеством строк и соответствует правилам, приведенным выше (если формулировка содержит одну строку, то она располагается на экранной строке 3, и т. д.). Если требуется специальное выравнивание какой-либо строки текста, то его можно добиться за счет добавления дополнительных пробелов в начало или конец строки; чтобы эти пробелы не были удалены, первый начальный (или последний конечный) пробел должен быть экранирован символом «\» (обратная косая черта).

При использовании варианта процедуры TaskText с единственным параметром для языка C++ удобно применять правило, согласно которому строковые литералы могут быть разделены пробелами и/или символами разрыва строки, например:

  TaskText("Дана строка~{S}.\n"
           "Вывести ее первый и последний символ.");

В случае языка C# удобно использовать дословные строки, например:

  TaskText(@"Дана строка~{S}.
             Вывести ее первый и последний символ.");

[Pascal]

procedure DataB ([Cmt: string;] B: boolean; X, Y: integer);
procedure DataN([Cmt: string;] N: integer; X, Y, W: integer);
procedure DataN2([Cmt: string;] N1, N2: integer; X, Y, W: integer);
procedure DataN3([Cmt: string;] N1, N2, N3: integer; X, Y, W: integer);
procedure DataR([Cmt: string;] R: real; X, Y, W: integer);
procedure DataR2([Cmt: string;] R1, R2: real; X, Y, W: integer);
procedure DataR3([Cmt: string;] R1, R2, R3: real; X, Y, W: integer);
procedure DataC([Cmt: string;] C: char; X, Y: integer);
procedure DataS([Cmt: string;] S: string; X, Y: integer);

[C++]

void DataB([const char* Cmt,] bool B, int X, int Y);
void DataN([const char* Cmt,] int N, int X, int Y, int W);
void DataN2([const char* Cmt,] int  N1, int N2, int X, int Y, int W);
void DataN3([const char* Cmt,] int N1, int N2, int N3, int X, int Y, int W);
void DataR([const char* Cmt,] double R, int X, int Y, int W);
void DataR2([const char* Cmt,] double R1, double R2, int X, int Y, int W);
void DataR3([const char* Cmt,] double R1, double R2, double R3, int X, int Y, int W);
void DataC([const char* Cmt,] char C, int  X, int Y);
void DataS([const char* Cmt,] const char* S, int X, int Y);

[C#, class PT4.TaskMaker]

protected static void DataB([string Cmt,] bool B, int X, int Y);
protected static void DataN([string Cmt,] int N, int X, int Y, int W);
protected static void DataN2([string Cmt,] int N1, int N2, int X, int Y, int W);
protected static void DataN3([string Cmt,] int N1, int N2, int N3, int X, int Y,
  int W);
protected static void DataR([string Cmt,] double R, int X, int Y, int W);
protected static void DataR2([string Cmt,] double R1, double R2, int X, int Y, int W);
protected static void DataR3([string Cmt,] double R1, double R2, double R3, int X,
  int Y, int W);
protected static void DataC([string Cmt,] char C, int X, int Y);
protected static void DataS([string Cmt,] string S, int X, int Y);

Процедуры группы Data добавляют к заданию элементы исходных данных. Добавленные элементы, вместе с необязательной строкой-комментарием Cmt, отображаются в разделе исходных данных, начиная с позиции X строки Y (позиции и строки нумеруются от 1; ширина экранной строки равна 78 позициям). Если используются значения параметра Y, большие 5, то разделе исходных данных будет доступна прокрутка. Как и для процедуры TaskText, параметр X может принимать три особых значения: 0 (центрирование по горизонтали относительно всей экранной строки), 100 (центрирование по горизонтали относительно левой половины экранной строки), 200 (центрирование по горизонтали относительно правой половины экранной строки). Эти значения можно также задавать с помощью констант xCenter, xLeft и xRight.

Параметр W определяет ширину поля вывода для числовых данных (выравнивание всегда производится по правому краю поля вывода). Если ширины поля вывода недостаточно, то значение параметра W игнорируется, и для вывода элемента используется минимально необходимое число экранных позиций. При определении ширины поля вывода для вещественного числа следует учитывать размер отображаемой дробной части (который определяется процедурой SetPrecision, описываемой далее).

Для нечисловых данных ширина поля вывода полагается равной фактической ширине данных; в частности, для данных символьного типа отводятся 3 позиции, содержащие начальный апостроф, собственно символ и конечный апостроф, а для логического типа отводятся 5 позиций, достаточных для вывода названий обеих логических констант в любом используемом языке программирования. Для строки отводятся L + 2 позиции, где L — длина строки (начальная и конечная позиции используются для вывода апострофов). В зависимости от текущего языка программирования используются либо одинарные, либо двойные апострофы.

Используя процедуры группы Data, в задание можно включить до 800 различных скалярных исходных данных (при этом следует учитывать, что некоторые процедуры, например, DataN2 и DataN3, добавляют в набор исходных данных несколько элементов). Наложение различных элементов в разделе исходных данных задачником не контролируется, поэтому при размещении данных следует обращать особое внимание на то, чтобы последующие элементы не скрывали предыдущие. Кроме того, важен порядок определения исходных данных, так как именно в этом порядке данные будут передаваться программе учащегося, выполняющей это задание. Следует придерживаться стандартных правил, принятых в базовых группах задачника: данные должны перебираться по строкам (в направлении сверху вниз), а в пределах каждой строки — слева направо.

В параметре Cmt, содержащем текст комментария к определяемому элементу исходных данных, можно использовать управляющие последовательности (например, для отображения индексов).

В любом задании должен быть задан хотя бы один элемент исходных данных; в противном случае выводится сообщение об ошибке.

Варианты данных процедур, в которых параметр Cmt отсутствует, добавлены в версию 4.11 конструктора.


[Pascal]

procedure DataComment(Cmt: string; X, Y: integer);

[C++]

void DataComment(const char* Cmt, int  X, int Y);

[C#, class PT4.TaskMaker]

protected static void DataComment(string Cmt, int X, int Y);

Процедура позволяет добавлять в раздел исходных данных отдельный комментарий Cmt, не связанный с каким-либо элементом исходных данных. Общее число отдельных комментариев, включаемых в разделы исходных и результирующих данных, не должно превосходить 200. Смысл параметров X и Y — тот же, что и для процедур группы Data.


[Pascal]

procedure ResultB ([Cmt: string;] B: boolean; X, Y: integer);
procedure ResultN([Cmt: string;] N: integer; X, Y, W: integer);
procedure ResultN2([Cmt: string;] N1, N2: integer; X, Y, W: integer);
procedure ResultN3([Cmt: string;] N1, N2, N3: integer; X, Y, W: integer);
procedure ResultR([Cmt: string;] R: real; X, Y, W: integer);
procedure ResultR2([Cmt: string;] R1, R2: real; X, Y, W: integer);
procedure ResultR3([Cmt: string;] R1, R2, R3: real; X, Y, W: integer);
procedure ResultC([Cmt: string;] C: char; X, Y: integer);
procedure ResultS([Cmt: string;] S: string; X, Y: integer);

[C++]

void ResultB([const char* Cmt,] bool B, int X, int Y);
void ResultN([const char* Cmt,] int N, int X, int Y, int  W);
void ResultN2([const char* Cmt,] int N1, int N2, int X, int Y, int W);
void ResultN3([const char* Cmt,] int N1, int N2, int N3, int X, int Y, int W);
void ResultR([const char* Cmt,] double R, int X, int Y, int W);
void ResultR2([const char* Cmt,] double R1, double R2, int X, int Y, int W);
void ResultR3([const char* Cmt,] double R1, double R2, double R3, int X, int Y, int W);
void ResultC([const char* Cmt,] char C, int X, int Y);
void ResultS([const char* Cmt,] const char* S, int X, int Y);

[C#, class PT4.TaskMaker]

protected static void ResultB([string Cmt,] bool B, int X, int Y);
protected static void ResultN([string Cmt,] int N, int X, int Y, int W);
protected static void ResultN2([string Cmt,] int N1, int N2, int X, int Y, int W);
protected static void ResultN3([string Cmt,] int N1, int N2, int N3, int X, int Y,
  int W);
protected static void ResultR([string Cmt,] double R, int X, int Y, int W);
protected static void ResultR2([string Cmt,] double R1, double R2, int X, int Y, int W);
protected static void ResultR3([string Cmt,] double R1, double R2, double R3, int X,
  int Y, int W);
protected static void ResultC([string Cmt,] char C, int X, int Y);
protected static void ResultS([string Cmt,] string S, int X, int Y);

Процедуры данной группы добавляют к заданию элементы результирующих данных вместе с их контрольными значениями. Комментарии Cmt к результирующим данным сразу отображаются в разделе результатов. Контрольные значения отображаются в разделе «Пример верного решения». Смысл параметров X, Y и W — тот же, что и для процедур группы Data. Задание может содержать до 800 скалярных элементов результирующих данных.

Как и в случае исходных данных, если элемент контрольных данных не умещается в поле, выделенном для его отображения (шириной W позиций), то параметр W игнорируется, и для вывода используется минимально необходимое число экранных позиций. Однако если элемент результирующих данных, переданный в задачник программой, решающей задание, не «уложится» в размер, выделенный для соответствующего элемента контрольных данных, то в правой позиции поля вывода для этого элемента отобразится символ «*» (звездочка) красного цвета. Подобная ситуация возможна как для чисел, так и для строк (если программа учащегося выведет число или строку, размер которых больше требуемого). Для того чтобы в этой ситуации увидеть полный текст всех подобных элементов результирующих данных, следует переместить курсор мыши в раздел результатов в окне задачника; через 1–2 секунды полный текст всех данных, размер которых превышает допустимый, появится во всплывающей подсказке.

Порядок вызова процедур группы Result важен, так как он соответствует порядку, в котором результирующие данные, полученные программой учащегося, должны передаваться задачнику для проверки их правильности. Поэтому, как и для исходных данных, для набора результирующих данных должен соблюдаться стандартный порядок их размещения: сверху вниз по строкам и слева направо в каждой строке.

В параметре Cmt, содержащем текст комментария к определяемому элементу результирующих данных, можно использовать управляющие последовательности.

Проверка правильности результатов, полученных программой учащегося, выполняется путем сравнения текста, изображающего эти результаты в окне задачника, с текстом, изображающим соответствующие контрольные данные. Это означает, в частности, что вычислительная погрешность, возникающая при обработке вещественных чисел, не будет влиять на проверку правильности, если при отображении этих чисел не используется слишком большое количество дробных знаков (напомним, что число дробных знаков можно задать с помощью процедуры SetPrecision).

В любом задании должен быть задан хотя бы один элемент результирующих данных; в противном случае выводится сообщение об ошибке.

Варианты данных процедур, в которых параметр Cmt отсутствует, добавлены в версию 4.11 конструктора.


[Pascal]

procedure ResultComment(Cmt: string; X, Y: integer);

[C++]

void ResultComment(const char* Cmt, int X, int Y);

[C#, class PT4.TaskMaker]

protected static void ResultComment(string Cmt, int X, int Y);

Процедура позволяет добавлять в раздел результатов отдельный комментарий Cmt, не связанный с каким-либо элементом результирующих данных. Общее число отдельных комментариев, включаемых в разделы исходных и результирующих данных, не должно превосходить 200. Смысл параметров X и Y — тот же, что и для процедур группы Data.


[Pascal]

procedure SetPrecision(N: integer);

[C++]

void SetPrecision(int N);

[C#, class PT4.TaskMaker]

protected static void SetPrecision(int N);

Процедура устанавливает количество N дробных знаков, используемое в дальнейшем при выводе всех элементов данных вещественного типа. По умолчанию количество дробных знаков равно 2. Если оно равно 0, то вещественные данные отображаются в экспоненциальном формате, а количество дробных знаков определяется шириной поля вывода, указанной для данного числа. Действие текущей настройки, определенной процедурой SetPrecision, продолжается до очередного вызова этой процедуры, однако не распространяется на другие учебные задания текущей группы. При отображении вещественных чисел в качестве десятичного разделителя всегда используется точка.


[Pascal]

procedure SetRequiredDataCount(N: integer);

[C++]

void SetRequiredDataCount(int N);

[C#, class PT4.TaskMaker]

protected static void SetRequiredDataCount(int N);

Процедура определяет минимально необходимое количество N элементов исходных данных, требуемое для правильного решения задания при текущем наборе исходных данных. По умолчанию это количество равно общему числу всех указанных в задании исходных данных. Если параметр N имеет нулевое или отрицательное значение, то выводится сообщение об ошибке; если значение параметра превышает общее число элементов исходных данных, то сообщение об ошибке не выводится, а требуемое количество исходных данных полагается равным их общему количеству.

Примером задания, в котором необходимо использовать данную процедуру, может служить задание Series10. В этом задании дается набор из N целых чисел и требуется вывести True, если данный набор содержит положительные числа, и False в противном случае. Ясно, что если при считывании элементов набора будет обнаружено положительное число, то можно сразу выводить значение True и завершать выполнение задания. Однако если при подготовке задания не указать минимально необходимое число исходных данных с помощью процедуры SetRequiredDataCount, то по умолчанию будет считаться, что для решения необходимо прочесть все исходные данные, и приведенный выше правильный вариант решения будет расценен как ошибочный (при этом будет выведено сообщение «Введены не все требуемые исходные данные»).

Если заданное с помощью процедуры SetRequiredDataCount количество требуемых исходных данных меньше их общего количества, то программа учащегося не обязана считывать все исходные данные: достаточно прочесть только требуемые. Однако если программа прочтет все данные и выведет правильный ответ, это также будет считаться верным вариантом решения.

При выполнении заданий по параллельному программированию во всех процессах параллельной программы должны быть введены все связанные с ними исходные данные. Поэтому попытка вызова процедуры SetRequiredDataCount(N) с параметром N, значение которого меньше общего числа исходных данных, приведет в задании по параллельному программированию к сообщению об ошибке.


[Pascal]

procedure SetTestCount(N: integer);

[C++]

void SetTestCount(int N);

[C#, class PT4.TaskMaker]

protected static void SetTestCount(int N);

Процедура определяет количество N успешных тестовых испытаний программы учащегося, необходимое для того, чтобы задание было зачтено как выполненное. По умолчанию количество тестовых испытаний полагается равным 5. Значение N должно находиться в пределах от 2 до 9; при указании других вариантов параметра N выводится сообщение об ошибке.

После каждого успешного тестового испытания в окне задачника выводится сообщение (на зеленом фоне), в котором указывается номер испытания и общее число тестов, необходимых для выполнения данного задания, например: «Верное решение. Тест номер 2 (из 5)». Если при очередном тестовом испытании программы ею будет получено ошибочное решение, то счетчик успешных тестов будет сброшен в 0, и тестирование (после исправления обнаруженной ошибки) придется начинать заново.


[Pascal]

function CurrentTest: integer;

[C++]

int CurrentTest();

[C#, class PT4.TaskMaker]

protected static int CurrentTest();

Данная функция добавлена в версию 4.11 конструктора учебных заданий. Она возвращает порядковый номер текущего тестового запуска, причем учитываются только успешные тестовые запуски. Если ранее успешных запусков не было, то функция возвращает 1. Если задание уже выполнено или было запущено в демонстрационном режиме, то функция возвращает 0.

При попытке подключения новой группы заданий, содержащей вызов функции CurrentTest, к задачнику более ранней версии (до 4.10 включительно) функция CurrentTest всегда возвращает 0.

Использование данной функции позволяет гарантировать включение в тестовые наборы специальных вариантов тестов (связанных с ситуациями, требующими особой обработки). В предыдущих версиях конструктора эти варианты выбирались только с применением датчика случайных чисел; это могло приводить к тому, что на протяжении требуемой серии тестов (которая не может превышать 9) особые варианты ни разу не генерировались. Используя функцию CurrentTest, особые варианты можно явно связать с тестовым испытанием, имеющим определенный номер. Наряду с подобными «фиксированными» испытаниями при формировании задания следует предусматривать и испытания, при которых варианты тестов по-прежнему выбираются случайным образом; это позволит избежать ситуации (впрочем, маловероятной), при которой учащийся будет запускать разные программы для тестовых испытаний с различными порядковыми номерами. Необходимо также учитывать, что в ряде ситуаций функция CurrentTest возвращает особое значение 0, при котором также целесообразно выбирать тестовые варианты случайным образом.

В качестве примера приведем начальную часть процедуры, реализующей задание Array32, в котором требуется найти номер первого локального минимума. Очевидно, в данном задании следует предусмотреть особые варианты тестов, в которых первым локальным минимумом является первый или последний элемент исходного набора (а также «промежуточный вариант», в котором первый локальный минимум расположен во внутренней части набора). Ранее это обеспечивалось следующим образом (здесь n — размер исходного набора, k — порядковый номер первого локального минимума):

[Pascal]

n := 5 + Random(6);
case Random(4) of
0: k := 1;
1: k := n;
2, 3: k := 2 + Random(n-2);
end;
…

При предусмотренных шести тестовых испытаниях вполне могло оказаться, что функция Random(4) ни разу не примет значения 0 или 1, и тем самым один или оба особых случая не будут протестированы. Возможна (хотя и менее вероятна) ситуация, при которой в течение всех испытаний ни разу не будут получены значения 2 и 3; тем самым не будет испытан «промежуточный вариант». В то же время было бы желательно, чтобы ошибка алгоритма, связанная с неверной обработкой одной из возможных ситуаций, была выявлена задачником автоматически, до просмотра преподавателем текста программы.

В новом варианте процедуры после первого оператора case был добавлен второй, в котором для некоторых тестовых испытаний вариант для значения k задается явным образом:

[Pascal]

n := RandomN(5, 10);
case Random(4) of
0: k := 1;
1: k := n;
2, 3: k := RandomN(2, n-1);
end;
case CurrentTest of
2: k := n;
3: k := RandomN(2, n-1);
5: k := 1;
end;
…

При этом для первого, четвертого и шестого (последнего) тестового испытания, а также при демонстрационных запусках, значение k по-прежнему выбирается случайным образом.

Заметим, что в новом варианте была также использована функция RandomN, добавленная в версию 4.11 конструктора.

После включения функции CurrentTest в конструктор были соответствующим образом модифицированы (без изменения формулировок) все группы заданий, включенные в базовый вариант задачника версии 4.11.


[Pascal]

function RandomN(M, N: integer): integer;
function RandomR(A, B: real): real;

[C++]

int RandomN(int M, int N);
double RandomR(double A, double B);

[C#, class PT4.TaskMaker]

protected static int RandomN(int M, int N);
protected static double RandomR(double A, double B);

Вспомогательные функции, которые могут использоваться при генерации исходных данных с применением датчика случайных чисел. В явной инициализации датчика нет необходимости, поскольку подобная инициализация выполняется в процедуре CreateGroup. Указанные функции позволяют выполнять единообразную генерацию данных при использовании любого языка, поддерживаемого конструктором учебных заданий.

Функция RandomN(M, N) возвращает псевдослучайное целое число, лежащее в диапазоне от M до N включительно. Если указанный диапазон пуст, то функция возвращает M.

Функция RandomR(A, B) возвращает псевдослучайное вещественное число, лежащее на полуинтервале [AB). Если указанный полуинтервал пуст, то функция возвращает A.

При генерации заданий можно применять и стандартные функции соответствующего языка программирования: Random и Random(N) для языка Pascal, rand() для языка C++; в этом случае явная инициализация датчика также не требуется. На языке C# можно воспользоваться членом Rnd класса PT4.TaskMaker, определенным следующим образом:

protected static Random Rnd = new Random();

[Pascal]

function Center(I, N, W, B: integer): integer;

[C++]

int Center(int I, int  N, int  W, int B);

[C#, class PT4.TaskMaker]

protected static int Center(int I, int N, int W, int B);

Вспомогательная функция, которая позволяет размещать по центру экранной строки набор из N элементов данных одинаковой ширины. Эта функция возвращает горизонтальную координату, начиная с которой следует выводить I-й элемент набора (I меняется от 1 до N) при условии, что ширина каждого элемента равна W позициям, а между элементами надо указывать B пробелов. Функция Center обычно используется в качестве параметра X в процедурах групп Data и Result при выводе однотипных наборов данных (в частности, элементов массива).

В качестве примера приведем фрагмент, обеспечивающий формирование и вывод в разделе исходных данных массива вещественных чисел:

[Pascal]

n := RandomN(2, 10);
DataN('N = ', n, 0, 2, 1);
for i := 1 to n do
begin
  a[i] := RandomR(-9.99, 9.99);
  DataR(a[i], Center(i, n, 5, 1), 4, 5);
end;

Вначале (во второй строке области исходных данных) выводится размер N массива, определяемый с помощью датчика случайных чисел и принимающий значения в диапазоне от 2 до 10 (он снабжается комментарием «N = »). Затем (в четвертой строке) выводятся сами элементы массива, причем благодаря использованию функции Center весь список выравнивается относительно центра экранной строки независимо от количества элементов. Целые части всех элементов лежат в диапазоне от -9 до 9, т. е. представляются одной цифрой, одна позиция отводится под знак числа, еще одна — под отображение десятичного разделителя-точки; наконец, по умолчанию указываются два дробных знака, поэтому для каждого элемента следует выделить 5 экранных позиций; это число указывается дважды: как второй параметр функции Center и как последний параметр процедуры DataR. Промежуток между элементами полагается равным 1 экранной позиции (это последний, четвертый параметр функции Center).

При использовании функции Center строку комментария следует оставлять пустой (начиная с версии 4.11 конструктора, в этом случае строку комментария можно просто не указывать).

Прокрутка разделов исходных данных и результатов

Начиная с версии 4.9 конструктора учебных заданий, для процедур групп Data и Result, в том числе DataComment и ResultComment, в качестве параметра Y разрешено указывать значение, превышающее 5. Если значение параметра Y для некоторого элемента раздела исходных данных превышает 5, то этот элемент размещается в строке с указанным номером, а в разделе исходных данных становится доступной прокрутка. Аналогичным образом прокрутка будет доступна в разделе результатов, если хотя бы один элемент этого раздела помещен в него процедурой с параметром Y, превышающим 5. Если оба раздела допускают прокрутку, то она выполняется независимо. Прокрутку в любом разделе можно выполнять с помощью клавиатуры или мыши; в последнем случае следует использовать полосы прокрутки, расположенные справа от прокручиваемого раздела. Прокрутка может также выполняться с помощью колесика мыши.

В задании запрещено использовать прокрутку раздела, если в нем уже имеется «внешний» объект (файл или динамическая структура). Если делается попытка вызвать какую-либо процедуру с параметром Y, большим 5, для раздела, уже содержащего внешний объект, то выводится сообщение об ошибке «При наличии внешних объектов режим прокрутки для всего раздела недоступен». Если же в разделе, уже имеющем элементы данных или комментарии, размещенные в неотображаемых строках, делается попытка разместить внешний объект, то выводится сообщение об ошибке «Раздел данных в режиме прокрутки не может содержать внешние объекты».

Возможность прокрутки разделов исходных и результирующих данных добавлена, прежде всего, для использования в заданиях по параллельному программированию. Однако она может оказаться полезной и в других случаях, например, при использования в качестве исходных данных нескольких двумерных массивов или массива строк. Большое количество заданий с прокруткой разделов исходных и результирующих данных содержится в группе Align, входящей в задачник по строковым алгоритмам биоинформатике Programming Taskbook for Bio.

В режиме окна с динамической компоновкой, появившемся в версии 4.11 задачника, раздельная прокрутка разделов не поддерживается, поэтому описанные в данном пункте возможности приводят в данном режиме лишь к увеличению высоты соответствующего раздела задания. Однако и в этом случае сохраняется указанное выше ограничение: параметр Y нельзя указывать большим 5, если в разделе присутствуют «внешние объекты» (файлы или динамические структуры). Отметим также, что начиная с версии 4.21, в окне задачника доступна только динамическая компоновка.

Импортирование существующих заданий в новую группу


[Pascal]

procedure UseTask(GroupName: string; TaskNumber: integer);
procedure UseTask(GroupName: string; TaskNumber: integer; TopicDescription: string);

[C++]

void UseTask(const char* GroupName, int TaskNumber);
void UseTask(const char* GroupName, int TaskNumber, const char* TopicDescription);

[C#, class PT4.TaskMaker]

protected static void UseTask(string GroupName, int TaskNumber);
protected static void UseTask(string GroupName, int TaskNumber, string TopicDescription);

Данная процедура позволяет импортировать в создаваемую группу задание с номером TaskNumber из группы GroupName. Она обычно вызывается непосредственно в основной процедуре группы. Если импортируемое задание не найдено, то при попытке его запуска в окне задачника выводится сообщение «Задание не реализовано для текущего языка программирования», и этот же текст, выделенный курсивом, указывается в html-описании группы после имени, которое должно быть связано с импортированным заданием.

При использовании мини-варианта задачника импортированные задания будут доступны для выполнения только в том случае, если они доступны для выполнения в исходных группах.

В параметре GroupName после имени группы можно дополнительно указывать поправку для вычисления ссылки на другое задание (поправка является целым числом и отделяется от имени группы символом #). Например, если в группу Demo в качестве задания Demo10 импортируется задание Proc46, а в качестве Demo11 — задание Proc49, ссылающееся на Proc46, то при импортировании задания Proc49 необходимо указать поправку, равную 2. Если этого не сделать, то в формулировке задания Demo11 будет указана ссылка не на задание Demo10, а на задание Demo8 (поскольку оно находится «на том же расстоянии» от задания Demo11, что и задание Proc46 относительно задания Proc49). Добавление поправки 2 должно быть оформлено следующим образом: UseTask('Proc#2',49).

Вариант процедуры с тремя параметрами доступен, начиная с версии 4.18 конструктора. Третий параметр TopicDescription позволяет изменить заголовок группы (или подгруппы), связанный с импортируемым заданием. Если данный параметр отсутствует или является пустой строкой, то для импортируемого задания используется его исходный заголовок. При запуске задания для версий задачника, предшествующих версии 4.18, значение параметра TopicDescription игнорируется.

Документирование группы заданий

Группы заданий можно снабжать комментариями, делая их «самодокументируемыми». Комментарии можно добавлять не только к группе, но и к ее подгруппам, т. е. наборам подряд идущих заданий в пределах группы (для включения задания в определенную подгруппу необходимо указать заголовок этой подгруппы в качестве параметра процедуры CreateTask).

Комментарии не отображаются в окне задачника, но включаются в html-описание группы. Они располагаются между заголовком группы (подгруппы) и формулировками заданий. Таким образом, эти комментарии представляют собой преамбулы к группе или ее подгруппам.

Определять преамбулу к подгруппе имеет смысл только в случае, если с этой подгруппой связаны некоторые задания, входящие в определяемую группу. Если группа не содержит заданий, связанных с некоторой подгруппой, то преамбула этой подгруппы в html-описании не выводится.

Для определения преамбул предназначены следующие процедуры.


[Pascal]

procedure CommentText(S: string);

[C++]

void CommentText(const char* S);

[C#, class PT4.TaskMaker]

protected static void CommentText(string S);

Данная процедура добавляет содержимое строки S к текущей преамбуле, отделяя это содержимое от предыдущего текста преамбулы пробелом. В строке S можно использовать управляющие последовательности, обеспечивающие ее форматирование. Например, для перехода к новому абзацу преамбулы следует использовать последовательность \P (управляющие последовательности чувствительны к регистру букв).


[Pascal]

procedure UseComment(GroupName: string[; SubgroupName: string]);

[C++]

void UseComment(const char* GroupName[, const char* SubgroupName]);

[C#, class PT4.TaskMaker]

protected static void UseComment(string GroupName[, string SubgroupName]);

Процедура UseComment добавляет к текущей преамбуле текст преамбулы подгруппы SubgroupName группы GroupName или, если параметр SubgroupName является пустой строкой или отсутствует, текст преамбулы самой группы GroupName. Этот текст отделяется от предыдущего текста преамбулы пробелом. Регистр символов в параметрах GroupName и SubgroupName может быть произвольным.

Если группа с именем GroupName не найдена или в ней отсутствует подгруппа SubgroupName, то процедура не выполняет никаких действий; сообщение об ошибке в этом случае не выводится.

Процедуры CommentText и UseComment должны вызваться после функции CreateGroup; при этом они определяют преамбулу данной группы. Для того чтобы они определяли преамбулу какой-либо подгруппы данной группы, перед их вызовом необходимо вызвать процедуру Subgroup, описываемую далее.


[Pascal]

procedure Subgroup(SubgroupName: string);

[C++]

void Subgroup(const char* SubgroupName);

[C#, class PT4.TaskMaker]

protected static void Subgroup(string SubgroupName);

Данная процедура устанавливает режим добавления текста к преамбуле подгруппы SubgroupName текущей группы. Этот режим сохраняется до следующего вызова данной процедуры или до завершения определения текущей группы заданий (определение группы, создаваемой в виде dll-файла, завершается при выходе из процедуры inittaskgroup).

Процедуру Subgroup можно вызывать несколько раз для одной и той же подгруппы, при этом ранее определенный текст преамбулы будет дополняться новыми данными. При вызове процедуры Subgroup с параметром — пустой строкой устанавливается режим дополнения преамбулы группы (напомним, что этот режим устанавливается также сразу после вызова процедуры CreateGroup).

Константы и функции для определения текущего состояния задачника


[Pascal]

const
  lgPascal       = $0000001;
  lgPascalABCNET = $0000401;
  lgPascalABCNET_flag
                 = $0000400;
  lgVB           = $0000002;
  lgCPP          = $0000004;
  lgC            = $0000008;
  lg1C           = $0000040;
  lgPython       = $0000080;
  lgPython3      = $1000080;
  lgPython3_flag = $1000000;
  lgCS           = $0000100;
  lgVBNET        = $0000200;
  lgFS           = $0000800;
  lgJava         = $0010000;
  lgRuby         = $0020000;
  lgJulia        = $0040000;
  lgWithPointers = $000003D;
  lgWithObjects  = $0FFFF80;
  lgNET          = $000FF00;
  lgAll          = $0FFFFFF;

[C++]

#define lgPascal      0x0000001
#define lgPascalABCNET 0x0000401
#define lgPascalABCNET_flag 0x0000400
#define lgVB           0x0000002
#define lgCPP          0x0000004
#define lgC            0x0000008
#define lg1C           0x0000040
#define lgPython       0x0000080
#define lgPython3      0x1000080
#define lgPython3_flag 0x1000000
#define lgCS           0x0000100
#define lgVBNET        0x0000200
#define lgFS           0x0000800
#define lgJava         0x0010000
#define lgRuby         0x0020000
#define lgJulia        0x0040000
#define lgWithPointers 0x000003D
#define lgWithObjects  0x0FFFF80
#define lgNET          0x000FF00
#define lgAll          0x0FFFFFF

[C#, class PT4.TaskMaker]

protected const int
    lgPascal       = 0x0000001,
    lgPascalABCNET = 0x0000401,
    lgPascalABCNET_flag
                   = 0x0000400,
    lgVB           = 0x0000002,
    lgCPP          = 0x0000004,
    lgC            = 0x0000008,
    lg1C           = 0x0000040,
    lgPython       = 0x0000080,
    lgPython3      = 0x1000080,
    lgPython3_flag = 0x1000000,
    lgCS           = 0x0000100,
    lgVBNET        = 0x0000200,
    lgFS           = 0x0000800,
    lgJava         = 0x0010000,
    lgRuby         = 0x0020000,
    lgJulia        = 0x0040000,
    lgWithPointers = 0x000003D,
    lgWithObjects  = 0x0FFFF80,
    lgNET          = 0x000FF00,
    lgAll          = 0x0FFFFFF;

Приведен набор констант для конструктора версии 4.23.

Данные константы, совместно с описываемой далее функцией CurrentLanguage, позволяют определить язык программирования, на который в данный момент (т. е. в момент инициализации текущей группы заданий) настроен задачник. Константы lgPascal, lgVB, lgCPP, lgC, lgCS, lgVBNET, lg1C, lgPython, lgJava, lgRuby, lgFS, lgJulia соответствуют конкретному языку из числа тех, которые доступны в текущей версии задачника (Pascal, Visual Basic, C++, C, C#, Visual Basic .NET, 1С:Предприятие, Python, Java, Ruby, F#, Julia). Эти константы являются битовыми флагами. Константа lg1C появилась в версии 4.9 конструктора учебных заданий (в связи с реализацией комплекса PT for 1C — варианта задачника для системы 1С:Предприятие), константа lgPython — в версии 4.10, константа lgJava — в версии 4.11, константа lgRuby — в версии 4.12, константа lgFS — в версии 4.19, константа lgJulia — в версии 4.22, константа lgС — в версии 4.23.

Некоторые константы являются комбинациями битовых флагов (т. е. битовыми масками) и позволяют определить, к какой категории относится текущий язык:

  • lgAll — любой язык,
  • lgNET — язык платформы .NET (языки PascalABC.NET, C#, Visual Basic .NET, F#),
  • lgWithPointers — язык, для которого можно разрабатывать группы заданий на обработку динамических структур с применением указателей (языки Pascal, C и C++, а также PascalABC.NET),
  • lgWithObjects — язык, для которого можно разрабатывать группы заданий на обработку динамических структур с применением объектов (все языки платформы .NET, а также Python, Java, Ruby, Julia).

Особое место занимает язык PascalABC.NET, поскольку в нем объединяются свойства обычного языка Pascal и языка платформы .NET. Данному языку соответствует комбинация флагов lgPascal и lgPascalABCNET_flag; это, в частности, означает, что он принадлежит одновременно к категориям lgWithPointers, lgWithObjects и lgNET. Для языка PascalABC.NET предусмотрена также именованная константа lgPascalABCNET.

В версии 4.14 в набор констант были добавлены константы, позволяющие различать версии 2 и 3 языка Python. Это флаг lgPython3_flag, а также константа lgPython3, являющаяся комбинацией флагов lgPython и lgPython3_flag. Для версии 2 языка Python функция CurrentLanguage возвращает константу lgPython, а для версии 3 — константу lgPython3.

В версии 4.22 прежнее значение $00FFF80 константы lgWithObjects изменено на $0FFFF80 (поскольку естественно ожидать, что новые поддерживаемые языки будут входить именно в эту категорию).


[Pascal]

function CurrentLanguage: integer;

[C++]

int CurrentLanguage();

[C#, class PT4.TaskMaker]

protected static int CurrentLanguage();

При использовании задачника совместно с системой PascalABC.NET функция CurrentLanguage всегда возвращает значение lgPascalABCNET.

Функция возвращает значение, соответствующее языку программирования, на который в данный момент настроен задачник. Вместо явного сравнения возвращаемого значения функции с константами, приведенными выше, во многих случаях оказывается более удобным использовать побитовые операции. В качестве примера приведем выражение, проверяющее, что текущий язык программирования относится к категории языков платформы .NET:

[Pascal]

CurrentLanguage and lgNET <> 0

[C++, C#]

(CurrentLanguage() & lgNET) != 0

Если требуется проверить, что текущим языком является одна из версий языка Python, то следует использовать выражение CurrentLanguage and lgPython <> 0, если же необходимо убедиться в том, что применяется версия 3 данного языка, то можно либо выполнить явное сравнение CurrentLanguage = lgPython3, либо проверить наличие флага lgPython3_flag: CurrentLanguage and lgPython3_flag <> 0.


[Pascal]

function CurrentLocale: string;

[C++]

char* CurrentLocale();

[C#, class PT4.TaskMaker]

protected static string CurrentLocale();

Функция возвращает строку, соответствующую текущей локали, т. е. текущему языку интерфейса, используемому в задачнике. Начиная с версии 4.10 конструктора учебных заданий, возможными возвращаемыми значениями функции CurrentLocale являются 'ru' (русский вариант задачника) и 'en' (английский вариант).


[Pascal]

function CurrentVersion: string;

[C++]

char* CurrentVersion();

[C#, class PT4.TaskMaker]

protected static string CurrentVersion();

Данная функция добавлена в версию 4.10 конструктора учебных заданий. Она возвращает номер текущей версии задачника в виде строки числа формата 'd.dd'. В частности, в случае версии 4.10 возвращается строка '4.10'. Для предыдущих версий задачника функция возвращает строку '4.00'.

Образцы слов и предложений

Приведенные ниже элементы конструктора PT4TaskMaker позволяют получить доступ к встроенным в него образцам текстовых исходных данных: словам (Word), предложениям (Sentence) и многострочным текстам (Text).


[Pascal]

const
  SampleError = '#ERROR?';
  MaxLineCount = 50;

function WordCount: integer;
function SentenceCount: integer;
function TextCount: integer;
function WordSample(N: integer): string;
function SentenceSample(N: integer): string;
function TextSample(N: integer): string;

function EnWordCount: integer;
function EnSentenceCount: integer;
function EnTextCount: integer;
function EnWordSample(N: integer): string;
function EnSentenceSample(N: integer): string;
function EnTextSample(N: integer): string;

[C++]

#define SampleError "#ERROR?"
#define MaxLineCount 50

int WordCount();
int SentenceCount();
int TextCount();
char* WordSample(int N);
char* SentenceSample(int N);
char* TextSample(int N);

int EnWordCount();
int EnSentenceCount();
int EnTextCount();
char* EnWordSample(int N);
char* EnSentenceSample(int N);
char* EnTextSample(int N);

[C#, class PT4.TaskMaker]

protected const string SampleError = "#ERROR?";
protected const int MaxLineCount = 50;

protected static int WordCount();
protected static int SentenceCount();
protected static int TextCount();
protected static string WordSample(int N);
protected static string SentenceSample(int N);
protected static string TextSample(int N);

protected static int EnWordCount();
protected static int EnSentenceCount();
protected static int EnTextCount();
protected static string EnWordSample(int N);
protected static string EnSentenceSample(int N);
protected static string EnTextSample(int N);

Функции WordSample, SentenceSample и TextSample возвращают текстовые данные, соответствующие текущей локали, т. е. текущему языку интерфейса, используемому в задачнике (см. функцию CurrentLocale): для русского варианта задачника возвращаются русские данные, для английского — английские. Варианты этих функций, снабженные префиксом En, возвращают английские текстовые данные в любом варианте задачника.

Функции, оканчивающиеся словом Count, возвращают количество соответствующих элементов данных. В версии 4.11, конструктора учебных заданий, как и в его предыдущих версиях, доступно 116 слов, 61 предложение и 85 текстов как на русском, так и на английском языке.

Функции WordSample/EnWordSample и SentenceSample/EnSentenceSample возвращают соответственно слово или предложение с индексом N (индексирование проводится от 0).

Функция TextSample/EnTextSample возвращает строку, связанную с многострочным текстом, имеющим индекс N (индексирование также проводится от 0). При этом между соседними строками этого текста располагаются символы #13#10 (маркеры конца строки). В конце текста маркер конца строки отсутствует, число строк в тексте не превышает значения константы MaxLineCount. Любой текст состоит из нескольких абзацев; между абзацами текста помещается одна пустая строка, отступы в начале абзацев («красная строка») не используются. В тексте не используются также переносы слов.

Если параметр N является недопустимым, то все функции возвращают особую строку, равную константе SampleError.

Буква «ё» в русских текстовых данных не используется.

Все слова-образцы состоят из заглавных (прописных) букв. Помимо слов «общего вида» в набор слов включены слова, обладающие следующими особенностями (наличие подобных особых слов может оказаться полезным при составлении заданий):

  • слова, начинающиеся и оканчивающиеся одной и той же буквой;
  • слова, содержащие три одинаковые буквы (в русском наборе — три буквы «А», в английском наборе — три буквы «E»).

Длина предложений-образцов не превосходит 76 символов; таким образом, любое предложение умещается на одной экранной строке (напомним, что строки при выводе в окне задачника обрамляются апострофами).

Многострочные тексты предназначены для использования, прежде всего, в заданиях на обработку текстовых файлов (см. реализацию подобного задания в разделе «Примеры»).

Использование графики

Начиная с версии 4.14, в формулировки учебных заданий можно включать графические иллюстрации. Каждая иллюстрация оформляется в виде отдельного графического файла формата png или jpg. Рекомендуется размещать графические файлы в подкаталоге LIB\Graph системного каталога задачника, однако допустимо в качестве места их размещения использовать другие подкаталоги каталога LIB, сам подкаталог LIB или рабочий каталог учащегося. В качестве имени файла желательно указывать имя задания и его порядковый номер, а также префикс «G», например, GDemoTask1.png.

При задании формулировки задания (с помощью процедуры TaskText) в том месте формулировки, в котором следует поместить рисунок, необходимо указать управляющую последовательность вида \G<имя графического файла> (имя файла снабжается расширением и указывается в угловых скобках). Перед именем файла можно указать имя подкаталога каталога LIB, в котором планируется разместить данный графический файл, например, \G<Graph\GDemoTask1.png>.

Графический файл последовательно ищется в следующих каталогах:

  • в подкаталоге каталога LIB, если в команде \G явно указан подкаталог;
  • в самом каталоге LIB;
  • в рабочем каталоге учащегося.

При отображении задания в окне задачника связанные с ним рисунки выводятся в правом верхнем углу экрана в порядке, соответствующем порядку их появления в тексте заданий. Для увеличения или уменьшения масштаба рисунков на 20 % от их текущего размера достаточно щелкнуть на одном из рисунков левой или, соответственно, правой кнопкой мыши или использовать клавиатурные комбинации [Ctrl]+[Alt]+[+] или [Ctrl]+[Alt]+[–]. Рисунки всегда отображаются поверх основного окна задачника (и окон других приложений). Если графический файл не найден или имеет неверный формат, то в окне, предназначенном для отображения данного файла, выводится соответствующее сообщение об ошибке.

При отображении заданий в html-документе связанные с ним рисунки выводятся непосредственно в тексте формулировки задания (в позиции соответствующей управляющей последовательности \G). Каждый рисунок выводится на отдельной строке в пределах текущего абзаца. Если графический файл не найден или имеет неверный формат, то в html-документе в позиции вставки рисунка выводится имя графического файла в рамке (без пути, если файл не найден, или с полным путем, если файл имеет неверный формат).


PrevNext

 

Рейтинг@Mail.ru

Разработка сайта:
М. Э. Абрамян, В. Н. Брагилевский

Последнее обновление:
01.01.2024