我正在尝试创建一个具有动态列数的动态表,并且hspace
。
以下是我目前所掌握的信息:
\documentclass{article}
\usepackage{tabularx}
\usepackage{array}
\usepackage{forloop}
\begin{document}
\edef\rowdescriptor{|c|}
\edef\pointsdescriptor{}
\newcounter{tempcounter}
\forloop{tempcounter}{0}{\value{tempcounter} < 5}{
\edef\rowdescriptor{\rowdescriptor c|}
\edef\pointsdescriptor{\expandafter\noexpand\pointsdescriptor & }
}
\expandafter\tabular\expandafter{\rowdescriptor}
\hline
\pointsdescriptor \\
\hline
\endtabular
\end{document}
这会产生六个框,正如预期的那样。但是,我想让框更宽,同时保留 ,c
因为实际表格有更多行,其中的文本需要居中。为此,我使用了\hspace
。因此,当我将 for 循环中的第二行更改为
\edef\pointsdescriptor{\expandafter\noexpand\pointsdescriptor & \noexpand{\hspace{0.75cm}}}
我立即收到错误“ \forloop 的使用与其定义不匹配”。
我是否以某种方式错误地扩展了令牌? 这里有什么错误? 我该如何做得更好?
答案1
这forloop
包似乎很旧了...我建议\foreach
使用前列腺素. 对于递归构建命令,我总是使用\gappto
使用电子工具箱包。另外,您不需要构建宏,\rowdescriptor
因为您可以定义:
\def\rowdescriptor{*5{|c}|}
意思*5{|c}
是“重复列规范|c
5 次”。
综合起来,下面就可以实现您想要的效果:
\documentclass{article}
\usepackage{tabularx}
\usepackage{array}
\usepackage{etoolbox}
\usepackage{pgffor}
\begin{document}
\def\rowdescriptor{*5{|c}|}
\foreach \x in {1,...,4}{
\gappto\pointsdescriptor{\hspace*{0.75cm}&}
}
\xappto\pointsdescriptor{\noexpand\hspace*{0.75cm}}
\expandafter\tabular\expandafter{\rowdescriptor}
\hline
\pointsdescriptor \\
\hline
\endtabular
\end{document}
我还使用了\hspace*
as 来强制插入空格。请注意,循环后必须添加一个“extra”,\hspace*
因为有 4 个&
s 和 5 列。以下是输出:
编辑
这是将列数隐藏在宏中的版本。当然,你可以\csname ....\endcsname
在这里使用,但我更喜欢使用\csuse{...}
但我更电子工具箱 包,因为我发现这更容易阅读。
\documentclass{article}
\usepackage{tabularx}
\usepackage{array}
\usepackage{etoolbox}
\usepackage{pgffor}
\begin{document}
\def\numberofcolumns{5}
\def\pointsdescriptor{}% initialise
\xdef\rowdescriptor{*{\csuse{numberofcolumns}}{|c}|}
\foreach \x in {1,...,\numexpr\csuse{numberofcolumns}-1}{
\gappto\pointsdescriptor{\hspace*{0.75cm}&}
}
\xappto\pointsdescriptor{\noexpand\hspace*{0.75cm}}
\expandafter\tabular\expandafter{\rowdescriptor}
\hline
\pointsdescriptor \\
\hline
\endtabular
\end{document}
输出与上面相同。请注意,如果{\csuse{numberofcolumns}}
列数超过 9 列,则应该使用括号。此外,\xdef\rowdescriptor
上面的 不是必需的,因为宏numberofcolumns
是“静态的”,但\xdef
如果您的实际 csname 依赖于计数器,则 是必需的。
这是第三种变体,其中代码放在一个宏中,该宏将列数作为可选参数,默认为 5:
\documentclass{article}
\usepackage{tabularx}
\usepackage{array}
\usepackage{etoolbox}
\usepackage{pgffor}
\newcommand\mytabular[1][5]{%
\bgroup%
\def\rowdescriptor{*{#1}{|c}|}%
\def\pointsdescriptor{}%
\foreach \x in {1,...,\numexpr#1-1}{%
\gappto\pointsdescriptor{\hspace*{0.75cm}&}
}%
\xappto\pointsdescriptor{\noexpand\hspace*{0.75cm}}%
\expandafter\tabular\expandafter{\rowdescriptor}
\hline
\pointsdescriptor \\
\hline
\endtabular%
\egroup%
}
\begin{document}
\mytabular
\mytabular[7]
\end{document}
这次的输出是:
我不确定您的实际应用是什么,但我可能会尝试使用类似这种方法。
答案2
您的问题是,只要有一个(第一个)标记需要保护以免扩展,就\expandafter\noexpand\pointsdescriptor
可以工作。使用 e-TeX,可以使用 轻松覆盖此问题。您也不需要,因为后者适用于,而 已经不可扩展。这意味着您将得到\pointsdescriptor
\unexpanded
{\noexpand\hspace{0.75cm}}
\noexpand{\hspace{0.75cm}}
\noexpand
{
\documentclass{article}
\usepackage{tabularx}
\usepackage{array}
\usepackage{forloop}
\begin{document}
\edef\rowdescriptor{|c|}
\edef\pointsdescriptor{}
\newcounter{tempcounter}
\forloop{tempcounter}{0}{\value{tempcounter} < 5}{
\edef\rowdescriptor{\rowdescriptor c|}
\edef\pointsdescriptor{\unexpanded\expandafter{\pointsdescriptor} & {\noexpand\hspace{0.75cm}}}
}
\expandafter\tabular\expandafter{\rowdescriptor}
\hline
\pointsdescriptor \\
\hline
\endtabular
\end{document}
值得注意的是,这没有放入足够的空间:安德鲁的回答已经涵盖了解决这个问题的方法(我认为这通常是一种更好的方法)。