如何将变量定义设置为全局变量以在 eachfor 循环之外使用它?
\newcommand\Var[3]{
\expandafter\edef\csname #1\Roman{#2}\endcsname{#3}
}
\newcounter{count}
\foreach \i in {1,2,3,4,5,6,7,8,9}{
\stepcounter{count}
\Var{var}{count}{\Alph{count}}
}
\varII ???
答案1
欢迎!您的问题的答案是:使用\xdef
而不是\edef
,即
\documentclass{article}
\usepackage{pgffor}
\newcounter{count}
\newcommand\Var[3]{
\expandafter\xdef\csname #1\Roman{#2}\endcsname{#3}
}
\foreach \i in {1,2,3,4,5,6,7,8,9}{
\stepcounter{count}
\Var{var}{count}{\Alph{count}}
}
\begin{document}
\varIII
\end{document}
但是,您不需要将变量设为全局变量。相反,您可以使用内置函数\loop
来实现这一点。
\documentclass{article}
\newcommand\Var[3]{
\expandafter\edef\csname #1\Roman{#2}\endcsname{#3}
}
\newcounter{count}
\setcounter{count}{0}
\loop
\stepcounter{count}
\Var{var}{count}{\Alph{count}}%
\ifnum\value{count}<10
\repeat
\begin{document}
\varIII
\end{document}
答案2
您可以使用 来实现xparse
;我假设您的值不是连续的整数。我添加了一个可选数字来更改列表分隔符,以防您需要在值中使用逗号。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\setvariables}{mO{,}m}
{% #1 = prefix for the variable name
% #2 = separator (optional, default comma)
% #3 list of values
\hadi_setvariables:nnn { #1 } { #2 } { #3 }
}
\cs_new_protected:Nn \hadi_setvariables:nnn
{
\seq_set_split:Nnn \l_tmpa_seq { #2 } { #3 }
\seq_indexed_map_inline:Nn \l_tmpa_seq
{% ##1 is the current index, ##2 is the current item
\tl_set:cn { #1 \int_to_Roman:n { ##1 } } { ##2 }
}
}
\ExplSyntaxOff
\begin{document}
\setvariables{var}{1,2,3,9,5.2}
\varI \quad \varII \quad \varIII \quad \varIV \quad \varV
\setvariables{xyz}[;]{1;0.1;a,b}
\xyzI \quad \xyzII \quad \xyzIII
\end{document}
答案3
使用 pgffor/TikZ 时,\foreach
每次迭代都在其自己的本地范围内进行。迭代中发生的非全局赋值(例如,就 而言\edef
)仅限于该迭代的本地范围。
请注意,当使用 LaTeX 2ε 内核\@for
而不是 pgffor/TikZ 内核时\foreach
,迭代不会在新的局部范围内进行。因此,使用 LaTeX 2ε 内核时,\@for
您不需要\xdef
但可以使用\edef
— 可以是这样的:
\documentclass{article}
\makeatletter
\newcounter{count}
\newcommand\Var[3]{%
\expandafter\edef\csname #1\Roman{#2}\endcsname{#3}%
}%
\setcounter{count}{0}%
\@for\i:=0001,0010,0011,0100,0101,0110,0111,1000,1001\do{%
\stepcounter{count}%
\Var{var}{count}{Alphabetic: \Alph{count}--Binary: \i}%
}%
\makeatother
\begin{document}
\noindent
\verb|\varI|: \varI \\
\verb|\varII|: \varII \\
\verb|\varIII|: \varIII \\
\verb|\varIV|: \varIV \\
\verb|\varV|: \varV \\
\verb|\varVI|: \varVI \\
\verb|\varVII|: \varVII \\
\verb|\varVIII|: \varVIII \\
\verb|\varIX|: \varIX \\
\end{document}
您使用和。\Roman{⟨LaTeX counter⟩}
\Alph{⟨LaTeX counter⟩}
如果您改用和,则可以不用计数寄存器。\@Roman{⟨TeX number quantity⟩}
\@Alph{⟨TeX number quantity⟩}
如果没有可用的 ε-TeX 扩展,您可能需要实现一个可扩展增量例程:
\documentclass{article}
\makeatletter
%------------------------------------------------------------------------------
% Expandable incrementing of natural number formed by a sequence of
% explicit catcode-12-character-tokens-from-the-set {0,1,2,3,4,5,6,7,8,9}
%..............................................................................
% \Increment{<natural number k as sequence of explicit catcode-12-character-
% tokens from the set 0123456789>}
% ->
% <natural number (k+1) as sequence of explicit catcode-12-character-tokens
% from the set 0123456789>
% In expansion-contexts the result is delivered after two expansion-steps/is
% obtained by "hitting" \Increment with \expandafter twice.
%------------------------------------------------------------------------------
\newcommand\Increment[1]{%
\romannumeral0%
\UD@IncrementReverse{\UD@IncrementFork{}}{\relax}{}#1\relax
}%
\newcommand\UD@IncrementReverse[4]{%
\ifx\relax#4%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{#1#3#2}{\UD@IncrementReverse{#1}{#2}{#4#3}}%
}%
\@ifdefinable\UD@IncrementSelect{%
\long\def\UD@IncrementSelect#10123456789\relax#2#3!!{#2}%
}%
\newcommand\UD@IncrementFork[2]{%
\UD@IncrementSelect
#2123456789\relax{\UD@IncrementReverse{ }{}{}#11}%
0#223456789\relax{\UD@IncrementReverse{ }{}{}#12}%
01#23456789\relax{\UD@IncrementReverse{ }{}{}#13}%
012#2456789\relax{\UD@IncrementReverse{ }{}{}#14}%
0123#256789\relax{\UD@IncrementReverse{ }{}{}#15}%
01234#26789\relax{\UD@IncrementReverse{ }{}{}#16}%
012345#2789\relax{\UD@IncrementReverse{ }{}{}#17}%
0123456#289\relax{\UD@IncrementReverse{ }{}{}#18}%
01234567#29\relax{\UD@IncrementReverse{ }{}{}#19}%
012345678#2\relax{\UD@IncrementFork{#10}}%
0123456789#2{\UD@IncrementReverse{ }{}{}#11\relax}%
0123456789\relax{\UD@IncrementReverse{ }{}{}#11#2}%
!!%
}%
%------------------------------------------------------------------------------
\newcommand\VarLoop[4]{%
\ifnum#2<\expandafter\@firstofone\expandafter{\number#1} %
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi{%
\expandafter\edef\csname#3\@Roman{#1}\endcsname{#4{#1}}%
%\expandafter\show\csname#3\@Roman{#1}\endcsname%
\expandafter\expandafter\expandafter\VarLoop
\expandafter\expandafter\expandafter{\Increment{#1}}{#2}{#3}{#4}%
}%
}%
%------------------------------------------------------------------------------
\VarLoop{1}{9}{var}{\@Alph}
%------------------------------------------------------------------------------
\makeatother
\begin{document}
\noindent
\verb|\varI|: \varI \\
\verb|\varII|: \varII \\
\verb|\varIII|: \varIII \\
\verb|\varIV|: \varIV \\
\verb|\varV|: \varV \\
\verb|\varVI|: \varVI \\
\verb|\varVII|: \varVII \\
\verb|\varVIII|: \varVIII \\
\verb|\varIX|: \varIX \\
\end{document}
如果有 ε-TeX 扩展可用,您可以使用\number\numexpr...\relax
可扩展增量:
\documentclass{article}
\makeatletter
%------------------------------------------------------------------------------
\newcommand\VarLoop[4]{%
\ifnum#2<\expandafter\@firstofone\expandafter{\number#1} %
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi{%
\expandafter\edef\csname#3\@Roman{#1}\endcsname{#4{#1}}%
%\expandafter\show\csname#3\@Roman{#1}\endcsname%
\expandafter\VarLoop
\expandafter{\number\numexpr\number#1+1\relax}{#2}{#3}{#4}%
}%
}%
%------------------------------------------------------------------------------
\VarLoop{1}{9}{var}{\@Alph}
%------------------------------------------------------------------------------
\makeatother
\begin{document}
\noindent
\verb|\varI|: \varI \\
\verb|\varII|: \varII \\
\verb|\varIII|: \varIII \\
\verb|\varIV|: \varIV \\
\verb|\varV|: \varV \\
\verb|\varVI|: \varVI \\
\verb|\varVII|: \varVII \\
\verb|\varVIII|: \varVIII \\
\verb|\varIX|: \varIX \\
\end{document}
顺便一提:
似乎您使用它\Roman
来将数字转换为类别代码 11(字母)的字符标记,这些字符标记可以出现在控制字标记的名称中,如\varI
、\varII
等。
您是否知道\csname..\endcsname
可以通过 (La)TeX 构造名称包含数字的标记?
例如,
\csname varI\endcsname
产生控制字标记\varI
。
同样地
\csname var1\endcsname
产生控制字标记\var1
。
您不能\var1
直接在 .tex 输入文件中输入,因为 (La)TeX 的读取和标记设备会将其标记成 和。\varcontrol word token
1explicit character token of category code 12(other)
但\csname var1\endcsname
读取和标记如下:
\csnamecontrol word token
vexplicit character token of category code 11(letter)
aexplicit character token of category code 11(letter)
rexplicit character token of category code 11(letter)
1explicit character token of category code 12(other)
\endcsnamecontrol word token
在下一个阶段,在扩展事物的时候,组成 -表达式 的标记\csname..\endcsname
会被扩展,扩展的结果\csname...
就是标记。\var1control word token
(La)TeX 中有一个很好的特殊功能,称为#{
-notation,它允许您定义最后一个参数以 分隔的宏{
。
您可以定义一个命令
\name⟨stuff without braces⟩{⟨ControlSequenceName⟩}
经过两个扩展步骤后,结果如下:
⟨stuff without braces⟩\ControlSequenceName
你可以像这样使用它:
\name{Var23}
→ \Var23
\name\newcommand{Var23}...
→ \newcommand\Var23...
\name\global\long\def{Var23}...
→ \global\long\def\Var23...
\name\show{Var23}
→ \show\Var23
\name\meaning{Var23}
→ \meaning\Var23
\name\name\let{Var23}={Var24}
→ \name\let\Var23={Var24}
→\let\Var23=\Var24
\documentclass{article}
\newcounter{scratchcounter}
% Let's define the \name-macro:
\makeatletter
\newcommand\exchange[2]{#2#1}%
\@ifdefinable\name{\long\def\name#1#{\romannumeral0\innername{#1}}}%
\newcommand\innername[2]{\expandafter\exchange\expandafter{\csname#2\endcsname}{ #1}}%
\makeatother
% Let's define "variables/macros" \var1..\var9 in a loop:
\setcounter{scratchcounter}{0}%
\loop
\stepcounter{scratchcounter}%
\name\name{@ifdefinable}{var\number\value{scratchcounter}}{%
\name\edef{var\number\value{scratchcounter}}{\Alph{scratchcounter}}%
}%
\ifnum\value{scratchcounter}<9
\repeat
% Let's define the macro \foo45/c-;/bar
\name\newcommand*{foo45/c-;/bar}{This is a macro with a weird name.}
\parindent=0ex
\begin{document}
\verb|\name{var1}|: $\to$ \texttt{\name\string{var1}} $\to$ \name{var1} \\
\verb|\name{var2}|: $\to$ \texttt{\name\string{var2}} $\to$ \name{var2} \\
\verb|\name{var3}|: $\to$ \texttt{\name\string{var3}} $\to$ \name{var3} \\
\verb|\name{var4}|: $\to$ \texttt{\name\string{var4}} $\to$ \name{var4} \\
\verb|\name{var5}|: $\to$ \texttt{\name\string{var5}} $\to$ \name{var5} \\
\verb|\name{var6}|: $\to$ \texttt{\name\string{var6}} $\to$ \name{var6} \\
\verb|\name{var7}|: $\to$ \texttt{\name\string{var7}} $\to$ \name{var7} \\
\verb|\name{var8}|: $\to$ \texttt{\name\string{var8}} $\to$ \name{var8} \\
\verb|\name{var9}|: $\to$ \texttt{\name\string{var9}} $\to$ \name{var9} \\
\verb|\name{foo45/c-;/bar}|: $\to$ \texttt{\name\string{foo45/c-;/bar}} $\to$ \name{foo45/c-;/bar}
\hrulefill\null
Now let's redefine \verb|\var8|:
\verb|\name\renewcommand{var8}[1]{Now we have a macro which processes an argument: #1}|\\
$\to$\\
\verb|\renewcommand\var8[1]{Now we have a macro which processes an argument: #1}|\\
\name\renewcommand{var8}[1]{Now we have a macro which processes an argument: #1}
\verb|\name\string{var8}: \name\meaning{var8}| yields:
\begingroup
\ttfamily\frenchspacing
\hbox{%
\name\string{var8}: \name\meaning{var8}%
}%
\endgroup
\end{document}