有一个答案解释如何将数字转换为文本这里\ref
。但是,如果我在命令中使用输出,即使引用输出是一位数,\convertdigits
它也会抛出错误。下面的代码取自该网站。Missing number, treated as zero.
\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}
\section{a}
\subsection{a1}\label{key}
\subsection{a2}
\section{b}
\subsection{b1}
\subsection{b2}
\subsubsection{b3}
\ref{key}
\def\myvar{2}
\convertdigits{2}
\convertdigits{\myvar}
\convertdigits{\ref{key}} % ERROR
\end{document}
我的问题:我可以将 的最后一位数字转换为\ref{key}
字符串吗?例如,如果
的输出\ref{key}
是2.3
然后
的输出\convertdigits{\ref{key}}
应该是three
。
答案1
你可以做这样的事情:
{\def\hbox#1{}\def\protect#1\empty{??}\xdef\reftext{\ref{key}\empty}}
\convertdigits{\reftext}
答案2
您可以使用refcount
并且其可扩展\getrefnumber
。
为了隔离输入字符串的最后一部分,您可以使用\regex_split:nnN
将以句点分隔的部分存储到序列的不同项目中并取最后一项。
\documentclass{article}
\usepackage{xparse}
\usepackage{refcount}
\ExplSyntaxOn
\NewDocumentCommand{\convertdigits}{m}
{
\mert_convertdigits:e { #1 }
}
\cs_new_protected:Nn \mert_convertdigits:n
{
\regex_split:nnN { \. } { #1 } \l__mert_convertdigits_seq
\__mert_digit:e { \seq_item:Nn \l__mert_convertdigits_seq { -1 } }
}
\cs_generate_variant:Nn \mert_convertdigits:n { e }
\cs_new:Nn \__mert_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
}
\cs_generate_variant:Nn \__mert_digit:n { e }
\ExplSyntaxOff
\begin{document}
\section{a}
\subsection{a1}\label{key}
\subsection{a2}
\section{b}
\subsection{b1}
\subsection{b2}\label{key2}
\subsubsection{b3}
\ref{key}, \ref{key2}
\def\myvar{2}
\convertdigits{2}
\convertdigits{\myvar}
\def\myvar{2.3}
\convertdigits{\myvar}
\convertdigits{\getrefnumber{key}}
\convertdigits{\getrefnumber{key2}}
\end{document}
如果要继续\ref
在该上下文中使用,可以将主定义更改为
\NewDocumentCommand{\convertdigits}{m}
{
\group_begin:
\cs_set_eq:NN \ref \getrefnumber
\mert_convertdigits:e { #1 }
\group_end:
}
答案3
您可以使用 refcount-package 中的宏\getrefbykeydefault
来提取产生引用文本字符串的标记序列。
假设扩展不会显著改变该序列,您可以将这些标记作为.
-separated 元素的列表并提取其中的最后一个。(当写“显著改变该序列”时,我会考虑诸如扩展之类的场景,从而删除一些点分隔的元素。)
如果确保扩展最后一个以点分隔的元素仅产生有效的⟨数字⟩-quantity 表示一个非负数,它可以被“馈送”,例如,到\numberstringnum
fmtcount 包的 -macro。
通过下面的示例检查是否扩展它只产生一个有效的 TeX-⟨数字⟩- 省略了表示非负数的数量,因为我不知道有任何测试是不存在某种缺陷的。
(任何此类测试必定是有缺陷的/只对可能的用户输入的某些受限子集有效:
当尝试实现此类测试的算法时,您将面临停机问题:
在扩展它们时,构成引用的文本字符串的最后一个点分隔元素的标记可能形成任意基于扩展的算法。让算法检查这种算法最终是否产生有效的 TeX-⟨数字⟩-quantity(表示非负数)意味着让算法检查另一个任意算法是否完全终止/终止时没有错误消息。这就是停机问题。艾伦图灵证明,不可能实现一种算法,对于任何任意算法,都可以“决定”该算法是否会终止。)
\documentclass{article}
\usepackage{hyperref}
\usepackage{refcount}
\usepackage{fmtcount}
\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\@secondoftwo\string{\expandafter
\@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
\@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
{\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%-------------------------------------------------------------------------
\@ifdefinable\UD@gobbletofirstdot{\long\def\UD@gobbletofirstdot#1.{}}%
\@ifdefinable\UD@keeptofirstdot{\long\def\UD@keeptofirstdot#1.{#1}}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}
\newcommand\extractlastdotitem[3]{\romannumeral0\extractlastdotitemloop{#1.}{#2}{#3}}%
\newcommand\extractlastdotitemloop[3]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletofirstdot#1}{%
\expandafter\expandafter\expandafter\UD@PassFirstToSecond
\expandafter\expandafter\expandafter{\expandafter\@gobble\UD@keeptofirstdot\relax#1}{ #2}#3%
}{%
\expandafter\extractlastdotitemloop\expandafter{\UD@gobbletofirstdot#1}{#2}{#3}%
}%
}%
\newcommand\convertdigitsoflabel[1]{%
\IfRefUndefinedBabel{#1}{\@ifundefined{hyperref}{\ref}{\ref*}{#1}}{%
\begingroup\protected@edef\@tempa{\getrefbykeydefault{#1}{}{0}}%
\expandafter\extractlastdotitem\expandafter{\@tempa}{\endgroup\numberstringnum}{[m]}%
}%
}%
\makeatother
\begin{document}
\section{a}
\subsection{a1}\label{a1}
\subsection{a2}
\subsection{a3}
\subsection{a4}
\subsection{a5}
\subsection{a6}
\subsection{a7}
\subsection{a8}
\subsection{a9}
\subsection{a10}
\subsection{a11}\label{a11}
\section{b}
\subsection{b1}
\subsection{b2}
\subsubsection{b3}
\bigskip\hrule\bigskip
\ref{a1}
\ref{a11}
\convertdigitsoflabel{a1}
\convertdigitsoflabel{a11}
\hyperref[{a1}]{\convertdigitsoflabel{a1}}
\hyperref[{a11}]{\convertdigitsoflabel{a11}}
\end{document}