虽然我已经使用 LaTeX 多年,但这是我第一次无法找到 LaTeX 问题的答案,所以这是我第一次发布的问题。
我正在定义一个命令 ( \QPreparation
),它将重新定义命令\QInput
。该命令\QInput{N}
应根据我发送的数字 N 将代码输入到我的文档中。每次调用该\QPreparation
命令时,我希望查找的基本路径\QInput
以及将\QInput
考虑的案例总数都会发生变化。输入文件命名为“C0.tex”、“C1.tex”、“C2.tex”...,以便在重新定义时\QInput
,新文件选项易于更新。
在我一直在研究的代码中(如下),两个输入是\QPreparation
(a)要更新的基本路径和(b)我想要考虑\QInput
的案例数量。\QInput
因为我的下一步是修改\QPreparation
命令,以便调用\QInput{0}
、、\QInput{1}
...\QInput{N}
以随机顺序加载所有 N 个文件,所以我不要相信以如下的方式进行\QPreparation
定义是可行的。\QInput
\input{#1/C##1.tex}
如果你好奇我计划如何进行随机化,请考虑 随机化 .tex 文件中文本行的顺序。
在我看来,解决这个问题最简单的方法是用\QInput
循环\ifcase
生成的定义。示例代码(如下)显示了我对此的尝试,但\or
循环中的附加内容会引发错误,例如:
! Extra \or. \iterate ->\ifnum \the \QIternum <4\relax \or \input {./Q1/C\the \QIternum ....
我的示例代码:
\newcommand{\QPreparation}[2]{%
\expandafter\renewcommand\csname QInput\endcsname[1]{%
\ifcase##1
\input{#1/C0.tex}
\QIternum=1
\loop\ifnum\the\QIternum<#2\relax
\or
\input{#1/C\the\QIternum.tex}
\advance\QIternum by 1
\repeat
\fi
}
}
任何帮助将不胜感激。
谢谢!
答案1
当替换文本被吸收时,替换文本不会被执行。
您可以以间接的方式构建宏:
\documentclass{article}
\newcommand{\QInput}{} % initialization
\makeatletter
\newcount\QIteration
\newcommand{\QPreparation}[2]{%
\QIteration=\z@
\gdef\tempa{\ifcase####1\relax\input{#1/C0.tex}}%
\loop\ifnum\QIteration<#2
\advance\QIteration\@ne
\edef\tempb{%
\expandafter\noexpand\csname or\endcsname
\noexpand\input{#1/C\the\QIteration.tex}%
}%
\expandafter\g@addto@macro\expandafter\tempa\expandafter{\tempb}%
\repeat
\g@addto@macro\tempa{\fi}
\def\tempb{\renewcommand\QInput[1]}%
\expandafter\tempb\expandafter{\tempa}
}
\makeatother
\QPreparation{foo}{5}
\show\QInput
该\show
命令将输出
> \QInput=\long macro:
#1->\ifcase #1\relax \input {foo/C0.tex}\or \input {foo/C1.tex}\or \input {foo/
C2.tex}\or \input {foo/C3.tex}\or \input {foo/C4.tex}\or \input {foo/C5.tex}\fi
.
这似乎就是你想要的。
有必要隐藏\or
在循环中,因为否则我们会得到一个“放错位置的\or
”错误。
没有全局定义的替代方案:
\documentclass{article}
\newcommand{\QInput}{} % initialization
\makeatletter
\newcount\QIteration
\toks@={}
\newcommand{\QPreparation}[2]{%
\QIteration=\z@
\toks@={\ifcase##1\relax\input{#1/C0.tex}}%
\loop\ifnum\QIteration<#2
\advance\QIteration\@ne
\edef\temp{%
\expandafter\noexpand\csname or\endcsname
\noexpand\input{#1/C\the\QIteration.tex}%
}%
\toks@=\expandafter{\the\expandafter\toks@\temp}%
\repeat
\toks@=\expandafter{\the\toks@\fi}%
\begingroup\edef\x{\endgroup
\noexpand\renewcommand\noexpand\QInput[1]{\the\toks@}%
}\x
}
\makeatother
\QPreparation{foo}{5}
\show\QInput
xparse
如果使用,则等效解决方案:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l_strickland_temp_tl
\NewDocumentCommand{\QPreparation}{mm}
{
\tl_clear:N \l_strickland_temp_tl
\int_step_inline:nnnn { 0 } { 1 } { #2 }
{
\tl_put_right:Nn \l_strickland_temp_tl { {##1}{\input{#1/C##1.tex}} }
}
\use:x
{
\exp_not:N \DeclareDocumentCommand \exp_not:N \QInput { m }
{
\exp_not:N \int_case:nn { ####1 } { \exp_not:V \l_strickland_temp_tl }
}
}
}
\ExplSyntaxOff
答案2
构建 ifcase 的另一种方法
\documentclass{article}
\def\QInput{}
\def\afterfi#1\fi{\fi#1}
\def\QPreparation#1#2{\bgroup
\let\or\relax\let\input\relax
\XQPreparation{#1}{#2}%
\edef\x{\egroup\def\noexpand\QInput####1{%
\noexpand\ifcase####1\relax\input{#1/C0.tex}\QInput\noexpand\fi}}%
\x
}
\def\XQPreparation#1#2{%
\ifnum#2>0 \afterfi
\edef\QInput{\or\input{#1/C#2.tex}\QInput}%
\XQPreparation{#1}{\the\numexpr#2-1\relax}%
\fi}
\begin{document}
\QPreparation{foo}{5}
\show\QInput
\end{document}
生产
> \QInput=macro:
#1->\ifcase #1\relax \input {foo/C0.tex}\or \input {foo/C1.tex}\or \input {foo/
C2.tex}\or \input {foo/C3.tex}\or \input {foo/C4.tex}\or \input {foo/C5.tex}\fi
.
l.23 \show\QInput