我有这个原始的乳胶生成器,用于根据客户的姓名、空格和姓氏生成文档编号:
\newcommand{\koda}[1]{%
\IfEqCase{#1}{%
{a}{1.}%
{b}{2.}%
{c}{3.}%
{č}{4.}%
{d}{5.}%
{e}{6.}%
{f}{7.}%
{g}{8.}%
{h}{9.}%
{i}{10.}%
{j}{11.}%
{k}{12.}%
{l}{13.}%
{m}{14.}%
{n}{15.}%
{o}{16.}%
{p}{17.}%
{r}{18.}%
{s}{19.}%
{š}{20.}%
{t}{21.}%
{u}{22.}%
{v}{23.}%
{z}{24.}%
{ž}{25.}%
{_}{26.}%
{ }{26.}%
% you can add more cases here as desired
}[\PackageError{koda}{Undefined option to koda: #1}{}]%
}%
我在文档中这样使用
\koda{n}\koda{a}\koda{m}\koda{e}\koda{_}\koda{s}\koda{u}\koda{r}\koda{n}\koda{a}\koda{m}\koda{e}
这将生成一个代码,其中客户的字母由其字母顺序数字表示(字母表中添加了下划线和空格)。代码如下所示:
这完全没问题,但我需要一种更简单的机制来输入客户的姓名并获取相同的文档代码。可以使用来实现吗\newcommand{}{}
?问题是因为不是每个客户的名字长度都相同,因此我不知道如何定义预期输入的数量...
我希望使用类似的东西\koda{name surname}
来获取代码。
答案1
我已经修改了来自如何重复字符串中的所有字符?针对您的问题
\documentclass{article}
\usepackage{xstring}
\makeatletter
\newcommand{\koda}[1]{%
\@tfor\next:=#1\do{\myList{\next}}%
}
\makeatother
\newcommand{\myList}[1]{%
\IfEqCase{#1}{%
{a}{1.}%
{b}{2.}%
{c}{3.}%
{č}{4.}%
{d}{5.}%
{e}{6.}%
{f}{7.}%
{g}{8.}%
{h}{9.}%
{i}{10.}%
{j}{11.}%
{k}{12.}%
{l}{13.}%
{m}{14.}%
{n}{15.}%
{o}{16.}%
{p}{17.}%
{r}{18.}%
{s}{19.}%
{š}{20.}%
{t}{21.}%
{u}{22.}%
{v}{23.}%
{z}{24.}%
{ž}{25.}%
{_}{26.}%
{ }{26.}%
% you can add more cases here as desired
}[\PackageError{koda}{Undefined option to koda: #1}{}]%
}%
\begin{document}
\koda{name_surname}
\end{document}
它似乎不能正确处理空间,因此我插入了它_
,但它是某种东西:)
编辑:我搜索了一下,想起了我从哪里得到答案
答案2
除非您使用 XeLaTeX 或 LuaLaTeX,否则问题出在重音字符上。这是一个适用于所有引擎的解决方案(但无论如何都需要 UTF-8)。
输入被字符串化,然后将各个位与前导码中建立的代码进行比较。如果字符恰好是 UTF-8 前缀,则将其放在一边,并将下一个字符添加到它以进行比较。
\documentclass{article}
\usepackage{ifxetex}
\ifxetex\else
\usepackage[utf8]{inputenc}
\fi
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\namekoda}{m}
{
\ziga_namekoda:n { #1 }
}
\cs_new_protected:Nn \ziga_namekoda:n
{
\tl_set:Nx \l__ziga_namekoda_input_tl { \tl_to_str:n { #1 } }
\tl_replace_all:Nnn \l__ziga_namekoda_input_tl { ~ } { | }
\tl_clear:N \l_ziga_namekoda_output_tl
\tl_clear:N \l__ziga_namekoda_current_tl
\tl_map_inline:Nn \l__ziga_namekoda_input_tl
{
\__ziga_namekoda_step:n { ##1 }
}
\tl_use:N \l_ziga_namekoda_output_tl
}
\cs_new_protected:Nn \__ziga_namekoda_step:n
{
\str_case_x:nnF { #1 }
{
{ \char_generate:nn { "C3 } { 12 } } { \__ziga_namekoda_add:n { #1 } }
{ \char_generate:nn { "C4 } { 12 } } { \__ziga_namekoda_add:n { #1 } }
{ \char_generate:nn { "C5 } { 12 } } { \__ziga_namekoda_add:n { #1 } }
}
{ \__ziga_namekoda_go:n { #1 } }
}
\cs_new_protected:Nn \__ziga_namekoda_add:n
{
\tl_put_right:Nn \l__ziga_namekoda_current_tl { #1 }
}
\cs_new_protected:Nn \__ziga_namekoda_go:n
{
\__ziga_namekoda_add:n { #1 }
\tl_put_right:Nx \l_ziga_namekoda_output_tl
{
\str_case:VV \l__ziga_namekoda_current_tl \c_ziga_namekoda_codes_tl .
}
\tl_clear:N \l__ziga_namekoda_current_tl
}
\cs_generate_variant:Nn \str_case:nn { VV }
\tl_const:Nx \c_ziga_namekoda_codes_tl
{
{ \tl_to_str:n { a } } { 1 }
{ \tl_to_str:n { A } } { 1 }
{ \tl_to_str:n { b } } { 2 }
{ \tl_to_str:n { B } } { 2 }
{ \tl_to_str:n { c } } { 3 }
{ \tl_to_str:n { C } } { 3 }
{ \tl_to_str:n { č } } { 4 }
{ \tl_to_str:n { Č } } { 4 }
{ \tl_to_str:n { d } } { 5 }
{ \tl_to_str:n { D } } { 5 }
{ \tl_to_str:n { e } } { 6 }
{ \tl_to_str:n { E } } { 6 }
{ \tl_to_str:n { f } } { 7 }
{ \tl_to_str:n { F } } { 7 }
{ \tl_to_str:n { g } } { 8 }
{ \tl_to_str:n { G } } { 8 }
{ \tl_to_str:n { h } } { 9 }
{ \tl_to_str:n { H } } { 9 }
{ \tl_to_str:n { i } } { 10 }
{ \tl_to_str:n { I } } { 10 }
{ \tl_to_str:n { j } } { 11 }
{ \tl_to_str:n { J } } { 11 }
{ \tl_to_str:n { k } } { 12 }
{ \tl_to_str:n { K } } { 12 }
{ \tl_to_str:n { l } } { 13 }
{ \tl_to_str:n { L } } { 13 }
{ \tl_to_str:n { m } } { 14 }
{ \tl_to_str:n { M } } { 14 }
{ \tl_to_str:n { n } } { 15 }
{ \tl_to_str:n { N } } { 15 }
{ \tl_to_str:n { o } } { 16 }
{ \tl_to_str:n { O } } { 16 }
{ \tl_to_str:n { p } } { 17 }
{ \tl_to_str:n { P } } { 17 }
{ \tl_to_str:n { r } } { 18 }
{ \tl_to_str:n { R } } { 18 }
{ \tl_to_str:n { s } } { 19 }
{ \tl_to_str:n { S } } { 19 }
{ \tl_to_str:n { š } } { 20 }
{ \tl_to_str:n { Š } } { 20 }
{ \tl_to_str:n { t } } { 21 }
{ \tl_to_str:n { T } } { 21 }
{ \tl_to_str:n { u } } { 22 }
{ \tl_to_str:n { U } } { 22 }
{ \tl_to_str:n { v } } { 23 }
{ \tl_to_str:n { V } } { 23 }
% { \tl_to_str:n { x } } { }
% { \tl_to_str:n { X } } { }
% { \tl_to_str:n { y } } { }
% { \tl_to_str:n { Y } } { }
{ \tl_to_str:n { z } } { 24 }
{ \tl_to_str:n { Z } } { 24 }
{ \tl_to_str:n { ž } } { 25 }
{ \tl_to_str:n { Ž } } { 25 }
{ \tl_to_str:n { _ } } { 26 }
{ \tl_to_str:n { | } } { 26 }
}
\ExplSyntaxOff
\begin{document}
\namekoda{Žiga Lausegger}
\namekoda{ŽIGA LAUSEGGER}
\namekoda{Marko Milič}
\end{document}
所有引擎的输出都是相同的。
解释
您似乎想要斯洛文尼亚语字母,其中包含 č、š 和 ž(其他常见外语字符如 ć 可能很容易容纳)。
主要问题是带有变音符号的字符在 UTF-8 中不是单个字节,并且pdflatex
通过读取将查看下一个字节的“前缀”来模拟 UTF-8 输入。
对于斯洛文尼亚语,前缀是字节0xC3
、0xC4
和0xC5
。一次检查一个字符是行不通的,所以我们需要一种不同的策略。
主宏的工作原理是将输入转换为字符串表示。然后,它会逐个字符地将其与给定的案例列表进行比较;如果该字符是前缀,则只存储它并读取下一个字符,形成一个双字节序列,并与给定的列表进行比较。
预加载列表的工作方式类似:每个字符被制成一个或两个字节的字符串,并\str_case:nn
准备一个可用作第二个参数的标记列表。
那么,名字会发生什么Žiga
?由它形成的字符串将包含字节
C5 BD 69 67 61
当字符串被映射时,第一个字节将被识别为前缀,因此将其放在一边,并将下一个字节添加到它;然后将构造的标记列表与\str_case:nn
(在变体中\str_case:VV
)进行比较,因此返回数字 25,后跟一个句点。标记25.
存储在用于输出的标记列表中,并检查下一个字符。重复直到结束。
最后,输出的令牌列表被传递。
如果使用 XeLaTeX 或 LuaLaTeX,问题就更简单了,因为在读入文件时 UTF-8 字符会转换为单个实体,因此检查前缀的步骤永远不会发生,但输出仍然是一样的。
答案3
您可以使用\def
递归方式提取名称中的字符来执行此操作:
\documentclass{article}
\usepackage{xstring}
\usepackage[utf8]{inputenc}
\newcommand{\realkoda}[1]{%
\IfEqCase{#1}{%
{a}{1.}%
{b}{2.}%
{c}{3.}%
{č}{4.}%
{d}{5.}%
{e}{6.}%
{f}{7.}%
{g}{8.}%
{h}{9.}%
{i}{10.}%
{j}{11.}%
{k}{12.}%
{l}{13.}%
{m}{14.}%
{n}{15.}%
{o}{16.}%
{p}{17.}%
{r}{18.}%
{s}{19.}%
{š}{20.}%
{t}{21.}%
{u}{22.}%
{v}{23.}%
{z}{24.}%
{ž}{25.}%
{_}{26.}%
{S}{26.}%
% you can add more cases here as desired
}[\PackageError{koda}{Undefined option to koda: #1}{}]%
}%
\makeatletter
\def\runningkoda#1#2@{\ifx#1!\relax\else\realkoda{#1}\ifx#2!\relax\else\runningkoda#2@\fi\fi}
\def\prekoda#1 #2@{\ifx#2\relax\relax\runningkoda#1!@\else\runningkoda#1S#2!@\fi}
\newcommand\koda[1]{\prekoda#1 @}
\makeatother
\begin{document}
Name surname: \koda{name surname}
Name\_surname: \koda{name_surname}
\end{document}
这个想法是,调用 并在末尾\koda
添加\runningkoda
一些零散字符,并使用这些字符来测试它是否位于字符列表的末尾。如果不是,则将 传递给原始宏,现在称为,并将作为 的参数传递给。我们每次都必须给出 ,因为每次使用时都会吞噬前一个。!@
\runningkoda
#1
\koda
\realkoda
#2@
\runningkoda
@
@
\runningkoda
处理名称中的空格有点棘手,但使用相同的思想。我用“预处理”名称,\prekoda
将名称排序为空格前和空格后的位。空格被替换,S
并识别它并将其替换为“代码”26。目前,这只能处理名称中的一个空格。如果有必要,应该/可能可以使用from 来\realkoda
允许多个空格\SplitArgument
解析。
输出如下:
如果您传递一个空字符串,我的宏将会出现错误。