该 TeX 代码如何在表格环境中生成自动 \hline?

该 TeX 代码如何在表格环境中生成自动 \hline?

@AlexeyMalistov 回答了让 LaTeX 在表格中的每一行之间绘制一个 \hline 而不使用 \hline?在 TeX.SE 出现之前,StackOverflow 上就有这个问题。后来 TeX.SE 上也出现了同样的问题:带有自动 \hline 的表格

Malistov 的答案成功地在表格的每一行之间生成了一条线,是在之前添加以下内容tabular

\catcode`@=11
\let \savecr \@tabularcr
\def\@tabularcr{\savecr\hline}
\catcode`@=12

我认为这重新定义了制表环境中的换行符,因此插入\hline了,但代码对我来说仍然只是巫术。有人愿意解释一下它是如何工作的吗?谢谢。

答案1

破解密码

\catcode`@=11
\let \savecr \@tabularcr
\def\@tabularcr{\savecr\hline}
\catcode`@=12

逐步向下:

  • \catcode`@=11

    这会将 的类别代码更改为@“字母”,因为@否则可能无法在宏名称中使用。您会注意到,后续行使用\@tabularcr,我们需要@将其类型设为“字母”。其他人喜欢使用\makeatletter(请参阅做什么\makeatletter\makeatother做什么?)。

  • \let \savecr \@tabularcr

    这将立即复制一份\@tabularcr并将其存储在 中\savecr。这样您就可以修改\@tabularcr(后续行)但仍保留旧版本的副本。

  • \def\@tabularcr{\savecr\hline}

    这里\@tabularcr实际上被重新定义为\savecr(上面存储为\@tabularcr 这个重新定义后面跟着\hline- 你想要的水平规则。为什么要(重新)定义\@tabularcr?从 LaTeX 内核(latex.ltx),环境的定义tabular执行(在稍后的阶段)

    \def\@tabular{\leavevmode \hbox \bgroup $\let\@acol\@tabacol
       \let\@classz\@tabclassz
       \let\@classiv\@tabclassiv \let\\\@tabularcr\@tabarray}
    

    在这里您可以看到(在最后一行),在开始实际之前将其\\设置为等同于,因此将具有现在包括附加的新定义。\@tabularcrtabular\\\@tabularcr\hline

  • \catcode`@=12

    这会将 的类别代码恢复@为 其他。有些用户更喜欢使用\makeatother

有关类别代码的参考,请参阅类别代码是什么?


当然,在 a 之前添加此内容tabular会使它在您的文档中全局化。也许更明智的做法是将其包含在一个组中(或作为环境)以本地化更改。或者,您可以定义命令开关来“激活”此\hline自动化并在稍后“停用”它。

答案2

该代码似乎可以工作,但实际上不行。我们来看一个例子:

\documentclass{article}

\catcode`@=11
\let \savecr \@tabularcr
\def\@tabularcr{\savecr\hline}
\catcode`@=12

\begin{document}
\begin{tabular}{c}
a\\[1cm]
b
\end{tabular}
\end{document}

输出

在此处输入图片描述

让我们看看为什么。的原始定义\@tabularcr

% latex.ltx, line 5040:
\def\@tabularcr{%
  {\ifnum0=`}\fi\@ifstar\@xtabularcr\@xtabularcr}

并且已经注意到一些事情:如果由于错误或因为tabular和之间共享了一些代码,用于结束一行的longtable类型将不会被重新定义的命令识别和删除,因为之后的标记始终是。\\**\savecr\hline

\@tabularcr因此输入流中的新叶子

\@xtabularcr\hline

事情又出错了,因为的定义\@xtabularcr

% latex.ltx, line 5042:
\def\@xtabularcr{\@ifnextchar[\@argtabularcr{\ifnum0=`{\fi}\cr}}

旁边的标记\@xtabularcr绝不[,这就是导致我的示例输出不佳的原因。


在每一行后自动添加规则的最佳方法是什么?没有,至少有两个原因:

  1. 每行之后不需要水平线。
  2. 您无法\cline在需要的地方添加它。

答案3

将此解决方案与 longtable 一起使用会导致一些行线丢失(如 egreg 所解释的那样)。一种解决方案是将 longtable 的块大小设置为大于表的行数:

\setcounter{LTchunksize}{1000}

注意:使用 pander 生成 RMarkdown 表时会发生这种情况:

pander(df, keep.line.breaks = TRUE, use.hyphening = TRUE, split.table = Inf)

相关内容