如何计算整数中的数字(或单词中的字母)的数量,然后检索其中的任意数字(或字母)?

如何计算整数中的数字(或单词中的字母)的数量,然后检索其中的任意数字(或字母)?

我需要 (1) 计算数字中的位数(或计算单词中的字母数),以及 (2) 检索这些数字中的任意一个(或这些字母中的任意一个)。此外,还需要满足以下条件:expl3不应使用以及非由 LaTeX 团队创作/维护的软件包。

\def\zCountDigits#1%
  {% COUNT DIGITS OF #1
  }
\def\zGetDigit#1#2%
  {% GET DIGIT OF #1 AT INDEX #2
  }

答案1

人们总是可以采用现有的代码并重新编写。在这里,我使用了一些想法,expl3但略微简化了(以牺牲一点鲁棒性为代价)

\def\zCountDigits#1{%
  \number\numexpr0\zCountDigitsAux#1\zCountDigitsEnd\relax
}
\def\zCountDigitsAux#1{%
  \ifx\zCountDigitsEnd#1\else+1\expandafter\zCountDigitsAux\fi
}
\def\zCountDigitsEnd{\zCountDigitsEnd}

\zCountDigits{}
\zCountDigits{123}
\zCountDigits{abC}

\def\zGetDigit#1#2{%
  \zGetDigitLoop{1}{#2}#1\zGetDigitEnd
}
\def\zGetDigitLoop#1#2#3{%
  \ifx\zGetDigitEnd#3\else
    \ifnum #1 = #2 %
      \expandafter\expandafter\expandafter\zGetDigitCleanup
        \expandafter\expandafter\expandafter#3%
    \else
      \zGetDigitLoopStep{#1}{#2}%
    \fi
  \fi
}
\def\zGetDigitCleanup#1#2\zGetDigitEnd{#1}
\def\zGetDigitLoopStep#1#2\fi\fi{\fi\fi
  \expandafter\zGetDigitLoop\expandafter{\number\numexpr#1 + 1\relax}{#2}%
}
\def\zGetDigitEnd{\zGetDigitEnd}

\zGetDigit{abc}{1}
\zGetDigit{abc}{3}
\zGetDigit{abc}{4}
\zGetDigit{abc}{-2}

\bye

(我不能 100% 确定你是否需要空间处理、括号组保留,ETC。:我采用了简单的方法,但它们也可以包括在内。


循环的工作方式是\zCountDigitsAux每次抓取一个标记:如果你看一下设置,就会发现 中没有括号#1\zCountDigits因此,\ifx\zCountDigitsEnd#1是将一个标记与结束标记进行比较。我使用了私有的“循环结束”标记,而不是说\relax。这是为了确保我们仍然可以计算包含 的输入序列\relax:这里的计数方法不仅适用于字符标记,还适用于宏、\chardef标记、ETC。

假设循环尚未完成,我们插入+1然后需要关闭条件。\zCountDigitsAux宏需要查看输入流中的下一个内容,我们需要避免打开越来越多的条件级别。因此我使用 \expandafter\zCountDigitsAux\fi。这会扩展\fi,结束条件,在\zCountDigitsAux扩展之前。(如果没有这个,\zCountDigitsAux会抓住\fi,我们会用完堆栈。)\zCountDigitsAux这里没有传递任何参数,因为其余的原始参数\zCountDigits仍在输入流中。

答案2

以下解决方案根本不使用任何包,因此不会违反禁止使用“非由 LaTeX 团队创作/维护”的包的规定。(另外:我不知道“LaTeX 团队”的成员是谁——或者甚至不知道是否有这样的团队。)

由于您在示例中使用的是\def而不是\newcommand,我认为您主要对“纯 TeX”解决方案感兴趣。因此,下面显示的代码使用的是 LuaTeX ,而不是 LuaLaTeX。代码提供了两个宏,\zCountChars\zGetChar。宏使用“primitive”命令\directlua和内置的 LuaTeX 函数tex.sprintstring.lenstring.sub

在此处输入图片描述

\def\zCountChars#1{\directlua{tex.sprint(string.len("#1"))}}
\def\zGetChar#1#2{\directlua{tex.sprint(string.sub("#1",#2,#2))}}

\zCountChars{1066}, \zCountChars{123abc}.

\zGetChar{6789}{2}, \zGetChar{123abc}{-2}.
\bye

请注意,可以使用负数作为 的第二个参数\zGetChar。在这种情况下,计数开始从最后字符串/数字,而不是从头开始。

相关内容