Смекни!
smekni.com

Тест программных программ (стр. 2 из 5)

End;

Readln;

Write('Фамилия: '); {вписывание фамилии}

Readln(a);

d:=length(a); {выставление пробелов}

Write(b1,a); {запись в файл}

For i:=1 to 14-d do Write(b1,' ');

Write('Имя: '); {вписывание имени, процедура повторяется}

Readln(a);

Write(b1,a);

d:=length(a);

For i:=1 to 11-d do Write(b1,' ');

Write('Отчесчтво: '); {вписывание отчества, процедура повторяется }

Readln(a);

Write(b1,a);

d:=length(a);

For i:=1 to 17-d do Write(b1,' ');

Write(b1,f);

d:=length(f);

For i:=1 to 8 do Write(b1,' ');

GetDate(g1,g2,g3,g4); {проставление даты}

Writeln(b1,g3,'.',g2,'.',g1);

close(b1);

Window(15,10,50,19);

TextBackGround(black);

clrscr;

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

Таймер, системное время.

Таймер был разработан для отсчета времени на тест, время вводится предварительно составителем теста. Кроме того, параллельно с выводом времени на тест выводится текущее системное время. Действие таймера основано на переменной-счетчике, которая через определенные промежутки времени уменьшает свое значение на 1(секунду). Системное время выводится благодаря процедуре GetTime.

Repeat {цикл счетчика времени}

Window(60,20,70,21); {окно вывода времени}

TextBackGround(black);

clrscr;

z2:=z2-1; {обратный отсчет секунд}

If z2<0 Then Begin {обнуление счетчика}

z1:=z1-1;

z2:=60;

End;

If (z1=0)and(z2=0) Then GoTo l1; {проверка исхода времени}

GetTime(g1,g2,g3,g4); {вывод таймера и текущего времени}

Writeln(z1,':',z2); {вывод времени на экран}

Write(g1,':',g2,' ',g3);

Delay(1000);

until keypressed;

Объявляется переменная, из которой каждую секунду вычитается 1. Так осуществляется обратный отсчет. С исходом времени программа автоматически переходит к выставлению оценки.

Оконная система диалога.

Поскольку прошлая моя работа была посвящена диалоговым системам, я учел тот опыт, но в этой программе сделал нововведение, приблизившее программу к современному «оконному» виду.

Над оформлением окна пришлось посидеть не один час, так как обычное окно в виде квадрата на экране совсем не привлекательно. Я изучил строение окон в среде MS-DOS и попытался воссоздать дизайн окна в своей программе. Если вы когда-либо видели схему окна в MS-DOS, то заметили, что окно обрамляется двойной рамкой, наверху которой находится название окна. Здесь мне помогло хитрое решение. Я заглянул в таблицу символов ASCII и нашел символ двойной рамки! Далее все просто: открывается окно, закрашивается, по краям с помощью циклов рисуется рамка и выводится название окна. Но это еще не все. Внутри окна открывается другое окно того же цвета, чтобы было незаметно. Теперь при вводе или выводе данных рамка не будет двигаться вместе с текстом, разрываться и т. д. Мы получаем полноценное окно.

Я сделал оформление окна в виде процедуры, необходимо лишь ввести координаты окна и его название. Ниже приведен код оформления окна:

Procedure windows(x,y,x1,y1:integer; b:string);

Var a,t:integer;

Begin

Window (x+1,y+1,x1+1,y1+1); {рисование тени от окна}

TextBackGround(black);

clrscr;

Window(x,y,x1,y1); {рисование окна}

TextBackGround(blue);

clrscr;

TextColor(darkgray); {цвет текста}

Write(' ');

Write(chr(201)); {рисование уголка}

For a:=1 to 4 do Write(chr(205)); {рисование полосы}

Write(' ');

TextColor(green); {цвет текста}

Write(b); {вывод названия окна}

Write(' ');

TextColor(darkgray); {цвет текста}

For a:=1 to (x1-x-9-length(b)) do Write(chr(205)); {рисование линии}

Writeln(chr(187)); {рисование уголка}

For a:=1 to (y1-y-1) do Begin {рисование линий по бокам}

Write(' ');

Write(chr(186));

For t:=1 to (x1-x-3) do Write(' ');

Writeln(chr(186));

End;

Write(' ');

Write(chr(200)); {рисование уголка}

For a:=1 to (x1-x-3) do Write(chr(205)); {рисование линии}

Write(chr(188)); {рисование уголка}

Window(x+2,y+1,x1-2,y1-1); {открытие окна ввода внутри окна}

TextColor(black);

End;

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

Вот как это выглядит в программе:

Window(10,22,69,22); {указывается окно с координатами}

TextBackGround(green); {задается цвет фона}

clrscr; {окно закрашивается}

Введение процедур. Основные функции редактора.

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

