# Incomplete \iffalse using \phantom

Can anyone help me debug the code below? As written, it produces an Incomplete \iffalse error on the \xdef line on the final iteration. The problem is somehow related to the \phantom macro, as \def\c{0} works fine. I know there are a couple of conditional tests inside \phantom, but I'm not enough of a TeX wizard to figure out what is colliding with what.

\documentclass{article}
\usepackage{tikz,xstring}

\begin{document}

\def\result{}
\foreach \i in {1,...,6}{
\StrChar{12345}{\i}[\c]
\ifx\c\empty
\def\c{\phantom{0}}
\fi
\xdef\result{\result\c}}

\stop

• Welcome to TeX.SX! Please help us to help you and add a minimal working example (MWE) that illustrates your problem. It will be much easier for us to reproduce your situation and find out what the issue is when we see compilable code, starting with \documentclass{...} and ending with \end{document}. – user31729 Dec 14 '14 at 20:30
• \phantom can't be used in \xdef, because it does assignments. – egreg Dec 14 '14 at 20:32
• See also tex.stackexchange.com/questions/215424/weird-tipx-error regarding @egreg's comment. – Ruben Dec 14 '14 at 20:36

\phantom is a fragile command and not safe in an \edef. One way to locally make it safe is:

\documentclass{article}
\usepackage{tikz,xstring}

\begin{document}

\def\result{}
\let\oldphantom\phantom
\let\phantom\relax
\foreach \i in {1,...,6}{
\StrChar{12345}{\i}[\c]
\ifx\c\empty
\def\c{\phantom{0}}
\fi
\xdef\result{\result\c}}
\let\phantom\oldphantom
\show\result

\stop

• You can simply do \let\phantom\relax inside the cycle code, because they are performed in a group. – egreg Dec 14 '14 at 21:02
• This solution works; thanks. I think I understand it, but I want to make sure. The \let\phantom\relax essentially makes \phantom an unexpandable noop inside the loop. But when \result is expanded at the end \phantom has its real definition back so it works as expected. Is that about right? – Jay Dec 14 '14 at 21:30
• @Jay yes, exactly – David Carlisle Dec 14 '14 at 21:39

You can't have \phantom inside \xdef, because it performs assignments.

There are several strategies for avoiding the problem.

First strategy: use a \protected macro:

\documentclass{article}
\usepackage{xstring,pgffor}

\protected\def\Pzero{\phantom{0}}

\begin{document}

\def\result{}
\foreach \i in {1,...,6}{%
\StrChar{12345}{\i}[\c]%
\ifx\c\empty
\def\c{\Pzero}%
\fi
\xdef\result{\result\c}%
}

X\result X

\end{document}


The loop can be, more simply,

\foreach \i in {1,...,6}{%
\StrChar{12345}{\i}[\c]%
\xdef\result{\result\ifx\c\empty\Pzero\else\c\fi}%
}


Second strategy: use token registers.

\documentclass{article}
\usepackage{xstring,pgffor}

\newtoks\mytoks

\begin{document}

\def\result{}
\mytoks={}
\foreach \i in {1,...,6}{%
\StrChar{12345}{\i}[\c]%
\ifx\c\empty
\global\mytoks=\expandafter{\the\mytoks\phantom{0}}%
\else
\global\mytoks=\expandafter{\the\expandafter\mytoks\c}%
\fi
}
\edef\result{\the\mytoks}

X\result X

\end{document}


Third strategy: forget xstring and pgffor and prefer expl3.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
{% #1 is the final number of digits
% #2 the given number
% #3 is an optional macro to store the result in
\IfNoValueTF{#3}
{
\jay_padnumber:nnn { \tl_use:N \l_jay_partial_tl } { #1 } { #2 }
}
{
\jay_padnumber:nnn { \tl_set_eq:NN #3 \l_jay_partial_tl } { #1 } { #2 }
}
}

\tl_new:N \l_jay_partial_tl

{
% store the given number
\tl_set:Nn \l_jay_partial_tl { #3 }
\int_compare:nT { \tl_count:N \l_jay_partial_tl < #2 }
{
% add as many \phantom{0} as needed
\tl_put_right:Nx \l_jay_partial_tl
{
\prg_replicate:nn { #2 - \tl_count:N \l_jay_partial_tl } { \exp_not:N \phantom { 0 } }
}
}
% produce the result or store it
#1
}
\ExplSyntaxOff

\begin{document}

X1234567890 % test


We count the items in the argument; if the number of items exceeds the given argument, the number is simply printed (or stored). Otherwise the right number of \phantom{0} is added in one step.