动态定义在 ttabbox 中不起作用

动态定义在 ttabbox 中不起作用

\uref我在其他人的帮助下创建了一个宏。它创建了动态定义,可以生成唯一的标签。如果我用它调用\uref{first}它,它会返回 a,并且每次使用相同标签调用它都会返回 a。如果我用新标签调用它,它会返回 b,依此类推。它通过检查定义是否存在来实现这一点,如果不存在,它会创建它并根据计数器分配一个字母。

它工作得很好,除了我用来调整表格标题和脚注大小的ttabbox命令。如果我以相同的顺序使用相同的标签floatrow,它ttabbox起作用了。所以我想我可以先用 构建一个不可见的表格\setbox0\vbox{\atable},但这并不能满足我理解为什么会发生这种情况的需求。无论如何,使用宏的目的是为了处理大型表格,我可能会更改行的顺序和标签的顺序,我不想加载两次长表格。

对于为什么这个命令会导致问题有任何见解吗?

\documentclass{article}

\usepackage{floatrow}

\newcounter{unilabIN}% my referene counter withIN each new instance
\newcounter{unilabOUT}% creates a new set of counters if incremented
\stepcounter{unilabOUT}% start at 1 -> a
\makeatletter
\newcommand\uref[1]{% my command "unique" referencer
  \@ifundefined{uni\alph{unilabOUT}lab@#1}{%if reference doesnt exist, ie. hasn't been used
    \stepcounter{unilabIN}\expandafter\xdef\csname uni\alph{unilabOUT}lab@#1\endcsname{\alph{unilabIN}}% create a label for reference
    % defines a command : uni&lab$  where & is group letter, and $ is the label name
  }{}%
  \csname uni\alph{unilabOUT}lab@#1\endcsname% call the label
}
\makeatother

\newcommand{\atnote}[1]{\textsuperscript{\uref{#1}}}

\begin{document}

\providecommand{\atable}{
\begin{tabular}{ll}
  \hline
    Things & Applicable Things \\\hline
    Aardvark & \atnote{lookslikerat}, \atnote{fourlegs} \\
    Bat & \atnote{lookslikerat} \\
    Cheetah & \atnote{fourlegs} \\\hline
\end{tabular}
}

Notes should print a, b, a, b

Mechanism doesn't work here (prints all a's)
\begin{table}[htpb]% htbp! settings
        \ttabbox% if no star use hanging
        {\caption{caption}\label{label}}%
        {\atable}%
\end{table}%

Mechanism works here IFF I comment out the above non working example
\atable%

\end{document}

答案1

(免责声明:我从未使用过floatrow,所以我可能误解了它的内部工作原理。)

您需要全局地采取措施,无论 的善意是什么\ttabbox(请参阅后面的详细说明)。基本上,您必须替换以下行

\stepcounter{unilabIN}

经过

\global\advance\value{unilabIN}\@ne

或(更低级的)

\global\advance\c@unilabIN\@ne

回到你最初的 MWE,这意味着

\documentclass{article}

\usepackage{floatrow}

\newcounter{unilabIN}% my referene counter withIN each new instance
\newcounter{unilabOUT}% creates a new set of counters if incremented
\stepcounter{unilabOUT}% start at 1 -> a
\makeatletter
\newcommand\uref[1]{% my command "unique" referencer
  \@ifundefined{uni\alph{unilabOUT}lab@#1}{%if reference doesnt exist, ie. hasn't been used
    \global\advance\value{unilabIN}\@ne  % <=== THIS BIT HERE
    \expandafter\xdef\csname uni\alph{unilabOUT}lab@#1\endcsname{\alph{unilabIN}}% create a label for reference
    % defines a command : uni&lab$  where & is group letter, and $ is the label name
  }{}%
  \csname uni\alph{unilabOUT}lab@#1\endcsname% call the label
}
\makeatother

\newcommand{\atnote}[1]{\textsuperscript{\uref{#1}}}

\providecommand{\atable}{%
\begin{tabular}{ll}
  \hline
  Things & Applicable Things \\
  \hline
  Aardvark & \atnote{lookslikerat}, \atnote{fourlegs} \\
  Bat & \atnote{lookslikerat} \\
  Cheetah & \atnote{fourlegs} \\
  \hline
\end{tabular}}

\begin{document}

\begin{table}
        \ttabbox
        {\caption{caption}\label{label}}%
        {\atable}%
\end{table}%

and see also\par\medskip
\atable

\end{document}

产量符合预期

在此处输入图片描述

问题的根源

该宏的\ttabbox目的是将标题文本(第一个强制参数)的宽度设置为其第二个强制参数(通常是 a tabular)的自然宽度。据我所知,它会输入三次内容:两次用于测量,最后一次用于输出。

为了避免“重复计数”,通过在前两个测量段落中删除它们的字符来floatrow重新定义\stepcounter(和其他事情)\global,以便计数器在最终排版中全局仅增加一次。例如,您可以检查

\documentclass{article}
\usepackage{floatrow}
\newcounter{mycntA}
\newcounter{mycntB}
\begin{document}
(\themycntA,\themycntB)
\begin{table}
\ttabbox{\caption{First}}
        {[Here a tabular]%
        \stepcounter{mycntA}%
        \global\advance\value{mycntB}1
        }
\end{table}
(\themycntA,\themycntB)
\end{document}

生产

在此处输入图片描述

计数器mycntA已增加\stepcounter,从 变为01计数器mycntB已手动增加全球并且已经从0变为3

你的情况怎么样

简化很多,您当前的代码可以归结为

\documentclass{article}

\usepackage{floatrow}
\newcounter{mycnt}

\makeatletter
\def\foo#1{%
   \@ifundefined{foo@#1}%
     {%
      \stepcounter{mycnt}%
      \expandafter\xdef\csname foo@#1\endcsname{\Alph{mycnt}}%
     }{}%
     \csname foo@#1\endcsname
}
\makeatother

\begin{document}
\begin{table}
\ttabbox{\caption{Caption}}%
  {%
   \begin{tabular}{cc}
   Left column & Right column \\
   \foo{bar} & \foo{baz}
   \end{tabular}}
\end{table}
\foo{bar}, \foo{baz}
\end{document}

在此处输入图片描述

现在,在第一个测量段落中\stepcounter只有局部效应:当 TeX 发现时,\foo{bar}它会检查是否\foo@bar定义;如果没有定义,它会踩计数器(本地!)并定义(全球因为\xdef!)\foo@cnt扩展为A。但由于增加是局部的,因此仅限于当前单元格(表格单元格始终隐式地充当组),因此当\foo在第二个单元格中再次调用 时,计数器再次为0!因此\foo@baz定义(全局)并(再次)分配值A

\foo@bar现在开始第二段:然而,这次对和的检查\foo@baz都是肯定的!结果,没有定义任何内容,只A打印了输出。(嗯,实际上没有打印,因为我们仍处于测量阶段。)

现在开始第三段:这将是“真正的”一个,其中\stepcounter是真的\global,并且会按照您的期望执行;但真正的分支 if\@ifundefined永远不会执行!这解释了为什么您的计数器在 之外从未真正增加\ttabbox

\foo@bar和的定义\foo@baz是全局的,因此它们当然也存在于 之外\ttabbox

相关内容