GeneralChecking if label defined

LaTeX specific issues not fitting into one of the other forums of this category.
Post Reply
Laurentius
Posts: 132
Joined: Wed Feb 11, 2009 11:38 pm

Checking if label defined

Post by Laurentius »

I want to check whether or not a lable containing a number is defined:

Code: Select all

\documentclass{article}

\begin{document}

\makeatletter

\count16=2
\label{snowflake\the\count16}
\label{apple}

\ifdefined \r@a a defined \else a undefined \fi % checks if label 'a' defined

\ifdefined \r@apple apple defined \else apple undefined \fi

\pageref{snowflake2} % prints the pagenumber

\pageref{snowflake\the\count16} % prints the pagenumber too

% But this doesn't work:
\ifdefined \r@snowflake2 snowflake2 defined \else snowflake2 undefined \fi

\makeatother

\end{document}
The overarching problem is that I need to use \ifnum on a \pageref; but this doesn't work unless the label is defined.

Recommended reading 2024:

LaTeXguide.org • LaTeX-Cookbook.net • TikZ.org

NEW: TikZ book now 40% off at Amazon.com for a short time.

cgnieder
Site Moderator
Posts: 2000
Joined: Sat Apr 16, 2011 7:27 pm

Checking if label defined

Post by cgnieder »

TeX's (and hence LaTeX's) control sequence names can either contain of arbitrary many letters, i.e., characters with category code 11, or of one character with another category code. This is the reason for \makeatletter: it gives @ the category code 11 (letter), \makeatother gives it category code 12 (other) again.

When you have

Code: Select all

\makeatletter
\ifdefined \r@snowflake2 snowflake2 defined \else snowflake2 undefined \fi
\makeatother
you test if the control sequence \r@snowflake is defined. If it is 2 snowflake2 defined is left in the input stream:

Code: Select all

\documentclass{article}
\begin{document}
\label{snowflake}

\makeatletter
\ifdefined \r@snowflake2 snowflake2 defined \else snowflake2 undefined \fi
\makeatother

\end{document}
Now you don't want to change the category code of 2 directly (although it is of course possible). The way around is to use TeX's primitive \csname ...\endcsname or in this case eTeX's \ifcsname ... \endcsname ... \fi. \csname <tokens>\endcsname builds a command sequence name of <tokens>.

Code: Select all

\documentclass{article}
\begin{document}
\label{snowflake2}

\makeatletter % not needed, strictly speaking: the @ will be part of the csname
\expandafter\ifdefined\csname r@snowflake2\endcsname
  snowflake2 defined%
\else
  snowflake2 undefined%
\fi

\ifcsname r@snowflake2\endcsname
  snowflake2 defined%
\else
  snowflake2 undefined%
\fi
\makeatother

\end{document}
It might be more convenient to use etoolbox's wrappers around this:

Code: Select all

\documentclass{article}
\usepackage{etoolbox}
\begin{document}
\label{snowflake2}

\makeatletter % not needed, strictly speaking: the @ will be part of the csname
\ifcsdef{r@snowflake2}
  {snowflake2 defined}
  {snowflake2 undefined}
\makeatother

\end{document}
Regards
site moderator & package author
Laurentius
Posts: 132
Joined: Wed Feb 11, 2009 11:38 pm

Re: Checking if label defined

Post by Laurentius »

Perfect! Many thanks again, Clemens.

Lorenz
Post Reply