Журнал LinuxFormat - перейти на главную

LXF158:LaTeX: Мас­си­вы мак­ро­ко­манд

Материал из Linuxformat
Перейти к: навигация, поиск


LaTeX Ав­то­ма­ти­зи­ру­ем ру­тин­ные за­да­чи посредством макрокоманд

Содержание

LaTeX: Мас­си­вы мак­ро­ко­манд

Дмит­рий Цы­май и Ста­ни­слав Ку­цен­ко пред­ла­га­ют раз­ра­ба­ты­вать тес­то­вые за­да­ния для сту­ден­тов сред­ст­ва­ми LaTeX, при­ме­нив их для под­го­тов­ки тек­стов.

LaTeX – по­пу­ляр­ный на­бор мак­ро­рас­ши­рений сис­те­мы ком­пь­ю­тер­ной вер­ст­ки TeX, об­лег­чающий под­го­тов­ку слож­ных до­ку­мен­тов. Применение мак­ро­па­ке­тов по­зво­ля­ет ав­то­ма­ти­зи­ро­вать за­да­чи на­бо­ра тек­ста и под­го­тов­ки ста­тей. LaTeX рас­ши­ряе­м также за счет на­пи­сания соб­ст­вен­ных мак­ро­команд – на­при­мер, при по­мо­щи встро­ен­ной в Tex ко­ман­ды \def, опи­сан­ной в [1]. Что­бы слу­чай­но не пе­ре­оп­ре­де­лить су­ще­ст­вую­щую ко­ман­ду, мож­но поль­зо­вать­ся встро­ен­ны­ми в LaTeX ко­ман­да­ми \newcommand для оп­ре­де­ления но­вой ко­ман­ды и \renewcommand для яв­но­го пе­ре­оп­ре­де­ления су­ще­ст­вую­щей, опи­сан­ны­ми в [2].

Все это удоб­но до тех пор, по­ка не по­тре­бу­ет­ся оп­ре­де­лить достаточно много но­вых мак­ро­команд. Такая за­да­ча вста­ла при раз­ра­бот­ке тес­то­вых за­даний для студентов. Одни и те же во­про­сы мо­гут по­вто­рять­ся в раз­ных тес­то­вых за­даниях, и ра­зум­но оп­ре­де­лить для ка­ж­до­го из них мак­ро­ко­ман­ду: это со­кратит вре­мя и на вер­ст­ку за­даний, и при п­рав­ке во­про­сов. Но слож­ность в том, что ка­ж­дая мак­ро­ко­ман­да требует уникаль­ного имени, а циф­ры в именах ис­поль­зо­вать нель­зя; не­об­хо­ди­мость дер­жать в па­мя­ти мно­же­ст­во но­вых команд сво­дит к ну­лю все пре­иму­ще­ст­ва их по­втор­но­го ис­поль­зо­вания. При вер­ст­ке тес­тов необ­хо­ди­мо иметь способ вста­вить фраг­мент (от­дель­ный во­про­с) в про­из­воль­ное за­дание, не вспо­ми­ная при этом имя команд­ной по­сле­до­ва­тель­но­сти. В [1] опи­са­н вариант реа­ли­за­ции спи­соч­ных мак­ро­команд. Дан­ный под­ход не со­всем удо­бен: он пред­по­ла­га­ет со­хранение всех фраг­мен­тов в оп­ре­де­лении од­ной спи­соч­ной мак­ро­ко­ман­ды.

Одно из воз­мож­ных ре­шений – мас­сив мак­ро­команд. Доста­точ­но оп­ре­де­лить од­но имя мас­си­ва для фраг­мен­тов тек­ста, раз­ме­тить ка­ж­дый во­прос (на­ча­ло и конец) оп­ре­де­лен­ны­ми ог­раничи­ваю­щи­ми ко­ман­да­ми и в дальней­шем об­ра­щать­ся к дан­ным фраг­мен­там по но­ме­рам, в со­от­вет­ст­вии с по­ряд­ком их оп­ре­де­ления в тек­сте. При­своение имен но­вым ко­ман­дам пе­ре­кла­ды­ва­ет­ся на ком­пь­ю­тер, т. е. про­ис­хо­дит про­зрач­но для поль­зо­ва­те­ля.

