[Tex/LaTex] Convert numbers in string to string

fmtcountstringsxstring

I store some strings in a variable \def\nomVAR{A12Z4E} and I want to create some other command using the content of \nomVAR. LaTeX doesn't accept to declare variable with number in its name. So the idea will be to convert all the number in the string using \numberstringnum command (fmtcount package). The xstring can extract some specific string in a string but I have to precise the position of each one.

Do you think it is possible to write a function to convert each number to a string in a string and to rebuilt it?

Thus A12Z4E will become AonetwoZfourE.

MNWE

\documentclass{minimal}

\usepackage{xstring}
\usepackage{fmtcount}

\begin{document}

\def\nomVAR {A12Z4E}

\nomVAR

\numberstringnum{1}

\numberstringnum{\nomVAR} %not working

\end{document}

SOLUTION (thanks egreg)

\documentclass{minimal}

\usepackage{xstring}

\begin{document}

\def\nomVAR {A12Z4E}

\nomVAR

\numberstringnum{1}

\newcommand{\changestep}[2]{%
  \expandafter\StrSubstitute\expandafter{\x}{#1}{#2}[\x]%
}
\newcommand{\changeall}[1]{
 % suppress expansions made by xstring
\StrSubstitute{#1}{0}{zero}[\x]%
\x
\noexpandarg
\changestep{1}{one}
\changestep{2}{two}
\changestep{3}{three}
\changestep{4}{four}
\changestep{5}{five}
\changestep{6}{six}
\changestep{7}{seven}
\changestep{8}{eight}
\changestep{9}{nine}
\x
}

\changeall{\nomVAR}

\end{document}

Best Answer

You can do it expandably, provided the string only has alphanumeric ASCII characters:

\documentclass{article}

\makeatletter
\newcommand{\convertdigits}[1]{\expandafter\convert@digits#1\convert@digits}
\def\convert@digits#1{%
  \ifx#1\convert@digits
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {\convert@@digits#1}%
}
\def\convert@@digits#1{%
  \ifnum9=9#1%
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {\convert@@digit#1}\convert@digits
}
\def\convert@@digit#1{%
  \ifcase#1%
    zero\or
    one\or
    two\or
    three\or
    four\or
    five\or
    six\or
    seven\or
    eight\or
    nine\fi
}
\makeatother

\begin{document}

\def\myvar{A12Z4E}

\convertdigits{A12Z4E}

\convertdigits{\myvar}

\edef\myvartext{\convertdigits{\myvar}}
\texttt{\meaning\myvartext}

\end{document}

enter image description here

A different expl3 implementation: the argument to \convertdigits is fully expanded before being examined and scanned item by item.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewExpandableDocumentCommand{\convertdigits}{m}
 {
  \guuk_convertdigits:e { #1 }
 }

\cs_new:Nn \guuk_convertdigits:n
 {
  \tl_map_function:nN { #1 } \guuk_digit:n
 }
\cs_generate_variant:Nn \guuk_convertdigits:n { e }

\cs_new:Nn \guuk_digit:n
 {
  \str_case:nnF { #1 }
   {
    {0}{zero}
    {1}{one}
    {2}{two}
    {3}{three}
    {4}{four}
    {5}{five}
    {6}{six}
    {7}{seven}
    {8}{eight}
    {9}{nine}
   }
   {#1}% not a digit
 }
\ExplSyntaxOff

\begin{document}

\def\myvar{A12Z4E}

\convertdigits{A12Z4E}

\convertdigits{\myvar}

\edef\myvartext{\convertdigits{\myvar}}
\texttt{\meaning\myvartext}

\end{document}
Related Question