定义一个命令(可能递归)以在命令中将文本换行 n 次

定义一个命令(可能递归)以在命令中将文本换行 n 次

我正在尝试\multiboxed在 LaTeX 中定义一个新命令,以便我可以输入n围绕方程式添加框,而无需手动嵌套\boxed命令。到目前为止,我已经(使用pgffor包):

def\multiboxed#1#2{
  \foreach \index in {1, ..., #1} {
      Hello
  }
  #1
  \foreach \index in {1, ..., #1} {
    World
  }
}

成功用 和 包装第二个参数HelloWorld次数与第一个参数相同。但是,将其更改为

def\multiboxed#1#2{
  \foreach \index in {1, ..., #1} {
      \fbox{
  }
  #1
  \foreach \index in {1, ..., #1} {
    }
  }
}

确实不起作用,正如预期的那样。因此,我有两个问题,我只需要回答其中一个:

  1. 如何成功修改 for 循环以实现所需的行为?
  2. 或者,我如何定义递归命令来实现相同的输出?

显然,对 (2) 的回答会更好,因为这是解决问题的更好方法,但我觉得我最好理解对 (1) 的回答。理想情况下,我也不必依赖该pgffor软件包。感谢您对此事的任何见解。

答案1

到目前为止的答案都没有问题,但它们都使用了重量级的大型包,而这个版本根本不使用任何包,并且需要的代码更少。

在此处输入图片描述

\documentclass{article}

\def\Fbox#1#2{\ifnum#1=0\mbox{#2}\else\fbox{\Fbox{\numexpr#1-1\relax}{#2}}\fi}


\begin{document}

\Fbox{0}{hello}
\Fbox{1}{hello}
\Fbox{2}{hello} 
\Fbox{3}{hello} 
\Fbox{4}{hello} 
\Fbox{5}{hello} 

\end{document}

另一种变体使用\@first/@secondoftwo

\makeatletter
\def\Fbox#1#2{%
  \ifnum#1=0\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\mbox{#2}}{\fbox{\Fbox{\numexpr#1-1\relax}{#2}}}%
}
\makeatother

答案2

令牌寄存器可以收集嵌套的\fbox命令。\global是必要的,因为的主体\foreach是成组执行的。

\documentclass{article}
\usepackage{pgffor}

\newtoks\ToksMultiBoxed
\newcommand*{\multiboxed}[2]{%
  \global\ToksMultiBoxed{#2}%
  \ifnum#1>0 %
    \foreach \index in {1,...,#1} {%
      \global\ToksMultiBoxed\expandafter{%
        \expandafter\fbox\expandafter{\the\ToksMultiBoxed}%
      }%
    }%
  \fi
  \the\ToksMultiBoxed
}

\begin{document}

\multiboxed{4}{Hello}
\multiboxed{1}{World}
\multiboxed{0}{!}

\end{document}

结果

\documentclass{article}
\usepackage{loops}[2012/10/16]
\makeatletter
\newcommand*{\multiboxed}[2]{%
  \skvifnumTF#1=\z@{%
    #2%
  }{%
    \@temptokena{#2}%
    \foreachfox {1,...,#1} {%
      \skvexpanded{\@temptokena{\noexpand\fbox{\the\@temptokena}}}%
    }%
    \the\@temptokena
  }%
}
\makeatother  
\begin{document}
\multiboxed{4}{Hello}
\multiboxed{1}{World}
\multiboxed{0}{!}
\end{document}

答案3

正如 David Carlisle 所说,其他答案并没有错。也就是说,只要你满足于清楚的盒子。但是说到画盒子,没有什么比这个tikz方法更好了:

在此处输入图片描述

通过在两个框中使用白线来实现额外的间距。

代码:

\documentclass{article}
\usepackage{tikz}
\usepackage{xstring}

\tikzset{Dotted Red/.style={draw=red, dotted, line width=1pt}}
\tikzset{Dashed Violet/.style={draw=violet, dashed}}

\newcommand{\Boxed}[3][]{
\begin{tikzpicture}[baseline, inner sep=0, outer sep=0]
    \node [thick] (Origin) {#3};
    \foreach \x in {1,...,#2} {%
        \pgfmathsetmacro{\Shift}{0.1*(\x+1)}%
        \StrBetween[\x,\numexpr\x+1\relax]{,#1,}{,}{,}[\LineStyle]
        \draw [thick, draw=black, \LineStyle] 
            ([shift={(-\Shift cm,-\Shift cm)}]Origin.south west) rectangle 
            ([shift={( \Shift cm, \Shift cm)}]Origin.north east) ;
    }%
\end{tikzpicture}
}



\begin{document}
    \Boxed{3}{Hello}
    \hspace{1cm}
    \Boxed[blue,black,green,violet,red]{5}{Hello World}

    \bigskip
    \hspace{1.0cm}\Boxed[blue,black,white,white,Dashed Violet,Dotted Red]{6}{How you doin?}
\end{document}

答案4

xparse以下是使用和的实现expl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\multibox}{mm}
 {
  \multibox_do:nn { #1 } { #2 }
 }

\tl_new:N \l_multibox_tokens_tl
\cs_new_protected:Npn \multibox_do:nn #1 #2
 {
  \tl_set:Nn \l_multibox_tokens_tl { #2 }
  \prg_replicate:nn { #1 }
   {
    \tl_set:Nx \l_multibox_tokens_tl { \exp_not:N \fbox{ \exp_not:V \l_multibox_tokens_tl } }
   }
  \tl_use:N \l_multibox_tokens_tl
 }
\ExplSyntaxOff

\begin{document}
\multibox{5}{Hello}
\multibox{2}{world}
\end{document}

它表现出一个有趣的特点:在复制的每一步中,先前的内容\l_multibox_tokens_tl仅扩展一次,即使在“完全扩展”的上下文中也是如此。

在此处输入图片描述

让我们看看它是如何工作的。正如样式指南所建议的那样,用户级命令\multibox被转换为函数,因此第一个定义并不神秘。

接下来,我们保留一个标记列表变量,该变量将设置为我们要装箱的文本。完成此分配后,我们启动一个简单的循环,其中使用 重复一些代码\prg_replicate:nn{...}{...}。第一个参数是重复次数,第二个参数是代码。

这是重要的部分:每次都会重置令牌列表变量:

\tl_set:Nx \l_multibox_tokens_tl { <tokens> }

完全展开<tokens>并将结果存储在标记列表变量中。但是,这种“完全展开”是可以控制的:在这种情况下,我们传递

\exp_not:N \fbox{ \exp_not:V \l_multibox_tokens_tl }

这意味着将按\fbox原样存储(即“\noexpand”);左括号已经像右括号一样不可展开。现在

\exp_not:V \l_multibox_tokens_tl

传递变量的当前值,但不会再扩展。因此\l_multibox_tokens_tl执行过程中的连续值\multibox{5}{Hello}将是

Hello
\fbox{Hello}
\fbox{\fbox{Hello}}
\fbox{\fbox{\fbox{Hello}}}
\fbox{\fbox{\fbox{\fbox{Hello}}}}
\fbox{\fbox{\fbox{\fbox{\fbox{Hello}}}}}

并且这个最后的值最终被传送用于排版。

因此,它与 Heiko 的第一个解决方案(使用令牌寄存器和)并没有太大区别\edef

相关内容