Ос­нов­ные коман­ды для мас­си­вов

LaTeX не име­ет своих средств для ра­бо­ты с мас­си­ва­ми мак­ро­команд. Встро­ен­ные средства про­грам­ми­ро­вания [3] предлагают:

  • объ­яв­ление мас­си­ва с про­из­воль­ным именем;
  • до­бав­ление в мас­сив про­из­воль­ных эле­мен­тов;
  • пе­ребор всех или час­ти эле­мен­тов мас­си­ва в цик­ле с вы­полнением над эле­мен­тами операций фор­ма­ти­ро­вания.

Разберем осо­бен­но­сти реа­ли­за­ции. Раз имя мак­ро­ко­ман­ды не долж­но вклю­чать араб­ских цифр, за­меним их на рим­ские, ото­бра­жаемые ла­тин­скими буквами. Тогда серия команд \qvery1, \qvery2, \qvery3... за­пишется \qveryi, \qveryii, \qveryiii... . Ка­ж­дое имя бу­дет уникаль­ным, но строка пе­ред рим­ски­ми циф­ра­ми не дол­жна совпадать с су­ще­ст­вую­щими ко­ман­дами LaTeX.

Ко­ман­да \newArray{<имя мас­си­ва>} оп­ре­де­ляет но­вый мас­си­в, и ав­то­ма­ти­че­­ски соз­дает счет­чик массива с именем arraycount<имя оп­ре­де­ляе­мо­го мас­си­ва> и на­чаль­ным зна­чени­ем 1. Па­ра­мет­р ко­ман­ды – имя но­во­го мас­си­ва, под­чи­няющее­ся тем же правилам, что и име­на счет­чи­ков и мак­ро­команд. Оп­ре­де­ление ко­ман­ды –

\def\newArray#1{

