Alguém pode me ajudar a depurar o código abaixo? Conforme está escrito, produz um Incomplete \iffalse error
na \xdef
linha da iteração final. O problema está de alguma forma relacionado à \phantom
macro, pois \def\c{0}
funciona bem. Eu sei que existem alguns testes condicionais dentro do \phantom
, mas não sou um assistente do TeX o suficiente para descobrir o que está colidindo com o quê.
\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
Responder1
\phantom
é um comando frágil e não é seguro em um arquivo \edef
. Uma maneira de torná-lo seguro localmente é:
\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
Responder2
Não pode ter \phantom
inside \xdef
, pois ele realiza atribuições.
Existem diversas estratégias para evitar o problema.
Primeira estratégia: use uma \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}
O loop pode ser, de forma mais simples,
\foreach \i in {1,...,6}{%
\StrChar{12345}{\i}[\c]%
\xdef\result{\result\ifx\c\empty\Pzero\else\c\fi}%
}
Segunda estratégia: use registros de token.
\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}
Terceira estratégia: esquecer xstring
e pgffor
preferir expl3
.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\padnumber}{mmo}
{% #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
\cs_new_protected:Npn \jay_padnumber:nnn #1 #2 #3
{
% 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
X\padnumber{6}{12345}X
X\padnumber{7}{12345}X
X\padnumber{4}{12345}X
\padnumber{8}{12345}[\result]
\texttt{\meaning\result}
\end{document}
Contamos os itens do argumento; se o número de itens exceder o argumento fornecido, o número será simplesmente impresso (ou armazenado). Caso contrário, o número certo de \phantom{0}
será adicionado em uma única etapa.