![\sbox 的奇怪行为](https://linux22.com/image/272053/%5Csbox%20%E7%9A%84%E5%A5%87%E6%80%AA%E8%A1%8C%E4%B8%BA.png)
这个问题由两个相关的部分组成。我已经解决了原始问题,但仍然不明白它从何而来,也不明白解决方案为何有效。
我使用subcaption
包,这样我就可以把两个子表并排放置。每个子表都需要预期的宽度,因此我另外使用一个savebox
来首先创建表,然后测量框的宽度以获得最佳子表宽度,最后但并非最不重要的是打印框的内容。
\newsavebox{\tablebox}
\sbox{\tablebox}{
\begin{tabular}{ccc}
1st & 2nd & 3rd \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{tabular}
}
% create fitting subtable
\begin{subtable}{\wd\tablebox}
\usebox{\tablebox}
\caption{Subable}
\end{subtable}
然而,pdflatex
开始给我以下警告
段落第 24-25 行的 \hbox 未满(badness 10000)
其中 24 是所在的线\usebox
。
这毫无意义,因为子表应该具有完全正确的宽度。通过反复试验,我发现警告仅在以下情况下发生:全部以下三个条件之一成立:
- 给定的构造用于附录中(即之后
\appendix
)。 - 程序
cleveref
包已加载。 %
行尾没有\usebox
。
我不明白为什么这些会产生影响......
我在尝试找出错误时出现了第二个问题。我用\rule
相同大小的表格替换了第二个表格,或者至少这是我试图实现的。虽然宽度 ( {\wd\tablebox}
) 对我来说看起来不错,但替换的高度 ( {\ht\tablebox}
) 是错误的。它太窄了。为什么?
最后,一个 MWE 演示了所有描述的效果。请注意,由于实际表格没有警告,但对于具有相同宽度的%
替换有一个警告:\rule
\documentclass[english]{scrreprt}
\usepackage{babel}
\usepackage{subcaption}
\usepackage{cleveref}
\begin{document}
\appendix
\newsavebox{\tablebox}
\begin{table}
% prepare table
\sbox{\tablebox}{
\begin{tabular}{ccc}
1st & 2nd & 3rd \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{tabular}
}
% create fitting subtable
\begin{subtable}{\wd\tablebox}
\usebox{\tablebox}% no warning for this table
\caption{Left Table}
\end{subtable}
%
\hspace{2ex}
%
% create fitting subtable
\begin{subtable}{\wd\tablebox}
\rule{\wd\tablebox}{\ht\tablebox}
\caption{Right Table}
\end{subtable}
\caption{Two Tables}
\end{table}
\end{document}
答案1
\hbox 未满
问题是cleveref
设置了不需要的空格的包。该行以填充整行的对象开头。通常,以下\caption
调用\par
会结束上一段并删除进程中的最新空格。但是,如果\caption
某些代码中有一个空格\cleveref
中有一个空格,则只有一段落末尾的空格会被删除。另一个空格会导致换行,并在新行的开头删除。但新行已经开始,而且很空,因此 LaTeX 会报错Underfull \hbox
。
普通 TeX 模型的示例:
\showboxdepth=1000
\showboxbreadth=1000
\tracingonline=1
\setbox0=\vbox{%
\noindent
\vrule height 1pt width \hsize\relax
\space\space
}
\showbox0
\csname @@end\endcsname\end
TeX 打印警告:
Underfull \hbox (badness 10000) in paragraph at lines 5--8
\hbox(0.0+0.0)x469.75499
.\glue(\rightskip) 0.0
框 0 包含:
> \box0=
\vbox(13.0+0.0)x469.75499
.\hbox(1.0+0.0)x469.75499
..\rule(1.0+*)x469.75499
..\glue(\rightskip) 0.0
.\penalty 300
.\glue(\baselineskip) 12.0
.\hbox(0.0+0.0)x469.75499
..\glue(\rightskip) 0.0
! OK.
l.9 \showbox0
在垂直框 ( \vbox
)内\noindent
开始一个不带缩进的新段落。在框的末尾,TeX 结束段落(隐式\par
)。然后 TeX 删除最后一个空格(隐式\unskip
)以删除最后一个空格。在本例中是第二个空格\space
,并改为添加空格\parfillskip
。然后,拆分前的段落包含:
<\vrule ...> <\space> <\hskip\parfillskip>
该规则填充整行,因此 TeX 会在规则之后的空格之前断开行。新行开头的空格会被删除,因此 和 都会
<\space>
被<\hskip\parfillskip>
删除。该行仅包含自动插入的\rightskip
,不包含可拉伸组件,请参见警告框:
\hbox(0.0+0.0)x469.75499
.\glue(\rightskip) 0.0
因此,盒子里不包含任何可以填充该线的东西,该线是未满。
解决方法:
- 注释行尾(您已经找到它)。
\par
在最后,后续空格在垂直模式下将被忽略。加载
cleveref
方式:\edef\RestoreEndlinechar{\endlinechar=\the\endlinechar\relax} \endlinechar=-1 % \usepackage{cleveref} \RestoreEndlinechar
(警告信息中的空格可能缺失。)
2013/03/22 v0.18.9的不需要的行结尾cleveref.sty
位于 的定义中\refstepcounter@noargs
,第 196 行和 242 行。
不完整规则
您只是忘记了,一个框可以有深度。 的默认行为tabular
是中间的基线。 但是,如果最后一个元素是普通行而不是,[b]
您也可以使用选项获得通常较小的深度。\hline
\raisebox
有助于创造深度:
\raisebox{-\dp\tablebox}{%
\rule{\wd\tablebox}{\dimexpr\ht\tablebox+\dp\tablebox\relax}%
}%