При анализе процедуры 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:
Читать дальше