如何迭代构建 \ifcase

如何迭代构建 \ifcase

虽然我已经使用 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

相关内容