语境
我正在尝试使用美国管理公司制作一份包含代码的考试。
然而,使用问题中的逐字代码超出了包的范围。他们建议声明框并在每个问题中使用它们。但是,我发现为\newbox
每个问题创建一个框并手动插入是有问题的。
因此,我寻找了如何自动创建和插入框的解决方案(以下这个问题和这个答案)。
问题
但是现在,我被宏的扩展问题困扰了。因为我使用的宏总是插入最后创建的框。AMC 软件包似乎处理了宏中的所有元素(问题)\onecopy
,然后扩展了我的宏\insertbox
。但是,我需要在每个元素中插入宏的扩展版本,以便插入我创建的框的扩展名称。
因此,我如何扩展框的定义并将其插入到每个问题中?
我尝试将\savebox
定义存储在另一个宏中,然后在使用后插入,\edef
但这也不起作用。
我希望\insertbox
以这样一种方式重新定义,即使用我创建的时间框的名称进行扩展,而不是一直扩展直到调用\onecopy
。
代码
\documentclass{article}
\usepackage[box]{automultiplechoice}
\usepackage{listings}
% a simple wrapper to create boxes automatically
\makeatletter
\newcounter{myboxcounter}
\newenvironment{mybox}{%
\addtocounter{myboxcounter}{1}%
\expandafter\newsavebox\csname foobox\roman{myboxcounter}\endcsname
\global\expandafter\setbox\csname foobox\roman{myboxcounter}\endcsname\hbox\bgroup\color@setgroup\ignorespaces
}{%
\color@endgroup\egroup
}
% first try
% \newcommand{\insertbox}{\expandafter\usebox\csname\name\endcsname}
% second one
\newcommand{\insertbox}{\edef\name{foobox\roman{myboxcounter}}\edef\x{\expandafter\usebox\csname\name\endcsname}\x}
\makeatother
\begin{document}
%%% preparation of the groups
\begin{mybox}
\begin{lstlisting}[language=C++]
int a = 10;
a = a + 10;
\end{lstlisting}
\end{mybox}
\element{code}{
\begin{question}{code 1}
Which is the result of \texttt{a}?
\insertbox
\begin{choices}
\correctchoice{10}
\wrongchoice{20}
\wrongchoice{0}
\wrongchoice{30}
\end{choices}
\end{question}
}
\begin{mybox}
\begin{lstlisting}[language=C++]
int a = 10;
a = a++;
\end{lstlisting}
\end{mybox}
\element{code}{
\begin{question}{code 2}
Which is the result of \texttt{a}?
\insertbox
\begin{choices}
\correctchoice{10}
\wrongchoice{11}
\wrongchoice{12}
\wrongchoice{0}
\end{choices}
\end{question}
}
%%% copies
\onecopy{1}{
\insertgroup{code}
}
\end{document}
如下图所示,插入的两个代码都属于最后创建的框。因为宏似乎是在稍后展开的,而不是在宏中调用时展开的\element
。
答案1
在这里,我在最终之前将计数器重置为 0 \onecopy
,并重新定义\insertbox
为使用其输出来步进计数器。
\documentclass{article}
\usepackage[box]{automultiplechoice}
\usepackage{listings}
% a simple wrapper to create boxes automatically
\makeatletter
\newcounter{myboxcounter}
\newenvironment{mybox}{%
\stepcounter{myboxcounter}%
\expandafter\newsavebox\csname foobox\roman{myboxcounter}\endcsname
\global\expandafter\setbox\csname foobox\roman{myboxcounter}\endcsname\hbox\bgroup\color@setgroup\ignorespaces
}{%
\color@endgroup\egroup
}
% first try
% \newcommand{\insertbox}{\expandafter\usebox\csname\name\endcsname}
% second one
\newcommand{\insertbox}{\stepcounter{myboxcounter}%
\edef\name{foobox\roman{myboxcounter}}\edef\x{%
\expandafter\usebox\csname\name\endcsname}\x}
\makeatother
\begin{document}
%%% preparation of the groups
\begin{mybox}
\begin{lstlisting}[language=C++]
int a = 10;
a = a + 10;
\end{lstlisting}
\end{mybox}
\element{code}{
\begin{question}{code 1}
Which is the result of \texttt{a}?
\insertbox
\begin{choices}
\correctchoice{10}
\wrongchoice{20}
\wrongchoice{0}
\wrongchoice{30}
\end{choices}
\end{question}
}
\begin{mybox}
\begin{lstlisting}[language=C++]
int a = 10;
a = a++;
\end{lstlisting}
\end{mybox}
\element{code}{
\begin{question}{code 2}
Which is the result of \texttt{a}?
\insertbox
\begin{choices}
\correctchoice{10}
\wrongchoice{11}
\wrongchoice{12}
\wrongchoice{0}
\end{choices}
\end{question}
}
%%% copies
\setcounter{myboxcounter}{0}
\onecopy{1}{
\insertgroup{code}
}
\end{document}
答案2
恐怕您必须给这些框命名,以便可以按正确的顺序检索它们。您可以使用问题 ID 作为框的名称:
\documentclass{article}
\usepackage[box]{automultiplechoice}
\usepackage{listings}
% a simple wrapper to create boxes automatically
\makeatletter
\newenvironment{mybox}[1]{%
\expandafter\newsavebox\csname foobox#1\endcsname
\global\expandafter\setbox\csname foobox#1\endcsname\hbox\bgroup\color@setgroup\ignorespaces
}{%
\color@endgroup\egroup
}
\newcommand{\insertbox}{\edef\name{foobox\AMCid@name}\edef\x{\expandafter\usebox\csname\name\endcsname}\x}
\makeatother
\begin{document}
%%% preparation of the groups
\begin{mybox}{code 1}
\begin{lstlisting}[language=C++]
int a = 10;
a = a + 10;
\end{lstlisting}
\end{mybox}
\element{code}{
\begin{question}{code 1}
Which is the result of \texttt{a}?
\insertbox
\begin{choices}
\correctchoice{10}
\wrongchoice{20}
\wrongchoice{0}
\wrongchoice{30}
\end{choices}
\end{question}
}
\begin{mybox}{code 2}
\begin{lstlisting}[language=C++]
int a = 10;
a = a++;
\end{lstlisting}
\end{mybox}
\element{code}{
\begin{question}{code 2}
Which is the result of \texttt{a}?
\insertbox
\begin{choices}
\correctchoice{10}
\wrongchoice{11}
\wrongchoice{12}
\wrongchoice{0}
\end{choices}
\end{question}
}
%%% copies
\onecopy{5}{
\shufflegroup{code}
\insertgroup{code}
}
\end{document}
然而,有了这个答案,
- 你不能用多个方框来回答同一个问题
- 如果你更改了问题 ID,你必须记住在源代码中的两个不同位置进行更改