![交叉引用任何计数器](https://linux22.com/image/380483/%E4%BA%A4%E5%8F%89%E5%BC%95%E7%94%A8%E4%BB%BB%E4%BD%95%E8%AE%A1%E6%95%B0%E5%99%A8.png)
我猜\ref{Label}
返回的是最后出现的计数器\label{Label}
?
此时有可能获取另一个计数器的任意值吗?\pageref
返回页码,如何获取我已经制作的一个计数器?
答案1
并非真正的最后一个计数器:\label{foo}
将引用使用\refstepcounter
在同一范围内 \label
。
我见过几次的一个错误是
\begin{figure}
\begin{center}
\includegraphics{whatever}
\caption{The caption text}
\end{center}
\label{foo}
\end{figure}
由于多种原因,这种做法是错误的,但在这种情况下,它有助于说明上面的观点:环境center
是计数器步进的范围figure
(作为的副作用\caption
),但\label
超出了这个范围,因此它不会引用图号。
该机制的工作方式如下:\refstepcounter{figure}
做两件事
\stepcounter{figure}
(全局操作figure
)\edef\@currentlabel{\thefigure}
请注意,第二部分是局部重新定义;\@currentlabel
是保存最后一个“refstepped”计数器的内部宏。
如果您想要\label
引用fredcounter
,您必须\refstepcounter{fredcounter}
在某处发出并确保\label{foo}
出现在任何其他计数器“refstepped”之前(通过诸如\section
、\caption
或 之类的命令\item
),并且在同一范围内。
答案2
我完全不知道为什么在放置标签时需要访问所有计数器的值。
我想了解LaTeX 中\label
..机制的工作原理可能会帮助您重新考虑您的愿望。\ref
就在几周前,TeX - LaTeX StackExchange 上出现了一个问题“如何防止在新环境中引用枚举?”,我看到了详细阐述与\label
..\ref
机制相关的事物在 LaTeX 2ε 中相互作用的方式的机会。我当时的回答可以在这里找到:https://tex.stackexchange.com/a/442118/118714
如果你已经了解\label
..\ref
机制的细节,并且有充分的理由坚持你的愿望,我在下面提供了一个示例,概述了可能处理此问题的方式。
这个想法的要点是:
\cl@@ckpt
用于\include
..功能的LaTeX2e-kernel-macro\includeonly
确实包含一个\@elt{⟨countername⟩}
列表,其中包含通过 创建的所有计数器的名称\newcounter
。
使用时Heiko Oberdiek 的zref 包,您可以轻松地使用该列表为每个计数器定义一个可引用的属性。
您需要区分立即设置值的计数器和在输出例程发出相关页面时设置/调整值的计数器。
您没有要求任何超链接/hyperref-package-functionity。
因此,对于下面的示例,我没有实现该功能,因为我没有理由猜测需要什么样的工作流程。
\documentclass{article}
\usepackage{zref}
\makeatletter
%%-------------------------------------------------------------------------
%% Paraphernalia:
%%.........................................................................
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@temp{}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
\UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
\UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%-------------------------------------------------------------------------
%% Check whether argument contains no \relax-token on top-brace-level:
%%.........................................................................
%% \UD@CheckWhetherNoRelax{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that
%% argument which is to be checked does not contain \relax>}%
%% {<Tokens to be delivered in case that
%% argument which is to be checked does contain \relax>}%
\newcommand*\UD@RemoveToRelax{}\long\def\UD@RemoveToRelax#1\relax{}%
\newcommand\UD@CheckWhetherNoRelax[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@RemoveToRelax#1\relax}%
}%
%%-------------------------------------------------------------------------
%% Fork depending on strings being "page", "abspage", i.e., the names
%% of counters whose values are not set immediately but at
%% page-shipout-time:
%%.........................................................................
\newcommand*\UD@@ForkDelayedCounter{}%
% Manually add the names of more counters whose values are not set immediately
% but at page-shipout-time.
\long\def\UD@@ForkDelayedCounter%
#1\relax page\relax abspage\relax#2#3\relax\relax\relax{#2}%
\newcommand\UD@ForkDelayedCounter[1]{%
\UD@CheckWhetherNoRelax{#1}{%
\UD@@ForkDelayedCounter
\relax#1\relax abspage\relax{\UD@firstoftwo}%<-page-counter
\relax page\relax#1\relax{\UD@firstoftwo}%<-abspage-counter
\relax page\relax abspage\relax{\UD@secondoftwo}%<-counter other than both page and abspage
\relax\relax\relax
}{\UD@secondoftwo}%<-\relax-token in counter name. This should not happen.
}%
%%-------------------------------------------------------------------------
%% At the beginning of the document-environment, when all counter-defining
%% should be done, create a new property list holding all counter values:
%% (The LaTeX2e-kernel-macro \cl@@ckpt which is used for the
%% \include/\includeonly-feature does hold an \@elt{<countername>}-list
%% with the names of all counters created via \newcounter.)
%%.........................................................................
\zref@newlist{UD@AllCounterValues}%
\newcommand\UD@CounterValueAsProperty[1]{%
\UD@ForkDelayedCounter{#1}{%
\zref@newprop*{Ref#1}{\csname the#1\endcsname}%
}{%
\zref@newprop{Ref#1}{\csname p@#1\endcsname\csname the#1\endcsname}%
}%
\zref@addprop{UD@AllCounterValues}{Ref#1}%
}%
\newcommand*\UD@AllCounterValuesAsProperties{%
\let\UD@temp=\@elt
\let\@elt=\UD@CounterValueAsProperty
\cl@@ckpt
\let\@elt=\UD@temp
}%
\AtBeginDocument{\UD@AllCounterValuesAsProperties}%
%%-------------------------------------------------------------------------
%% Create referencing and label commands:
%%.........................................................................
\newcommand*\AllCounterValuesLabel[1]{%
\@bsphack
\zref@labelbylist{#1}{UD@AllCounterValues}%
\@esphack
}%
\newcommand*\CounterValueRef[2]{%
\zifrefundefined{#1}{%
\zref@refused{#1}\nfss@text{\reset@font\bfseries??}%
}{%
\zref@extractdefault{#1}{Ref#2}{%
\@latex@warning{%
Reference `#1' on page \thepage\space does not hold a value of counter #2%
}%
\nfss@text{\reset@font\bfseries??}%
}%
}%
}%
\makeatother
\newcounter{mycounter}
\newcommand\DoSomethingWithMycounter{%
\stepcounter{mycounter}%
\texttt{mycounter} has the value \number\value{mycounter}.
}%
\begin{document}
\section{A section}
Some text
\subsection{A subsection}
Some text
\subsection{Another subsection}
\subsubsection{A subsubsection}
\subsubsection{Another subsubsection}
\subsubsection{Yet another subsubsection}
\begin{enumerate}
\item Item 1
\item Item 2
\item Item 3
\item Item 4\par
\DoSomethingWithMycounter\par
\DoSomethingWithMycounter\par
\AllCounterValuesLabel{MyNiceLabel}%
\end{enumerate}
\newpage
\section*{Referencing:}
\hskip\parindent
At the time of placing the label \verb!MyNiceLabel!,\\
\verb!\p@section\thesection! expanded to:
\CounterValueRef{MyNiceLabel}{section}
\bigskip
At the time of placing the label \verb!MyNiceLabel!,\\
\verb!\p@subsection\thesubsection! expanded to:
\CounterValueRef{MyNiceLabel}{subsection}
\bigskip
At the time of placing the label \verb!MyNiceLabel!,\\
\verb!\p@subsubsection\thesubsubsection! expanded to:
\CounterValueRef{MyNiceLabel}{subsubsection}
\bigskip
At the time of placing the label \verb!MyNiceLabel!,\\
\verb!\p@enumi\theenumi! expanded to:
\CounterValueRef{MyNiceLabel}{enumi}
\bigskip
At the time of placing the label \verb!MyNiceLabel!,\\
\verb!\p@mycounter\themycounter! expanded to:
\CounterValueRef{MyNiceLabel}{mycounter}
\bigskip
\end{document}