关于宏内部变量名和变量值

关于宏内部变量名和变量值

我有一些问题想解决,因为我正在尝试为我的考试任务建立一个宏。第一个问题是:有没有办法在变量定义中包含数字?假设我正在编写一个包含 10 个问题的测试考试,我想将\T1问题 1 的答案分配给一个变量,\T2将问题 2 的答案分配给另一个变量,等等。显而易见的事情,例如

\def\T1{answer 1}
\def\T2{answer 2}

或类似\newcommand不起作用。有没有在变量定义中使用数字的正确方法?

第二个问题是:我有一个宏,它调用第二个宏,第二个宏在其上定义一个变量。当我尝试从主代码访问最内层宏中定义的变量的值时,系统会报错。那么有没有办法将变量名称和值保存在宏中,以便可以从外部访问它们?

谢谢,抱歉我的 TeX/LaTeX 知识太差 :(

答案1

有几种方法可以采用。这里有一个利用 TeX 的解决方案,\ifcase对于这类事情非常有用:

\documentclass{article}
\usepackage[margin=1in]{geometry}
\newcounter{examquestion}
\newcommand{\question}{\stepcounter{examquestion}\noindent\textbf{Q\theexamquestion.)}\hspace*{1em}}
\newcommand{\answers}[1][\theexamquestion]{%
    \ifcase#1\relax{This would be the answer to question 0: I presume there is no question 0}
                   \or{Answer to question 1}%
                   \or{Answer to question 2}%
                   \or{Answer to question 3}%
                   \or{Answer to question 4}%
                   \fi}%'
%% for purposes of this example only
\usepackage{lipsum}
\pagestyle{empty}
\begin{document}
\question \lipsum[1]
    \par\hspace*{\fill}\textbf{Answer: \answers}
    \vspace{0.25in}

\question \lipsum[2]
    \par\hspace*{\fill}\textbf{Answer: \answers}
    \vspace{0.25in}

\question \lipsum[3]
    \par\hspace*{\fill}\textbf{Answer: \answers}
    \vspace{0.25in}

Summary:
\begin{itemize}
\item  \answers[1]
\item  \answers[2]
\item  \answers[3]
\end{itemize}


\end{document}

如果每个问题都有一个计数器,那么这种方法就很好用。我编写了命令\answers,使其默认使用问题计数器的当前值examquestion。但您可以覆盖它。您可能注意到,当提出答案时,我已经回答了每个问题。也许这不是您想要做的。我允许您覆盖此默认值。我在分项摘要中说明了这一点。

在此处输入图片描述

LaTeX3用更好的用户界面回答:

\documentclass{article}
\usepackage[margin=1in]{geometry}
\usepackage{xparse}
\ExplSyntaxOn
%% expl3::warnings and error messages
\msg_new:nnnn {examanswer}{answer_already_defined}{%
                           You're\ attempting\ to\ define\ an\ answer\ that\ 
                           already\ exists.\\
               \\
                           \ \ \ \ Key\ "#1"\ already\ exists.
                           }{}
\msg_new:nnnn {examanswer}{answer_not_defined}{%
                           You're\ attempting\ to\ call\ an\ answer\ that\ 
                           has\ not\ been\ defined.\\
               \\
                           \ \ \ \ Key\ "#1"\ does\ not\ exist.}{}
%% expl3 code to save and retrieve answers
\prop_new:N \g__answers_to_exam_problems_plist
\cs_new_protected:Npn \__setting_answers_cs:nn #1#2 {
    \prop_if_in:NnTF \g__answers_to_exam_problems_plist {#1}
    {
        \msg_error:nnx{examanswer}{answer_already_defined}{#1}
    }
    {
        \prop_gput:Nnn \g__answers_to_exam_problems_plist {#1} {#2}
    }    
}
\cs_new_protected:Npn \__getting_answers_cs:n #1 {
    \prop_if_in:NnTF \g__answers_to_exam_problems_plist {#1}
    {
        \prop_get:Nn \g__answers_to_exam_problems_plist {#1}
    }
    {
        \msg_error:nnx {examanswer}{answer_not_defined}{#1}
    }
}   
%% user interface to save and retrieve answers
\NewDocumentCommand{\saveanswer}{ m m }{
    \__setting_answers_cs:nn {#1}{#2}
}
\NewDocumentCommand{\getanswer}{ m }{
    \__getting_answers_cs:n {#1}
}
\ExplSyntaxOff
%% a bit of the old version:  here purely for the sake of illustration
\newcounter{examquestion}
\newcommand{\question}{\stepcounter{examquestion}\noindent\textbf{Q\theexamquestion.)}\hspace*{1em}}
%% for purposes of this example only
\usepackage{lipsum}
\pagestyle{empty}
\begin{document}
\question \lipsum[1]
    \saveanswer{q1ans}{This is the answer to question 1}
    \vspace{0.25in}

\question \lipsum[2]
    \saveanswer{q2ans}{Answer to question 2}
    \vspace{0.25in}

\question \lipsum[3]
    \saveanswer{Q:supplementary angles}{$m\angle{ABC}=30$}
    \vspace{0.25in}

Summary:
\begin{itemize}
\item  \getanswer{q1ans}
\item  \getanswer{q2ans}
\item  \getanswer{Q:supplementary angles}
\end{itemize}

\end{document}

我认为这种方法更好。它允许你独立于问题的实际编号来命名特定问题的答案:在这个例子中,我给出了最多的答案名称对应于提问的顺序。但是这段代码没有理由不让你写,

\setanswer{Q:supplementary angles}{$m\angle{ABC}=30$}

然后稍后调用它

\getanswer{Q:supplementary angles}

我更喜欢这种命名约定,因为它更具描述性:并且,如果您稍后重新排列问题,弄清楚神秘的含义\T1\getanswer{q1ans}不会那么麻烦了。

我还添加了一些花哨的东西确保您不会覆盖以前定义的答案,并在调用未定义的答案时发出警告。

在此处输入图片描述

答案2

对于您的第一个问题:您可以定义一个宏 T1,但这对您没有帮助,因为您不能使用反斜杠语法调用它。请参见以下示例:

\documentclass{minimal}

\begin{document}
\expandafter\def\csname T1\endcsname{Test 1}
\expandafter\def\csname T2\endcsname{Test 2}

\csname T1\endcsname

\csname T2\endcsname

\T1
\end{document}

您可以改为定义一个宏\def\T#1{code},并使用 if-then 结构或类似结构来根据参数打印不同的问题。您可以使用\T1, \T2, ... ¸来调用它\T9,但对于更高的值,您需要括号:\T{13}

对于第二个问题,一个最小的(不)工作示例会有所帮助。

相关内容