\newcounter{arraycount#1}

\setcounter{arraycount#1}{1}

}

Для объ­яв­ле­ния но­во­го мас­си­ва не­об­хо­ди­мо за­пи­сать:

\newArray{<имя мас­си­ва>}

Ко­ман­да \AddItem{<имя мас­си­ва>}{<эле­мент>} позво­ля­ет до­бав­лять эле­мен­ты в объ­яв­лен­ный мас­сив. Ка­ж­дый эле­мент бу­дет хранить­ся в но­вой ко­ман­де, с именем array<имя мас­си­ва><зна­чение счет­чи­ка рим­ски­ми циф­ра­ми>. Та­к обес­пе­чи­ва­ет­ся уни­­каль­ность имени ка­ж­до­го эле­мен­та. На­при­мер, для мас­си­ва с именем qvery име­на мак­ро­команд для 1-го, 2-го и 3-го эле­мен­тов бу­дут, со­от­вет­ст­вен­но, arrayqveryi, arrayqveryii и arrayqveryiii. При вы­полнении ко­ман­ды счет­чик, свя­зан­ный с мас­си­вом, уве­ли­чи­вает­ся на единицу. Ко­ман­да име­ет сле­дую­щее оп­ре­де­ление:

\long\def\AddItem#1#2{%

\expandafter\gdef\csname array#1\roman{arraycount#1}\endcsname{#2}

\global\addtocounter{arraycount#1}{1}

}

Рас­смот­рим эле­мен­ты Tex в составе оп­ре­де­ле­ния. Ко­ман­да

\csname... \endcsname

зада­ет но­вую команд­ную по­сле­до­ва­тель­ность без со­дер­жания; поз­же ее мож­но пе­ре­оп­ре­де­лить. Ко­ман­да \expandafter ­в­елит TeX’у рас­крыть по­сле­до­ва­тель­ность, оп­ре­де­ляю­щую имя но­вой мак­ро­ко­ман­ды, а за­тем оп­ре­де­лить ее гло­баль­но при по­мо­щи \gdef. Ко­ман­да \roman{arraycount#1} вы­во­дит зна­чение счет­чи­ка, свя­зан­но­го с мас­си­вом рим­ски­ми циф­ра­ми. Об­щий син­так­си­с ко­ман­ды – \roman{<имя счет­чи­ка>}.

Эле­мен­та мас­си­ва по его но­ме­ру извлекается коман­дой

\GetItem{<имя мас­си­ва>}{<эле­мент>}

имею­щая два па­ра­мет­ра: имя мас­си­ва и но­мер эле­мен­та.

\long\def\GetItem#1#2{%

\setcounter{temparraycount}{#2}

\ifnum\arabic{temparraycount}<\arabic{arraycount#1}

\csname array#1\roman{temparraycount}\endcsname

\fi

}

Здесь ис­поль­зу­ет­ся вспо­мо­га­тель­ный счет­чик temparraycount, оп­ре­де­лен­ный ранее. Услов­ный опе­ра­тор \ifnum<Ко­ман­ды>\. по­зво­ляет вы­пол­нять ко­ман­ду, если но­мер вы­зы­вае­мо­го эле­мен­та не ­вы­ходит за границы мас­си­ва. Вы­пол­ня­ет­ся сравнение зна­чений счет­чи­ков temparraycount и arraycount<имя мас­си­ва>, пред­став­лен­ные араб­ски­ми циф­ра­ми, ко­ман­дой \arabic{<имя счет­чи­ка>}.

Чис­ло эле­мен­тов мас­си­ва на 1 мень­ше зна­чения счет­чи­ка arraycount#1. Оп­ре­де­ление для ко­ман­ды \ArrayCount{<имя мас­си­ва>} по­лу­чения чис­ла эле­мен­тов мас­си­ва –

\def\ArrayCount#1{

\setcounter{temparraycount}{\arabic{arraycount#1}}

\global\addtocounter{temparraycount}{-1}

\arabic{temparraycount}

\global\addtocounter{temparraycount}{1}

}

Так­же необ­хо­ди­мы ко­ман­ды пе­ре­чис­ления всех эле­мен­тов мас­си­ва. Их две. Од­на яв­ля­ет­ся ана­ло­гом ко­ман­ды foreach... in.... Она принима­ет два па­ра­мет­ра: имя мас­си­ва и ко­ман­ду, ко­то­рую на­до ис­полнить над ка­ж­дым эле­мен­том при его вы­во­де.

\long\def\foreachArray#1#2{%

\setcounter{temparraycount}{1}

\loop\ifnum\arabic{temparraycount}<\arabic{arraycount#1}

  1. 2{\GetItem{#1}{\arabic{temparraycount}}}

\global\addtocounter{temparraycount}{1}

\repeat

}

По­доб­на ей ко­ман­да-ана­ло­г цик­ла for... from... to. У нее 4 па­ра­мет­ра: имя мас­си­ва, но­мера пер­во­го и по­следнего вы­во­ди­мо­го эле­мен­та и операция, ис­пол­няе­мая над эле­мен­тами при вы­во­де.

\long\def\ForFromToArray#1#2#3#4{%

\setcounter{temparraycount}{#2}

\setcounter{temparraycounta}{#3}

\ifnum\arabic{temparraycounta}<\arabic{arraycount#1}

\addtocounter{temparraycounta}{1}

\else

\setcounter{temparraycounta}{\arabic{arraycount#1}}

\fi

\loop\ifnum\arabic{temparraycount}<\arabic{temparraycounta}

  1. 4{\GetItem{#1}{\arabic{temparraycount}}}

\global\addtocounter{temparraycount}{1}

\repeat

}

В двух по­следних оп­ре­де­лениях ко­ман­да \loop\if <усло­вие><те­ло цик­ла>... \repeat по­зво­ля­ет ис­поль­зо­вать цикл. Те­ло цик­ла вы­пол­ня­ет­ся, по­ка ис­тин­но усло­вие по­сле \if.

Мас­си­вы команд в действии

Рас­смот­рим при­ме­ры применения пред­ло­жен­ных команд. Для это­го в пре­ам­бу­ле до­ку­мен­та под­клю­чим файл с оп­ре­де­ления­ми:

\input{texarray}

Оп­ре­де­ля­ем два мас­си­ва: mytestq и mytestw.

\newArray{mytestq} \newArray{mytestw}

До­бав­ля­ем эле­мен­ты в оба мас­си­ва.

\AddItem{mytestq}{фраг­мент 1}

\AddItem{mytestw}{фраг­мент 2}

\AddItem{mytestq}{фраг­мент 3} \

AddItem{mytestw}{фраг­мент 4}

\AddItem{mytestw}{фраг­мент 5}

\AddItem{mytestw}{фраг­мент 6}

\AddItem{mytestw}{фраг­мент 7}

Вы­во­дим вто­рой эле­мент мас­си­ва mytestq: фраг­мент 3.

\GetItem{mytestq}{2}

Ко­ли­че­ст­во эле­мен­тов в мас­си­ве mytestq рав­но 2.

\ArrayCount{mytestq}

Ко­ли­че­ст­во эле­мен­тов в мас­си­ве mytestw рав­но 5.

\ArrayCount{mytestw}

Пе­ре­чис­ля­ем все эле­мен­ты мас­си­ва mytestw:

\foreachArray{mytestw}{}

Ре­зуль­тат: фраг­мент 2 фраг­мент 4 фраг­мент 5 фраг­мент 6 фраг­мент 7

До­бав­ля­ем еще­о­дин эле­мент в мас­сив mytestq:

\AddItem{mytestq}{фраг­мент 8}

Пе­ре­чис­ля­ем все эле­мен­ты мас­си­ва mytestq

\foreachArray{mytestq}{}

Ре­зуль­тат: фраг­мент 1 фраг­мент 3 фраг­мент 8

Пе­ре­чис­лим все эле­мен­ты мас­си­ва mytestq с вы­пол­не­ни­ем операции, задан­ной вторым па­ра­мет­ром, над всеми эле­мен­тами мас­си­ва. Для это­го оп­ре­де­лим ко­ман­ду вы­во­да текста жир­ным кур­си­вом –

\def\testcommand#1{\textbf{\textit{#1}}}

и при­ме­ним ее в вы­зо­ве функ­ции пе­ре­бора эле­мен­тов мас­си­ва.

\foreachArray{mytestq}{\testcommand}

Ре­зуль­тат: фраг­мент 1 фраг­мент 3 фраг­мент 8

Пе­ре­чис­лим эле­мен­ты мас­си­ва mytestw со 2-го по 4-й.

\ForFromToArray{mytestw}{2}{4}{}

Ре­зуль­тат: фраг­мент 4 фраг­мент 5 фраг­мент 6

Вы­ве­дем эле­мен­ты мас­си­ва mytestw со 2-го по 4-й с вы­пол­не­ни­ем операции над ка­ж­дым эле­мен­том мас­си­ва.

\ForFromToArray{mytestw}{2}{4}{\testcommand}

Ре­зуль­тат: фраг­мент 4 фраг­мент 5 фраг­мент 6

Пробуем соз­да­ть тес­ты

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

  • Счет­чи­ки и вспо­мо­га­тель­ные оп­ре­де­ления

Для ра­бо­ты с мак­ро­ко­ман­да­ми оп­ре­де­лим несколь­ко счет­чи­ков:

    • BiletNumber Счет­чик но­мер би­ле­та
    • VoprosNumber Счет­чик для во­про­сов
    • VarOtvNumber Счет­чик ва­ри­ан­тов от­ве­тов

Ус­та­но­вим ука­зан­ные счет­чи­ки рав­ны­ми 1 при по­мо­щи команд

\newcounter{BiletNumber}

\setcounter{BiletNumber}{1}

\newcounter{VoprosNumber}

\setcounter{VoprosNumber}{1}

\newcounter{VarOtvNumber}

\setcounter{VarOtvNumber}{1}

  • Ко­ман­ды для раз­мет­ки ис­ход­ных во­про­сов

Для ра­бо­ты с тес­та­ми мы ис­поль­зу­ем создан­ные на­ми ко­ман­ды ра­бо­ты с мас­си­ва­ми. Оп­ре­де­лим но­вый мас­сив:

\newArray{qvery}

Оп­ре­де­лим ко­ман­ду для обо­зна­чения во­про­са, до­бав­ляю­щую тек­сто­вый фраг­мент в мас­сив qvery, осно­ван­ную на ко­ман­де \AddItem:

\long\def\Qvery #1\endQvery{%

\AddItem{qvery}{#1}

}

К во­про­сам, обо­зна­чен­ным при по­мо­щи \Qvery #1\endQvery, мож­но об­ра­тить­ся по но­ме­ру, со­от­вет­ст­вую­ще­му их по­яв­лению в тек­сте, при по­мо­щи дру­гой ко­ман­ды – \printQ{<но­мер во­про­са>}, осно­ван­ной на ис­поль­зо­вании ко­ман­ды \GetItem{qvery}{<но­мер во­про­са>}.

\long\def\printQ#1{%

\setcounter{VarOtvNumber}{1}

\par\noindent\arabic{VoprosNumber}. % \

GetItem{qvery}{#1}

\addtocounter{VoprosNumber}{1}%

}

В ре­зуль­та­те пе­ча­та­ет­ся эле­мент мас­си­ва qvery с но­ме­ром, коорый па­ра­мет­ром. При­мер вы­пол­не­ния ко­ман­ды показан на рис. 1.

Ва­ри­ант от­ве­та обо­зна­ча­ет­ся ко­ман­дой

\long\def\VarQveryOtv{%

\par\indent\ \ \arabic{VarOtvNumber}) %

\addtocounter{VarOtvNumber}{1}%

}

Ко­ман­ды, оп­ре­де­ляю­щие вид пе­чат­но­го до­ку­мен­та

Эти команды имею­т вспо­мо­га­тель­ное зна­чение. Они могут быть использованы при необходимости.

Зна­чение пе­ре­мен­ной printotv оп­ре­де­ля­ет, по­ме­чать ли в конеч­ном до­ку­мен­те пра­виль­ные от­ве­ты, ес­ли ис­поль­зу­ют­ся ко­ман­ды для обо­зна­чения пра­виль­ных ва­ри­ан­тов от­ве­тов. Ес­ли оно рав­но 1, пра­виль­ные от­ве­ты от­ме­ча­ют­ся. Зна­чение prnsimple оп­ре­де­ля­ет, пе­ча­тать ли все за­го­лов­ки, оп­ре­де­лен­ные для тес­та. Ес­ли оно рав­но 1, пе­ча­та­ют­ся толь­ко основ­ные за­го­лов­ки.

\newcount\printotv

\printotv=0 \

newcount\prnsimple

\prnsimple=0

Зна­чения этих пе­ре­мен­ных для лю­бой час­ти до­ку­мен­та задаются ко­ман­да­ми

  • \printsimple Пе­ча­тать без за­го­лов­ков.
  • \printall Пе­ча­тать с за­го­лов­ка­ми.
  • \setprinttrueotv По­ме­чать пра­виль­ные от­ве­ты на пе­ча­ти
  • \setnoprinttrueotv Не по­ме­чать пра­виль­ные от­ве­ты на пе­ча­ти
  • \trueotv Мар­кер пра­виль­ных от­ве­тов.

Указанные ко­ман­ды дей­ст­ви­тель­ны для остав­шей­ся час­ти тек­ста, по­ка не встре­тит­ся отменяющая ко­ман­да. Приведем определения этих команд:

\def\printsimple{\prnsimple=1}

\def\printall{\prnsimple=0}

\def\setprinttrueotv{\printotv=1}

\def\setnoprinttrueotv{\printotv=0}

\def\trueotv{\ifnum\printotv=1$\bullet $\ \fi}

Кро­ме то­го, вид пе­чат­но­го до­ку­мен­та оп­ре­де­ля­ют пе­ре­мен­ные шаб­ло­на, оп­ре­де­ляю­щие по­сле­дую­щий текст, ко­то­рые мож­но за­дать в лю­бом мес­те до­ку­мен­та. Дальней­шее рас­смот­рение ве­дет­ся на при­ме­ре эк­за­ме­на­ци­он­ных би­ле­тов. При­ве­ден­ные ни­же­ ко­ман­ды по­зво­ля­ют оп­ре­де­лить ряд строк в за­го­лов­ке – на­при­мер, в эк­за­ме­на­ци­он­ных би­ле­тах это стро­ки «Ут­вер­ждаю», «Пред­мет», «Спе­ци­аль­ность», «Зав каф», «Со­ста­вил». Дан­ные ко­ман­ды оп­ре­де­ля­ют, в свою оче­редь, но­вые ко­ман­ды, ис­поль­зуе­мые внут­ри шаб­ло­на.

\def\templateutv#1{\edef\ltemplateutv{#1}}

\def\templatepredm#1{\edef\ltemplatepredm{#1}}

\def\templatespez#1{\edef\ltemplatespez{#1}}

\def\templatezavkaf#1{\edef\ltemplatezavkaf{#1}}

\def\templatesost#1{\edef\ltemplatesost{#1}}

Ана­ло­гич­но оп­ре­де­ля­ет­ся ряд дру­гих па­ра­мет­ров тес­та, та­ких как на­звание под­раз­де­ления, фа­ми­лия ру­ко­во­ди­те­ля, да­та ут­вер­ждения, на­звание ор­ганиза­ции, фа­ми­лия со­ста­ви­те­ля, за­го­ло­вок тес­та, на­звание пред­ме­та, шифр спе­ци­аль­но­сти.

\def\kafedra#1{\edef\lkafedra{#1}}

\def\zavkaf#1{\edef\lzavkaf{#1}}

\def\datautv#1{\edef\ldatautv{#1}}

\def\vuz#1{\edef\lvuz{#1}}

\def\bilettitle#1{\edef\lbilettitle{#1}}

\def\biletauthor#1{\edef\lbiletauthor{#1}}

\def\predmet#1{\edef\lpredmet{#1}}

\def\spez#1{\edef\lspez{#1}}

Пе­ре­оп­ре­де­ление строк шаб­ло­на мо­жно сде­ла­ть в лю­бом мес­те до­ку­мен­та; оно име­ет си­лу, по­ка не встре­тит­ся но­вое оп­ре­де­ление.

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

\templateutv{УТВЕРЖДАЮ}

\templatepredm{Пред­мет}

\templatespez{Спе­ци­аль­ность}

\templatezavkaf{Зав.ка­фед­рой}

\templatesost{Со­ста­вил}

\kafedra{<На­зва­ние ка­фед­ры>}

\zavkaf{<Фа­ми­лия И.О.>}

\datautv{<чч.мv.гг>}

\vuz{<На­зва­ние ВУ­За>}

\bilettitle{<За­го­ло­вок би­ле­та>}

\biletauthor{<Фа­ми­лия И.О.>}

\predmet{<На­зва­ние пред­ме­та>}

\spez{<Спе­ци­аль­но­сти>}

Ко­ман­ды для ком­по­нов­ки от­дель­ных тес­тов

Для ра­бо­ты с от­дель­ны­ми тес­та­ми предусмотрена ко­ман­да для за­го­лов­ка тес­та \BiletHeader. Ре­зуль­тат ее выполнения за­ви­сит от пе­ре­мен­ных шаб­ло­на. Происходит установка счетчика но­ме­ров во­про­сов VoprosNumber равным 1, а счет­чик но­ме­ров би­ле­та BiletNumber уве­ли­чи­ва­ет­ся на 1.

\newcommand{\BiletHeader}{%

\ifnum\prnsimple=0

\nopagebreak \par

\noindent\textbf{\ltemplateutv}

\vspace{0.4cm}\nopagebreak

\par

\ \ltemplatezavkaf <<\lkafedra >>

\par%

\rule[-1pt]{2 cm}{0.4pt} \lzavkaf

\vspace{0.2cm}\nopagebreak

\par%

\ \ltemplatepredm : <<\lpredmet >>\nopagebreak \par

\ \ltemplatespez : \lspez\nopagebreak \par

\ldatautv

\vspace{0.1cm}\nopagebreak \par

\begin{center}

\textbf{\lvuz}\nopagebreak

\end{center}

\fi

\begin{center}

\textbf{\lbilettitle \No \arabic{BiletNumber}}\nopagebreak

\vspace{0.2cm}\nopagebreak

\addtocounter{BiletNumber}{1}

\setcounter{VoprosNumber}{1}

\nopagebreak

\end{center}

}

Ко­ман­да для нижней час­ти тес­та \BiletFooter. Здесь толь­ко ко­ман­ды фор­ма­ти­ро­вания, вы­во­ди­мые в за­ви­си­мо­сти от усло­вий.

\newcommand{\BiletFooter}{%

\ifnum\prnsimple=0

\vspace{0.4cm}\nopagebreak \par

\noindent\ltemplatesost

\rule[-1pt]{1.5cm}{0.4pt}

\lbiletauthor \nopagebreak

\vspace{0.1cm}

\fi

\par

}

Ок­ру­же­ние для би­ле­та, в ко­то­ром ис­поль­зу­ют­ся обе вы­ше­при­ве­ден­ные ко­ман­ды для за­го­лов­ка и ниж­ней час­ти би­ле­та –

\newenvironment{EkzBilet}{\BiletHeader}{\BiletFooter }

Ок­ру­же­ние для спи­ска во­про­сов –

\newenvironment{ListQvery}{%

\par\noindent\textbf{\ltemplateutv}

\vspace{0.4cm}

\\

\ \ltemplatezavkaf <<\lkafedra >> \rule[-1pt]{3cm}{0.4pt} \lzavkaf

\vspace{0.2cm}

\\

\begin{center}

\textbf{Спи­сок во­про­сов по кур­су <<\lpredmet >>}\\

для спе­ци­аль­но­сти \lspez

\end{center}

\setcounter{VoprosNumber}{1}

}{\BiletFooter}

Данное окружение ис­поль­зо­ва­но в ко­ман­де для рас­пе­чат­ки спи­ска во­про­сов.

\def\makelistqvery{%

\begin{ListQvery}

\setcounter{VoprosNumber}{1}

\foreachArray{qvery}{\par\noindent\arabic{VoprosNumber}.%

\addtocounter{VoprosNumber}{1}}

\end{ListQvery}

}

Ис­поль­зу­ет­ся ко­ман­да, рас­пе­ча­ты­ваю­щая все эле­мен­ты мас­си­ва qvery. Пе­ред рас­пе­чат­кой оче­ред­но­го эле­мен­та вы­пол­ня­ет­ся ко­ман­да рас­пе­ча­тать по­ряд­ко­вый но­мер во­про­са и уве­ли­чить его на 1.

\par\noindent\arabic{VoprosNumber}. \addtocounter{VoprosNumber}{1}

Ре­зуль­тат ра­бо­ты ко­ман­ды пред­став­лен на рис. 2. Для ком­по­нов­ки от­дель­но­го тес­та мож­но восполь­зо­вать­ся как вы­ше­при­ве­ден­ны­ми ок­ру­жения­ми, так и ко­ман­дой \printbilet, па­ра­мет­ром ко­то­рой яв­ля­ют­ся но­ме­ра во­про­сов, вклю­чае­мых в тест, раз­де­лен­ные ко­ман­дой \and. Ре­зуль­тат ра­бо­ты ко­ман­ды пред­став­лен на рис. 3.

\long\def\printbilet #1{

\let\and=\printQ %

\begin{EkzBilet}

\printQ #1

\end{EkzBilet}

}

Ко­ман­ды для ком­по­нов­ки тес­тов

Для ком­по­нов­ки бло­ков из 2-х и 4-х тес­тов ис­поль­зу­ет­ся ок­ру­жение tabular. Оп­ре­де­ле­на ко­ман­да \twotestblok для ком­по­нов­ки бло­ка из 2-х тес­тов, ко­то­рая име­ет два па­ра­мет­ра, за­да­вае­мых по ана­ло­гии с па­ра­мет­ром ко­ман­ды \printbilet. Ре­зуль­тат ра­бо­ты ко­ман­ды показан на рис. 4.

\long\def\twotestblok#1#2{

\begin{tabular}{p{0.9\linewidth}}

\hline \\ \printbilet{#1}\\ \hline \\ \printbilet{#2} \\ \hline %

\end{tabular}

}

Оп­ре­де­ле­на ко­ман­да \fiertestblok для ком­по­нов­ки бло­ка из 4-х тес­тов, ко­то­рая име­ет че­ты­ре па­ра­мет­ра, за­да­вае­мых по ана­ло­гии с па­ра­мет­ром ко­ман­ды \printbilet. Ре­зуль­тат ее ра­бо­ты – на рис. 5.

\long\def\fiertestblok#1#2#3#4{

\small

\begin{tabular}{p{0.45\linewidth}|p{0.45\linewidth}}

\hline \\ \printbilet{#1} & \printbilet{#2} \\ \hline \\ %

\printbilet{#3} & \printbilet{#4} \\ \hline

\end{tabular}

}

Все рас­смот­рен­ные вы­ше ко­ман­ды можно свести в от­дель­ный файл testsmakr, под­клю­чае­мый ко­ман­дой \input{testsmakr}. При­мер ра­бо­че­го фай­ла, при ком­пи­ля­ции ко­то­ро­го по­лу­че­ны ре­зуль­та­ты, пред­став­лен­ные на ри­сун­ках, мы предоставляем собрать читателю. (Те, кто хочет убедиться в правильности своего результата, найдут полный текст на стр. 111.)

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

За­клю­чение

Вме­сто мно­же­ст­ва команд для встав­ки ка­ж­до­го фраг­мен­та поль­зо­ва­те­лю доста­точ­но за­помнить лишь пять:

1 Ко­ман­ды– ог­раничи­те­ли на­ча­ла и кон­ца за­по­ми­нае­мо­го фраг­мен­та

2 Ко­ман­ды встав­ки от­дель­но­го фраг­мен­та

3 Ко­ман­ды встав­ки всех фраг­мен­тов или их час­ти

4 Ко­ман­ды встав­ки бло­ков из двух или че­ты­рех би­ле­тов

5 Два но­вых ок­ру­жения, спе­циа­ли­зи­ро­ван­ных для под­го­тов­ки тес­тов: спи­сок во­про­сов и би­лет

Ко­ман­ды и ок­ру­жения, ука­зан­ные в 4-м и 5-м пунк­тах, в от­ли­чие от пунк­тов 1 – 3, спе­циа­ли­зи­ро­ва­ны для под­го­тов­ки тес­то­вых за­даний. Кро­ме то­го, при вы­во­де всех фраг­мен­тов име­ет­ся воз­мож­ность вы­полнения про­из­воль­но­го фор­ма­ти­ро­вания над ка­ж­дым фраг­мен­том.

Пре­иму­ще­ст­вом по­доб­но­го под­хо­да яв­ля­ет­ся воз­мож­ность для ав­то­ра со­сре­до­то­чить­ся на со­дер­жании са­мих во­про­сов, а не на их оформ­лении при ком­по­нов­ке тес­тов. Зна­чи­тель­но уп­ро­ща­ет­ся кор­рек­ти­ров­ка во­про­сов. Пра­вить необ­хо­ди­мо толь­ко в од­ном мес­те без ис­поль­зо­вания по­ис­ка и ав­то­за­ме­ны, как при ис­поль­зо­вании ко­пи­ро­вания – встав­ки из бу­фе­ра об­ме­на в MicrosoftWord.

Ре­зуль­та­том ис­поль­зо­вания рас­смот­рен­ных в ста­тье мак­ро­команд яв­ля­ет­ся по­вы­шение эф­фек­тив­но­сти ра­бо­ты за счет пе­ре­ло­жения на ком­пь­ю­тер ру­тин­ных за­дач. |

Персональные инструменты
купить
подписаться
Яндекс.Метрика