我在David Hanak回答之后编辑了这个问题(谢谢顺便说一下!)。他帮助了语法,但似乎我没有使用正确的函数开始。
基本上我想要的是让编译器忽略某个标签的多个定义而只使用第一个。为了做到这一点,我想我会做这样的事情:
\makeatletter \newcommand{\mylabel}[1]{ \@ifundefined{#1}{\label{#1}}{X} } \makeatother
但这不起作用,因为始终选择第一个选项(如果定义了标签,则无关紧要)。我认为\ @ifundefined(以及建议的\ ifundefined)仅适用于命令而不适用于标签,但我对LaTeX并不是很了解。任何帮助都会很棒!谢谢!
很晚以后更新: 我将David Hanak的回答标记为我问题的正确答案,但它并不是一个完整的解决方案,尽管它确实帮助了我。 问题是,我认为,但我不是专家,即使David的代码检查是否定义了标签,它只在标签在前一次运行中定义时才有效(即在.aux文件中)。如果在同一次运行中定义了两个具有相同名称的\ mylabels,则仍将定义第二个\ mylabels。此外,即使您设法解决此问题,它也会使LaTeX使用您按时间顺序定义的第一个标签,而不一定是文本中的第一个标签。 无论如何,下面是我的快速和肮脏的解决方案。它使用的事实是,似乎确实立即定义了计数器。
\newcommand{\mylabel}[1]{% \@ifundefined{c@#1}{% \newcounter{#1}% \setcounter{#1}{0}% }{}% \ifthenelse{\value{#1} > 0}{}{% \label{#1}% \addtocounter{#1}{1}% }% }
我不确定是否有必要将计数器初始化为0,因为它似乎可能是默认值,但我无法找到是否是这种情况,所以我只是安全。 此外,这使用'ifthen'包,我不确定是否必要。
答案 0 :(得分:4)
@
是LaTeX中的一个特殊字符。为了使您的声明在语法上正确,您还需要再添加两行:
\makeatletter
\newcommand{\mylabel}[1]{
\@ifundefined{#1}{\label{#1}}{X}
}
\makeatother
第一行将@
变为普通字母,最后一行将其效果反转。
更新:您可能还想查看“普通”\ifundefined
LaTeX macro。
更新2
好的,我做了一些研究来找出真正的问题的答案。问题是定义标签不会通过该名称创建宏;它预先给它一个“r @”。请尝试以下方法:
\makeatletter
\newcommand{\mylabel}[1]{
\@ifundefined{r@#1}{\label{#1}}{X}
}
\makeatother
有关更多技术细节,请参阅LaTeX发行版中的latex.ltx第3863行(其中显示\def\newlabel{\@newl@bel r}
)。
答案 1 :(得分:4)
我也不是LaTeX专家,但是经过一天尝试和搜索互联网后,以下内容对我有用。我使用了一个虚拟计数器来解决问题。希望这有帮助,显然没有多少人在寻找这个。
\newcommand{\mylabel}[1]{
\ifcsname c@#1\endcsname%
\else%
\newcounter{#1}\label{#1}%
\fi%
}
答案 2 :(得分:0)
Victor Eijkhout," TeX by Topic",p.143:
\def\ifUnDefinedCs#1{\expandafter\ifx\csname#1\endcsname\relax}
这可用于检查是否定义了标签;如果没有,则打印标签:
\newcommand{\myautoref}[1]{\ifUnDefinedCs{r@#1}{\color{magenta}\IDontKnow\{#1\}}\else\autoref{#1}\fi}