\char<number>
是一个 TeX 原语,可生成类别代码为 12 的 ASCII 码字符。但是,与它的许多同类字符、等<number>
不同,它不可扩展。\romannumeral
\number
据我了解,\char
不会查找大写/小写/类别代码表,例如\uppercase
和\lowercase
,所以我很困惑为什么它无法扩展。(我不确定这是否完全相关,但我从我的头脑中记得这是这种情况\upper/lowercase
)
答案1
luatex 和 xetex 提供\Uchar
可扩展的
请注意,tex 在外部字符编码和内部字符代码之间具有内置映射,并且\char
访问后者,因此如果\char
扩展为字符标记并且文件被写出并读回(用于目录等),则行为将不同于当前不可扩展的行为,因为字符将被重新映射(很可能是错误的)
答案2
仅用于附加信息。您可以\echar{number}
通过以下代码定义可扩展pdftex
:
\def\hex#1{\ifcase\numexpr#1\relax 0\or 1\or 2\or 3\or 4%
\or 5\or 6\or 7\or 8\or 9\or a\or b\or c\or d\or e\or f\fi}
\newcount\tmpa \newcount\tmpb
\def\echar{}
\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\xstring{\expandafter\xstringA\string} \def\xstringA#1{}
{\endlinechar=-1
\loop
\edef\tmp{\noexpand\xstring\xstring\\^\string^\hex\tmpb\hex\tmpa}
\scantokens\expandafter{\expandafter\edef\expandafter\tmp\expandafter{\tmp}}
\global\expandafter\addto\expandafter\echar\expandafter{\tmp\noexpand\or}
\advance\tmpa by1\relax
\ifnum\tmpa=16 \tmpa=0 \advance\tmpb by1 \fi
\ifnum\tmpb<16 \repeat
}
\edef\echar #1{\noexpand\ifcase\noexpand\numexpr#1\relax\echar\noexpand\fi}
这段代码创建了\echar
一个宏,大致如下:
\def\echar#1{\ifcase#1^^00\or ^^01\or ^^02\or ... \or ^^fe\or ^^ff\fi}
其中 之间的所有标记\or
都属于 之后 之类的类别\string
。
答案3
大卫卡莱尔已经解释过为什么不\char
应该是可扩展的。
但是,在某些情况下,可扩展版本很方便,并且expl3
具有可用的功能。这是一个纯 TeX 版本(需要 e-TeX 引擎,例如pdftex
、xetex
或luatex
)。
\input expl3-generic
\ExplSyntaxOn
\cs_new:Npn \expchar #1 { \char_generate:nn { #1 } { 12 } }
\cs_new:Npn \xexpchar #1 #2 { \char_generate:nn { #1 } { #2 } }
\ExplSyntaxOff
\edef\test{\expchar{92}}
{\tt\meaning\test}
{\tt\test}
\catcode`/=13 \def/{abc}
\xexpchar{47}{13}
\bye
使用 LaTeX 有一个更好的功能(类别代码可以作为可选参数给出)
\documentclass{article}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\expchar}{O{12}m}
{
\char_generate:nn { #2 } { #1 }
}
\ExplSyntaxOff
\begin{document}
\ttfamily
\edef\test{\expchar{92}}
\meaning\test
\test
\begingroup
\catcode`/=13 \def/{abc}
\edef\test{\expchar[13]{47}}
\meaning\test
\test
\endgroup
\end{document}