`

W Cat - Описание языка PascalABC.NET

Перейти на страницу:

var

f1,f2: text;

f1name, f2name: string;

procedure StartExam;

var

s: string;

begin

Str(RandomN(10000, 99999), s);

f1name := 'pt1' + s + '.tst';

f2name := 'pt2' + s + '.tst';

Assign(f1, f1name);

Rewrite(f1);

Assign(f2, f2name);

Rewrite(f2);

end;

procedure EndExam;

begin

Close(f1);

Close(f2);

DataS(f1name, 3, 1);

DataS(f2name, 45, 1);

DataFileT(f1name, 1, 5);

ResultFileT(f2name, 1, 5);

end;

Обсудим особенности этих процедур. Имена файлов, создаваемых в процедуре StartExam, имеют вид pt1#####.tst (для файла с исходными данными) и pt2#####.tst (для файла с контрольными данными), причем в позициях, помеченных символом #", располагаются цифры, выбираемые случайным образом. Тем самым обеспечиваются все требования к именам файлов: они генерируются случайным образом, имеют расширение .tst, и имя файла с исходными данными всегда отличается от имени контрольного файла. Напомним, что все файлы с расширением .tst автоматически удаляются из рабочего каталога после проверки учебного задания.

При анализе процедуры EndExam следует обратить внимание на то, что информация о содержимом исходного файла занимает всю область исходных данных (строки с первой по пятую -- см. вызов процедуры DataFileT) и, таким образом, она скрывает информацию об именах файлов, ранее выведенную в первой строке области исходных данных (см. вызовы процедур DataS). В обычном задании такая реализация была бы ошибочной, поскольку учащийся не увидел бы на экране имена файлов и не понял бы, что эти имена необходимо ввести и обработать в его программе. Однако в задании групп Exam именно такая реализация является правильной, поскольку ввод имен файлов и связывание этих файлов со стандартными потоками ввода-вывода выполняется автоматически (незаметно" для программы учащегося), и поэтому информацию об именах файлов на экране отображать не следует.

Итак, наличие процедур StartExam и EndExam позволяет нам упростить реализацию заданий: после определения формулировки любого задания нам достаточно вызвать процедуру StartExam, заполнить файлы f1 и f2 исходными и, соответственно, контрольными данными и вызвать процедуру EndExam.

Приступим к непосредственной реализации заданий. Поскольку эти задания являются однотипными, реализуем их в одной процедуре Exam1, снабдив ее параметром m: при m = 1 будет инициализироваться первое задание, а при m = 2 -- второе:

procedure Exam1(m: integer);

var

n, i: integer;

a: array[1..10] of real;

begin

CreateTask('Преобразование массивов');

case m of

1:

begin

TaskText('На вход в первой строке подается целое положительное четное число {N},', 0, 1);

TaskText('а во второй строке = массив из {N} вещественных чисел. Поменять местами', 0, 2);

TaskText('его первый элемент со вторым, третий с четвертым, и т.,д. Вывести', 0, 3);

TaskText('преобразованный массив в одной строке, для каждого элемента', 0, 4);

TaskText('отводить 7 экранных позиций.', 0, 5);

end;

2:

begin

TaskText('На вход в первой строке подается целое положительное четное число {N},', 0, 2);

TaskText('а во второй строке = массив из {N} вещественных чисел. Поменять местами', 0, 3);

TaskText('первую и вторую половину элементов массива. Вывести преобразованный массив', 0, 4);

TaskText('в одной строке, для каждого элемента отводить 7 экранных позиций.', 0, 5);

end;

end;

StartExam;

n := 2 * RandomN(1, 5);

for i := 1 to n do

a[i] := RandR(-99, 99);

writeln(f1,n);

for i := 1 to n - 1 do

write(f1, a[i]:0:2, ' ');

writeln(f1, a[n]:0:2);

for i := 1 to n div 2 do

case m of

1: SwapR(a[2*i - 1], a[2*i]);

2: SwapR(a[i], a[i + n div 2]);

end;

for i := 1 to n do

write(f2, a[i]:7:2);

writeln(f2);

EndExam;

SetTestCount(3);

end;

Обратите внимание на то, что при вызове процедуры CreateTask ей передается строковый параметр, содержащий имя подгруппы "Преобразование массивов". Это обеспечивает включение новых заданий в подгруппу, с которой связаны ранее импортированные в нашу группу задания ExamBegin71 и ExamBegin72.

Размер исходного массива всегда будет четным и не превосходящим 10; последнее условие необходимо для того, чтобы все исходные данные можно было разместить на одной экранной строке.

В обоих заданиях значения элементов исходного массива можно выбирать произвольным образом из некоторого диапазона. Мы выбрали диапазон от -99 до 99, поскольку в этом случае при отображении чисел с двумя дробными знаками они будут занимать не более 6 экранных позиций.

При записи в файл элементов исходного массива между ними всегда располагается по одному пробелу, поскольку такой порядок организации исходных данных принят во всех заданиях групп ExamBegin и ExamTaskC. Чтобы обеспечить при этом отображение вещественных чисел с двумя дробными знаками, используется специальный набор форматирующих атрибутов: ":0:2". При выводе результатов, согласно формулировке задания, необходимо отводить для каждого элемента массива по 7 экранных позиций и выводить его с двумя дробными знаками (последнее условие принято по умолчанию во всех заданиях групп ExamBegin и ExamTaskC, использующих вещественные данные). Поэтому при выводе применяются другие форматирующие атрибуты: ":7:2".

Так как алгоритм решения обеих задач не содержит ветвлений, для проверки его правильности достаточно небольшого числа тестовых запусков. Мы установили это число равным трем, указав его в качестве параметра процедуры SetTestCount.

Нам осталось включить вызовы процедуры Exam1 (с параметрами, равными 1 и 2) в основную процедуру группы InitTask, связав эти вызовы с номерами заданий. Следует разместить новые задания сразу после импортированных заданий ExamBegin71 и ExamBegin72, так как все эти задания относятся к одной и той же подгруппе "Преобразование массивов". При этом номера последних 12 заданий увеличатся на 2:

procedure InitTask(num: integer);

begin

case num of

1..2: UseTask('ExamBegin', 70 + num);

3..4: Exam1(num - 2);

5..16: UseTask('ExamTaskC', 20 + num);

end;

end;

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

Для просмотра новых заданий в окне задачника надо заменить в параметре процедуры Task тестирующей программы символ "#" на "?": Task('ExamDemo?').

При нажатии клавиши [F9] мы увидим на экране окно задачника в демо-режиме, в котором можно выбрать и просмотреть все задания, включенные к настоящему моменту в нашу группу. Приведем вид окна для задания ExamDemo4 (напомним, что это задание инициализируется посредством вызова процедуры Exam1 с параметром, равным 2):

Добавление заданий повышенной сложности

Наша группа ExamDemo к настоящему моменту содержит 12 заданий повышенной сложности, импортированных из группы ExamTaskC. Все эти задания связаны с общей предметной областью; они содержат сведения об абитуриентах и включают их фамилии, номера школ и годы поступления в вузы. Для того чтобы проиллюстрировать некоторые особенности, связанные с разработкой подобных заданий, дополним набор уже имеющихся заданий двумя новыми заданиями из той же предметной области.

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

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

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

Перейти на страницу:

Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение W Cat - Описание языка PascalABC.NET, относящееся к жанру Детская образовательная литература. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.

Комментарии (0)