\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
,从 变为0
;1
计数器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
。