我将一些字符串存储在一个变量中\def\nomVAR{A12Z4E}
,我想使用的内容创建其他命令\nomVAR
。LaTeX 不接受在名称中声明带有数字的变量。因此,想法是使用\numberstringnum
命令(fmtcount
包)转换字符串中的所有数字。xstring
可以提取字符串中的一些特定字符串,但我必须精确确定每个字符串的位置。
您认为是否可以编写一个函数将字符串中的每个数字转换为字符串并重建它?
这样A12Z4E
就会变成AonetwoZfourE
。
微电子工程协会
\documentclass{minimal}
\usepackage{xstring}
\usepackage{fmtcount}
\begin{document}
\def\nomVAR {A12Z4E}
\nomVAR
\numberstringnum{1}
\numberstringnum{\nomVAR} %not working
\end{document}
解决方案(感谢 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}
答案1
您可以扩展它,只要字符串仅包含字母数字 ASCII 字符:
\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}
不同的实现:在逐项检查和扫描之前,expl3
对参数进行充分展开。\convertdigits
\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}
答案2
这里我设置了一个 tokencycle 来逐个查找字母 (catcode 11) 和数字。其他内容将被丢弃。数字通过 进行处理\spelldigit
,它会执行一个简单的\ifcase
。
\documentclass{article}
\usepackage{tokcycle}
\newcommand\numberstringnum[1]{%
\resettokcycle
\Characterdirective{\tctestifcatnx A##1{##1}{\spelldigit##1}}%
\expandafter\tokcyclexpress\expandafter{#1}}
\newcommand\spelldigit[1]{%
\ifcase\numexpr`#1-`0 zero\or one\or two\or three\or four\or five\or
six\or seven\or eight\or nine\fi}
\begin{document}
\def\nomVAR {A12Z4E}
\nomVAR
\numberstringnum{\nomVAR}
\numberstringnum{AB23z0BN56q}
\end{document}
例如,如果您需要能够使用字符串来构建命令,则此变体不会输出结果,而是将其存储在中\thestring
,随后可以使用,如本 MWE 所示。
\documentclass{article}
\usepackage{tokcycle}
\newcommand\numberstringnum[1]{%
\Characterdirective{\tctestifcatnx A##1{\addcytoks{##1}}%
{\addcytoks[x]{\spelldigit##1}}}%
\Groupdirective{}%
\Macrodirective{}%
\Spacedirective{}%
\expandafter\tokcyclexpress\expandafter{#1}%
\edef\thestring{\the\cytoks}%
\expandafter\def\csname\thestring\expandafter\endcsname\expandafter
{#1}}
\newcommand\spelldigit[1]{%
\ifcase\numexpr`#1-`0 zero\or one\or two\or three\or four\or five\or
six\or seven\or eight\or nine\fi}
\begin{document}
\def\nomVAR {A12Z4E}
\numberstringnum{\nomVAR}
\textbackslash\thestring=\csname\thestring\endcsname
\numberstringnum{AB23Z0BN56Q}
\textbackslash\thestring=\csname\thestring\endcsname
\end{document}