我以前曾使用 TikZ 做过练习和解决方案表,所以我不确定为什么会失败。
这只是一组极其简单的 2+2=?练习及其解决方案。
我希望它能将问题隔离开来我之前的帖子。
\Solution
我在“打破这一点”的定义中写了什么?
\documentclass{article}
\usepackage{tikz}
\newcommand{\GenerateExerciseAndSolution}
{\newcommand{\Exercise}
{\begin{tikzpicture}
\node at (0,0) {$2+2=?$};
\end{tikzpicture}
}
\newcommand{\Solution}
{\begin{tikzpicture}
\node at (0,0) {$2+2=4$};
\end{tikzpicture}
}
}
\setlength{\parindent}{0cm}
\begin{document}
\section*{Exercises}
\newcommand{\SolutionSet}{}
\foreach \x in {1,...,5}
{\GenerateExerciseAndSolution (\x) \Exercise \par
\xdef\SolutionSet{\SolutionSet (\x) \Solution \par} % This compiles if I delete "\Solution" from this line.
}
\section*{Solutions}
\SolutionSet
\end{document}
答案1
错误的原因在于\xdef
尝试完全扩展给定的内容,但 LaTeX 中并非所有内容都是可扩展的。特别是,像tikzpicture
环境这样的“复杂”对象不太可能扩展。您似乎假设\xdef
只会将“当前值”插入其中\Solution
,\SolutionSet
但实际上 LaTeX 尝试添加大量代码,\SolutionSet
而这根本行不通。
正如您在评论中所说,“‘不要使用 xdef’ 不是一个解决方案”,但我认为没有简单的方法可以解决您正在做的事情,因为底层方法存在缺陷(抱歉!)。使用蒂克兹排版问题及其解决方案的列表当然是新颖的,但这并没有发挥 的优势tikz
,因为 主要用于绘制图形。enumerate
环境之类的东西可能更适合显示练习。
我怀疑您之所以使用是\tikz
因为您想利用它\foreach
,但对于您想做的事情,存在一大堆扩展障碍需要您解决,而我认为您不想去那里。
相反,我建议你看看\docsvlist
查看电子工具箱包。这可用于处理逗号分隔变量的“列表”。您似乎正在处理的练习集类型很容易写成逗号分隔列表:
1+1 = 2,
1+2 = 3,
1+3 = 4,
2+2 = 4
这也适用于更复杂的练习,但您应该避免使用逗号并且只使用一个等号 - 或更改语法!
给定其中一个“练习”,我们需要将练习和解决方案分开。现代 LaTeX 的方法是使用\SplitArgument
使用解析包,但我们只使用普通的 TeX hack 来代替:
\def\printExercise#1=#2!!!{\item $#1=\space?$}
因此,\printExercise 1+1 = 2!!!
将设置为#1
等于1+1
并将结果添加到输入流中。该命令将命令应用于给定的列表的每个元素,因此我们只需要让给出练习到。我们还需要一个相应的宏。希望这足以解释为什么以下代码#2
2
\item $1+1=\space?$
\docsvlist
\do
\do
\printExercise
\printSolution
\documentclass{article}
\usepackage{etoolbox}
\usepackage{enumitem}
\def\printExercise#1=#2!!!{\item $#1=\space?$}
\def\printSolution#1=#2!!!{\item $#1=#2$}
\newcommand\PrintExercises[1]{%
\section*{Exercises}
\renewcommand*\do[1]{\printExercise##1!!!}
\begin{enumerate}[label=(\arabic*)]
\docsvlist{#1}
\end{enumerate}
\section*{Solutions}
\renewcommand*\do[1]{\printSolution##1!!!}
\begin{enumerate}[label=(\arabic*)]
\docsvlist{#1}
\end{enumerate}
}
\begin{document}
\PrintExercises{% comma separated list of exercise: solution pairs
1+1 = 2,
1+2 = 3,
1+3 = 4,
2+2 = 4
}
\end{document}
产生类似于您正在寻找的输出(我认为):
事实上,由于\printSolution
正在打印“完整的练习解决方案方程”,并且不对#1
或进行任何操作#2
,我们可以用 替换\renewcommand*\do[1]{\printSolution##1!!!}
上面的内容\renewcommand*\do[1]{\item $##1$}
。我们只需要一个\printSolution
宏来对解决方案进行“更复杂”的处理——例如,如果我们只想打印解决方案而不是完整的方程。
这里的主要技巧是将数据(即练习和解决方案)与我们需要显示它的周围 LaTeX 代码分开。我认为将数据的相关部分(在本例中为练习及其解决方案)尽可能地放在一起始终是一个好主意。