Я до сих пор говорил об основных функциях редактора, но не показывал их программного кода. Начнем с функции создания теста. Она создает файл теста и файл ответов, последовательно записывает вопросы и ответы и затем закрывает файл.

Procedure NewF;

Var h1:string; {объявление локальных переменных}

Begin

Window(10,10,53,15);

TextBackGround(black);

clrscr;

Window(20,10,66,15); {начальное окно}

TextBackGround(blue);

clrscr;

TextColor(black);

Write('сохранить файл как ');

Readln(a); {ввод пути создаваемого файла без расширения}

a:=a+'.ts'; {дописывание расширения}

h1:=a;

Assign(c,a); {связь переменной с файлом вопросов}

a:=a+'o'; {изменение расширения}

Assign(u,a); {связь переменной с файлом ответов}

Rewrite(c);

Rewrite(u);

Window(20,10,66,15); {закрытие окна}

TextBackGround(black);

clrscr;

Window(30,5,50,10); {открытие окна характеристик}

TextBackGround(yellow);

clrscr;

GoToXY(30,6);

Write('кол-во вопросов ');

Readln(d); {ввод количества вопросов}

Writeln(c,' ',d);

GoToXY(30,8);

Writeln('название теста '); {ввод названия теста}

Readln(f);

Writeln(c,f);

Writeln('пароль на защиту');

Readln(f); {ввод пароля}

Writeln(u,f);

Window(30,5,50,10);

TextBackGround(black);

clrscr;

For i:=1 to d do Begin

Writeln(c);

Window(10,10,53,20); {окно вопроса}

TextBackGround(lightgray);

clrscr;

Writeln(i,'-й вопрос: ');

Readln(a); {ввод вопроса}

Str(i,f);

f:=f+')'; {запись вопроса в файл}

Writeln(c,f);

Writeln(c,a);

Window(55,10,80,15); {окно количества ответов}

TextBackGround(cyan);

clrscr;

Write('количество ответов на ',i,'-й вопрос ');

Readln(e); {ввод количества ответов}

Window(10,10,53,20); {окно ответов}

TextBackGround(lightgray);

clrscr;

For j:=1 to e do Begin

Write(' ',j,')');

Readln(a); {ввод ответов}

Str(j,f);

a:=' '+f+')'+a;

Write(c,a);

End;

Write(c,'&'); {запись в файл конца ввода}

Window(55,10,80,15);

TextBackGround(cyan); {окно правильного ответа}

clrscr;

Write('Правильный ответ: ');

Readln(b); {ввод правильного ответа}

Writeln(u,b);

End;

close(u); {закрытие файлов и окон}

Reset(u);

Readln(u);

close(c);

Window(55,10,80,15);

TextBackGround(black);

clrscr;

End;

В этой, как и в других функциях, работающих с файлами, я столкнулся с проблемой записи тестов в файлах. Во-первых, я решил разделить сам тест и ответы к нему. Тест находится в файле с расширением qs, а ответы к нему- в файле с расширением qso. Второй проблемой стала остановка чтения вопроса, ведь вопросы должны выводиться не подряд, а по очереди. В связи с этим я использовал символ «&» в конце каждого вопроса и указал программе читать до этого символа, но сам символ не выводить. Можно было использовать счетчик строк, который останавливает программу после прочтения двух строк (вопрос и варианты ответов), но в случае сбоя тест приходит в негодность. Далее требовалось разместить данные о названии теста, количестве вопросов, пароле и т. п. Я разместил их по этим двум файлам. Опытные программисты заметят: зачем было использовать текстовые файлы, ведь можно было применить работу с типом «запись» и сохранять данные в нетипизированных файлах, и шифровщик бы не потребовался. Действительно, но использование типа «запись» не позволяет создавать тесты с динамическим числом ответов на вопрос. Это возможно лишь путем использования в записи динамического массива. Но это сделает работу с файлом очень сложной а сам файл будет занимать много места на диске по сравнению с обычным текстовым.

Естественно, что при поиске файла программа может его не найти, в этом случае выдается ошибка поиска. Требовалось ее обойти, выдавая собственное сообщение программы. Это осуществляется следующим образом: задается директива компиллятора на его отключение $I-, проверяется нулевой результат IORESULT=0, выдается сообщение и компиллятор включается снова $I+. Я использовал эту функцию компиллятора там, где необходимо осуществить поиск файла. Такая функция обхода компилятора называется обработкой сообщений и является составляющей объектного програмимирования.

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

Procedure OpenF;

label l1;

Var f1:string; {объявление локальных переменных}

Begin

p:=0;

Window(10,10,53,15);

TextBackGround(black);

TextColor(black);

clrscr;

Window(20,10,66,15); {начальное окно}

TextBackGround(blue);

clrscr;

Writeln('какой файл открыть ');

Readln(a); {ввод пути к файлу без расширения}