Неполный \iffalse с использованием \phantom

Неполный \iffalse с использованием \phantom

Может ли кто-нибудь помочь мне отладить код ниже? Как написано, он выдает Incomplete \iffalse errorна \xdefстроке на последней итерации. Проблема как-то связана с \phantomмакросом, так как \def\c{0}работает нормально. Я знаю, что внутри есть пара условных проверок \phantom, но я не настолько мастер TeX, чтобы понять, что с чем сталкивается.

\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

решение1

\phantomэто хрупкая команда и небезопасна в \edef. Один из способов сделать ее безопасной локально:

\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

решение2

\phantomВнутри его быть не может \xdef, так как он выполняет задания.

Существует несколько стратегий, позволяющих избежать этой проблемы.

Первая стратегия: используйте \protectedмакрос:

\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}

Цикл может быть, проще говоря,

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

Вторая стратегия: используйте регистры токенов.

\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}

Третья стратегия: забыть xstringи pgfforи предпочесть 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}

Подсчитываем элементы в аргументе; если количество элементов превышает заданный аргумент, число просто выводится (или сохраняется). В противном случае нужное количество \phantom{0}добавляется за один шаг.

введите описание изображения здесь

Связанный контент