如何使超过 9 个参数的命令与表格一起工作?

如何使超过 9 个参数的命令与表格一起工作?

我有一个命令需要超过 9 个参数。我偶然发现了这个解决方案:如何定义接受超过 9 个参数的命令。这在普通文本中运行良好。但我尝试在tabular环境中使用它,但出现undefined control sequence错误。这是一个 MWE:

\documentclass{article}
\begin{document}
\newcommand*\foo[9]{%
 \def\tempa{#1}%
 \def\tempb{#2}%
 \def\tempc{#3}%
 \def\tempd{#4}%
 \def\tempe{#5}%
 \def\tempf{#6}%
 \def\tempg{#7}%
 \def\temph{#8}%
 \def\tempi{#9}%
 \foocont
}
\newcommand\foocont[1]{\tempa & \tempb & \tempc & \tempd & \tempe & \tempf & \tempg & \temph & \tempi & #1 \cr}

\begin{tabular}{*{10}c}
\foo{1}{2}{3}{4}{5}{6}{7}{8}{9}{a}
\end{tabular}
\end{document}

如果删除所有&\crtabular环境,只\foo使用 10 个参数调用,则代码可以很好地编译(打印出123456789a)。

我怎样才能使这个“参数扩展”与之一起工作tabular

答案1

执行 的第一个表格单元格\foo也是一个本地组。在下一个之后,、 、 ...&的本地含义将丢失。\tempb\tempc

有几种方法

全局定义

\documentclass{article}
\begin{document}
\newcommand*\foo[9]{%
 \gdef\tempa{#1}%
 \gdef\tempb{#2}%
 \gdef\tempc{#3}%
 \gdef\tempd{#4}%
 \gdef\tempe{#5}%
 \gdef\tempf{#6}%
 \gdef\tempg{#7}%
 \gdef\temph{#8}%
 \gdef\tempi{#9}%
 \foocont
}
\newcommand\foocont[1]{\tempa & \tempb & \tempc & \tempd & \tempe & \tempf &
\tempg & \temph & \tempi & #1 \cr}

\begin{tabular}{*{10}c}
\foo{1}{2}{3}{4}{5}{6}{7}{8}{9}{a}
\end{tabular}
\end{document}

结果

扩张

以下示例\temp...通过 扩展了宏。这通过和强大的命令\protected@edef支持 LaTeX 保护机制。宏甚至可以仅在本地分配:\protect\temp...

\documentclass{article}
\begin{document}
\newcommand*\foo[9]{%
  \begingroup
  \def\tempa{#1}%
  \def\tempb{#2}%
  \def\tempc{#3}%
  \def\tempd{#4}%
  \def\tempe{#5}%
  \def\tempf{#6}%
  \def\tempg{#7}%
  \def\temph{#8}%
  \def\tempi{#9}%
  \foocont
}
\makeatletter
\newcommand*\foocont[1]{%
  \protected@edef\process@me{%
    \endgroup
    \tempa & \tempb & \tempc & \tempd & \tempe & \tempf &
    \tempg & \temph & \tempi & #1 \cr
  }%
  \process@me
}
\makeatother

\begin{tabular}{*{10}c}
\foo{1}{2}{3}{4}{5}{6}{7}{8}{9}{a}
\end{tabular}
\end{document}

一级扩展

\protect如果宏仅展开一次,则可以避免 使用脆弱命令。e-TeX 的\temp...命令\unexpanded会有所帮助。不使用 e-TeX 的替代方案是使用令牌寄存器。

\documentclass{article}
\begin{document}
\newcommand*\foo[9]{%
  \begingroup
  \def\tempa{#1}%
  \def\tempb{#2}%
  \def\tempc{#3}%
  \def\tempd{#4}%
  \def\tempe{#5}%
  \def\tempf{#6}%
  \def\tempg{#7}%
  \def\temph{#8}%
  \def\tempi{#9}%
  \foocont
}
\newcommand*\foocont[1]{%
  \edef\processme{%
    \endgroup
    \unexpanded\expandafter{\tempa} &
    \unexpanded\expandafter{\tempb} &
    \unexpanded\expandafter{\tempc} &
    \unexpanded\expandafter{\tempd} &
    \unexpanded\expandafter{\tempe} &
    \unexpanded\expandafter{\tempf} &
    \unexpanded\expandafter{\tempg} &
    \unexpanded\expandafter{\temph} &
    \unexpanded\expandafter{\tempi} & #1 \cr
  }%
  \processme
}

\begin{tabular}{*{10}c}
\foo{1}{2}{3}{4}{5}{6}{7}{8}{9}{a}
\end{tabular}
\end{document}

答案2

正如 David 在评论中所建议的,另一种方法是使用逗号分隔的语法:

\foo{1,2,3,4,5,6,7,8,9,a}

然后,您可以循环遍历条目并将它们放到位。由于我们在表格内工作,因此仍然存在一些扩展问题,但您可以使用电子工具箱\foreach使用以下方法循环遍历参数来构建每一行前列腺素

这样做的主要优点是代码可以轻松扩展到任意数量的参数。其次,代码更短,更容易维护,因为您不需要像 Heiko 那样对每个参数进行特殊处理。如果您真的想要,您可以检查参数数量是否正确,但在我看来这似乎有点过头了,因为输出中清除的行太少,而太多会自动给出错误。

我改变了 MWE,以说服自己这样做是可行的:

在此处输入图片描述

以下是代码:

\documentclass{article}
\usepackage{pgffor}
\usepackage{etoolbox}
\newcommand\foo[1]{%
  \global\def\sep{}% will expand to & except for the first column
  \global\let\myrow\relax% will become the row built from #1
  \foreach \arg in {#1} {% loop over #1 to build \myrow
     \xappto\myrow{\sep\arg}% global expansion
     \gdef\sep{&}% make the next separator &
  }%
  \myrow\\% print the row
}

\begin{document}

\begin{tabular}{*{10}{c|}}
  \foo{1,2,3,4,5,6,7,8,9,a}
  \foo{111,22,,444,55,{10,000},77,88,99,a}
\end{tabular}

\end{document}

(顺便说一句,正如booktabs 包,使用垂直线来分隔列通常不是一个好主意。我上面这样做只是为了表明代码可以正常工作。)

相关内容