如何将命令参数处理成一定数量的字符?

如何将命令参数处理成一定数量的字符?

目前,我正在编写一份旅行指南,我想在地点和活动旁边添加一般价格信息,例如

$$$$ - 高档昂贵的牛排馆

我认为既然我经常这样做,那么最好制作一个小命令来插入任意数量的美元符号,而不是单独转义每个美元符号,但我无论如何都无法弄清楚。

理想情况下,我希望命令类似于

\price{4}

像上面那样插入 4 个美元符号。我感觉我遗漏了一些简单的东西,但在谷歌搜索了我的问题的各种变体并查看了 tex 宏(不幸的是没有结果)之后,我仍然不知所措。我还希望能够格式化美元符号(例如灰色),但我觉得\price一旦我让它工作起来,我可以通过围绕命令定义一个环境来做到这一点。

任何帮助或相关文档的指引都将不胜感激。谢谢!

答案1

最好将\price和分开\pricesymbol

\documentclass{article}
\usepackage{xcolor}

\NewDocumentCommand{\pricesymbol}{}{\textcolor{black!60}{\$}}

\ExplSyntaxOn

\NewDocumentCommand{\price}{m}
 {
  \prg_replicate:nn { #1 } { \pricesymbol }
 }

\ExplSyntaxOff

\begin{document}

\price{4} -- Fancy Expensive Steakhouse

\price{2} -- Pizza House (no pineapple)

\end{document}

在此处输入图片描述

您甚至可以使用分数价格符号。

\documentclass{article}
\usepackage{xcolor}
\usepackage{trimclip}

\NewDocumentCommand{\pricesymbol}{}{\textcolor{black!60}{\$}}

\ExplSyntaxOn

\NewDocumentCommand{\price}{m}
 {
  \prg_replicate:nn { \fp_eval:n { trunc(#1,0) } } { \pricesymbol }
  \fp_compare:nT { #1 - trunc(#1,0) > 0 }
   {
    \clipbox{0~0~{\fp_eval:n { 1 - #1 + trunc(#1,0) }\width}~0} { \pricesymbol } \,
   }
 }

\ExplSyntaxOff

\begin{document}

\price{4} -- Fancy Expensive Steakhouse

\price{2} -- Pizza House (no pineapple)

\price{2.3} -- Pizza House (no pineapple)

\price{2.5} -- Pizza House (no pineapple)

\price{2.7} -- Pizza House (no pineapple)

\end{document}

在此处输入图片描述

答案2

在此处输入图片描述

一种方法是对数字进行简单的递归


\documentclass{article}
\begin{document}
\newcommand\price[1]{\ifnum#1>0\$\price{\numexpr#1-1\relax}\fi}

\price{1}  zzz

\price{20} ZZZ

\end{document}

答案3

尾递归,仅限传统 TeX:

\documentclass{article}

\newcommand\priceloop[1]{\if#1m\$\expandafter\priceloop\fi}
\newcommand\price[1]{\expandafter\priceloop\romannumeral\number\number#1 000\relax}

\begin{document}

\price{12}

\end{document}

尾递归,eTeX 扩展:

\documentclass{article}

\newcommand\exchange[2]{#2#1}%
\newcommand\price[1]{\ifnum#1>0 \exchange{\$\expandafter\price\expandafter{\the\numexpr#1-1\relax}}\fi}

\begin{document}

\price{12}

\end{document}

或者使用David Kastrup 的\replicate变体:

\documentclass{article}

\newcommand\gobble[1]{}
\newcommand\xii[2]{\if#2m#1\expandafter\xii\else\expandafter\gobble\fi{#1}}
\newcommand\xiii[2]{\xii{#2}#1\relax}
\newcommand\replicate[1]{\expandafter\xiii\expandafter{\romannumeral\number\number#1 000}}%

\newcommand\price[1]{\replicate{#1}{\$}}

\begin{document}

\price{12}

\end{document}
\documentclass{article}

\newcommand\recur[1]{\csname rn#1\recur}
\newcommand\rnm[1]{\endcsname{#1}#1}
\newcommand\rn[1]{}
\newcommand\replicate[1]{\csname rn\expandafter\recur\romannumeral\number\number#1 000\endcsname\endcsname}

\newcommand\price[1]{\replicate{#1}{\$}}

\begin{document}

\price{12}

\end{document}

该顺序\romannumeral\number\number#1 000而不仅仅是\romannumeral#1000出于以下原因:

#1是一些 TeX-⟨数字⟩-数量需要通过附加数字乘以 1000,000以便\romannumeral提供相应数量的字符标记m

#1不一定是数字序列。

\count也可以是一个-寄存器,您需要一个空格标记来将表示-寄存器的数字\count与三个零分开,以附加到形成该\count-寄存器中保存的值的标记:

\count假设您希望表示寄存器 17中保存的值:

\romannumeral\count17000不会起作用,因为 TeX 假设尝试表示\count寄存器 17000 中保存的值,并且由于没有\count寄存器 17000 而引发错误。

\romannumeral\number\number\count17 000确实有效:

第二个\number将保存在寄存器 17 中的值作为数字序列传递。后面/前面\count的空间被用作表示寄存器的数字序列的结束标记。1700017\count

\number这里不需要第一个/这不会改变这样一个事实:当第二个\number完成时,您已经有一个附加了三个零的数字序列,可以通过来处理\romannumeral

但是 TeX-⟨数字⟩-quantity 可以是\countdef-token 或\chardef-token 或类似的,此后空格标记将不会被 TeX 删除。

假设有人做\chardef\sixtyfive=`\A.
\romannumeral\sixtyfive000不会成功,因为 TeX 收集 TeX 的规则是⟨数字⟩\chardef带有-tokens的-quantities000将不会被视为要处理的数字的一部分\romannumeral

但会解决:\romannumeral\number\number\sixtyfive⟨space-token⟩000

第二个从 chardef-token\number传递。后面跟着65\sixtyfive65⟨空间标记⟩和三个零。第一个\number找到后面65跟着一个⟨空间标记⟩并消除了⟨空间标记⟩. 现在\romannumeral作为要转换的数字可以收集65000和传递 65 个字符m

相关内容