Seltsames Verhalten von \sbox

Seltsames Verhalten von \sbox

Diese Frage besteht aus zwei miteinander verbundenen Teilen. Ich habe das ursprüngliche Problem bereits gelöst, verstehe aber immer noch nicht, woher es kam oder warum die Lösung funktioniert.

Ich verwende das subcaptionPaket, um zwei Untertabellen nebeneinander platzieren zu können. Jede Untertabelle benötigt die vorgesehene Breite, daher verwende ich zusätzlich ein , saveboxum zuerst die Tabelle zu erstellen, dann die Breite der Box zu messen, um die optimale Untertabellenbreite zu erhalten und zu guter Letzt den Inhalt der Box auszudrucken.

\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}

Allerdings pdflatexbegann mir die folgende Warnung zu geben

Nicht voll \hbox (Badness 10000) im Absatz in den Zeilen 24--25

wobei 24 die Linie ist, \useboxbei der sich das befindet.

Das macht keinen Sinn, da die Untertabelle genau die richtige Breite haben sollte. Durch Ausprobieren habe ich herausgefunden, dass die Warnung nur dann auftritt, wennalleeine der folgenden drei Bedingungen gilt:

  1. Die angegebene Konstruktion wird im Anhang (also nach \appendix) verwendet.
  2. Das cleverefPaket wird geladen.
  3. %Am Ende der Zeile steht „Nein“ \usebox.

Ich verstehe nicht, warum das alles überhaupt einen Einfluss hat …

Meine zweite Frage tauchte bei der Suche nach dem Fehler auf. Ich habe die zweite Tabelle durch eine \rulegleich große ersetzt, zumindest habe ich das versucht. Während die Breite ( {\wd\tablebox}) für mich in Ordnung aussieht, stimmt die Höhe der Ersetzung ( {\ht\tablebox}) nicht. Sie ist viel zu schmal. Warum?

Zum Schluss noch ein MWE, das alle beschriebenen Effekte demonstriert. Bitte beachten Sie, dass es aufgrund der keine Warnung für die eigentliche Tabelle gibt, %aber eine für den Ersatz \rulemit der gleichen Breite:

\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}

Antwort1

Unterfüllt \hbox

Das Problem ist ein Paket cleveref, das ein unerwünschtes Leerzeichen setzt. Die Zeile beginnt mit einem Objekt, das die gesamte Zeile füllt. Normalerweise beendet der folgende \captionAufruf den vorherigen Absatz und entfernt dabei das letzte Leerzeichen. Wenn jedoch durch einen Code von vorher \parein Leerzeichen gesetzt wurde , dann nur\caption\cleverefeinsLeerzeichen werden am Ende des Absatzes entfernt. Das andere Leerzeichen verursacht einen Zeilenumbruch und wird am Anfang der neuen Zeile entfernt. Die neue Zeile hat jedoch bereits begonnen und ist ziemlich leer, und LaTeX beschwert sich mit Underfull \hbox.

Ein Beispiel für ein einfaches TeX-Modell:

\showboxdepth=1000
\showboxbreadth=1000
\tracingonline=1
\setbox0=\vbox{%
  \noindent
  \vrule height 1pt width \hsize\relax
  \space\space
}
\showbox0
\csname @@end\endcsname\end

TeX gibt als Warnung aus:

Underfull \hbox (badness 10000) in paragraph at lines 5--8

\hbox(0.0+0.0)x469.75499
.\glue(\rightskip) 0.0

Und Box 0 enthält:

> \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

Innerhalb des vertikalen Felds ( \vbox) \noindentbeginnt ein neuer Absatz ohne Einzug. Am Ende des Felds beendet TeX den Absatz (implizit \par). Dann entfernt TeX ein letztes Leerzeichen (implizit \unskip), um das letzte Leerzeichen zu entfernen. In diesem Fall das zweite \spaceund fügt stattdessen das Leerzeichen hinzu \parfillskip. Dann enthält der Absatz vor dem Umbruch:

<\vrule ...> <\space> <\hskip\parfillskip>

Die Regel füllt die komplette Zeile, daher bricht TeX die Zeile nach der Regel vor dem Leerzeichen ab. Am Anfang der neuen Zeile werden Leerzeichen entfernt, daher werden sowohl als auch <\space>entfernt <\hskip\parfillskip>. Die Zeile enthält nur die automatisch eingefügten \rightskip, die keine dehnbaren Komponenten enthalten, siehe das Feld der Warnung:

\hbox(0.0+0.0)x469.75499
.\glue(\rightskip) 0.0

Die Box enthält also nichts, was die Zeile füllen würde. Die Zeile istunterfüllt.

Problemumgehungen:

  • Kommentieren Sie das Zeilenende (Sie haben es bereits gefunden).
  • \param Ende, dann werden nachfolgende Leerzeichen im vertikalen Modus ignoriert.
  • Laden cleverefüber:

    \edef\RestoreEndlinechar{\endlinechar=\the\endlinechar\relax}
    \endlinechar=-1 %
    \usepackage{cleveref}
    \RestoreEndlinechar
    

    (Leerzeichen in Warnmeldungen können fehlen.)

Das unerwünschte Zeilenende von cleveref.sty2013/03/22 v0.18.9 befindet sich in der Definition von \refstepcounter@noargs, Zeile 196 und 242.

Unvollständige Regel

Du hast einfach vergessen, dass eine Box eine Tiefe haben kann. Das Standardverhalten einer Box tabularist die Grundlinie in der Mitte. Aber auch mit Option [b]kannst du eine normalerweise geringe Tiefe haben, wenn das letzte Element eine normale Zeile und keine Box ist \hline.

\raiseboxkann helfen, eine Tiefe zu erzeugen:

    \raisebox{-\dp\tablebox}{%
      \rule{\wd\tablebox}{\dimexpr\ht\tablebox+\dp\tablebox\relax}%
    }%

verwandte Informationen