我如何使用 \expandafter 扩展这个控制序列的定义?

我如何使用 \expandafter 扩展这个控制序列的定义?

我定义了一个命令\test,它不执行任何操作,只是定义了一个控制序列\c[count],其中是执行时[count]计数器的当前文本值。我想输出文本“Number ”,其中应该是执行时的值。count\test\c[count]\thecount\thecountcount

\documentclass[12pt]{article}

\newcounter{count}

\newcommand{\test}{\expandafter\def\csname c\thecount\endcsname{Number \thecount~}}

\begin{document}

\setcounter{count}{1}
\test 
\setcounter{count}{2}
\test
\setcounter{count}{3}
\test

\csname c1\endcsname
\csname c2\endcsname
\csname c3\endcsname

\end{document}

输出结果为:“Number 3 Number 3 Number 3”。我相信这意味着\thecount的输出\test在每个 期间都没有展开\test

我该如何修复此问题,使其按预期显示“数字 1 数字 2 数字 3”?我不确定如何使用\expandafter它,我的尝试总是会破坏一切。我对这种 LaTeX 还比较陌生,因此如果能就此问题提供任何帮助,我将不胜感激。

答案1

让我们看看发生了什么。

  1. 宏的替换文本被吸收无解释或在期间进行宏扩展\def,除了显式括号必须匹配这一事实,这对于确定替换文本的结束位置是必要的。

  2. \csname被扩展时,标记会完全扩展,直到只剩下不可扩展的标记,直到匹配的\endcsname

因此,如果您这样做\def\foo{Number \thecount},替换文本将包含在使用时\thecount将在扩展后扩展的文本\foo。宏名称是什么完全无关紧要。

相反,如果的值为count1,\expandafter\def\csname foo\thecount\endcsname{whatever}将定义名为“ ”的宏(除非使用或改变的类别代码,foo1否则无法访问)。\csname1

请注意,单个扩展步骤\thecount不会产生1,而只是

\@arabic\c@count

因为 LaTeX 默认会这样做\def\thecount{\@arabic\c@count},所以一个步骤\expandafter是不够的:需要三个扩展步骤,因为\@arabic定义为

> \@arabic=macro:
#1->\number #1.

因此需要另一个步骤来获取阿拉伯数字的值。

但是,\@arabic是完全可扩展的,因此您可以使用\edef

\newcommand{\test}{\expandafter\edef\csname c\thecount\endcsname{Number \thecount~}}

因为\edef与 相同,但是替换文本由定义主体中的\def的完整扩展组成。<balanced text>

\newcommand{\test}{%
  \expandafter\def\csname c\thecount\expandafter\endcsname\expandafter{%
    \expanded{Number \thecount~}%
  }%
}

会起作用,因为后面\expandafter\csname \expandafter展开,触发之前的展开{,这会触发 的展开\expanded。当然\edef要简单得多,但\expanded在其他情况下也很有用。

小心使用\edef\expanded,因为“危险”的标记可能需要\noexpand

相关内容