我定义了一个命令\test
,它不执行任何操作,只是定义了一个控制序列\c[count]
,其中是执行时[count]
计数器的当前文本值。我想输出文本“Number ”,其中应该是执行时的值。count
\test
\c[count]
\thecount
\thecount
count
\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
让我们看看发生了什么。
宏的替换文本被吸收无解释或在期间进行宏扩展
\def
,除了显式括号必须匹配这一事实,这对于确定替换文本的结束位置是必要的。当
\csname
被扩展时,标记会完全扩展,直到只剩下不可扩展的标记,直到匹配的\endcsname
。
因此,如果您这样做\def\foo{Number \thecount}
,替换文本将包含在使用时\thecount
将在扩展后扩展的文本\foo
。宏名称是什么完全无关紧要。
相反,如果的值为count
1,\expandafter\def\csname foo\thecount\endcsname{whatever}
将定义名为“ ”的宏(除非使用或改变的类别代码,foo1
否则无法访问)。\csname
1
请注意,单个扩展步骤\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
。