请考虑下面的 Unicode 表。Unicode 联盟未定义某些位置,因此在表中显示为空(第二行中的位置 7、8、15 和 16)。我如何检测这些位置并用符号替换字符?
最小:
\documentclass{article}
\usepackage{fontspec}
\newfontfamily\greek{Times New Roman}
\makeatletter
%puts the unicode label (removes last char and adds x)
\def\putunicode@label#1#2;{%
\def\reformat@unicode@string##1{%
\bgroup%
\ttfamily
U+%
\edef\z{}%
\expandafter\@tfor\expandafter\i\expandafter:\expandafter=#2;\do{%
\if\i;x\space
\else\z\fi%
\edef\z{\i}%
}%
\egroup
}%
\makebox[5em]{\reformat@unicode@string{#2}}%
}
\def\putchar@cx#1{%
\char\n$_{\the\r}$
}
\def\urow@cx#1{%
\parindent0pt%
\n=#1%
\r=1%
\expandafter\putunicode@label#1;%
\loop%
\ifnum\n<\numexpr#1+16%
\makebox[2.1em]{\expandafter\putchar@cx{#1}}%
\advance\r by1%
\ifnum\r>16\r=1\relax\else\fi
\advance\n by1%
\repeat
\par
}
\def\typeseturows@cx#1{%
\@for\next:=#1\do{%
\urow@cx\next\vskip3pt}}
\newcommand\unicodetable[2]{%
\par\leavevmode
\bgroup%
\parindent0pt%
\newcount\n%
\newcount\r%
\r=1%
\raggedright%
\@nameuse{#1}%
\r=1%
{\ttfamily\makebox[3.1em]{}}%
\loop%
\ifnum\r<17%
\makebox[2.1em]{\hfill\texttt{\the\r}\hfill}%
\advance\r by1%
\repeat
\vskip3pt
\typeseturows@cx{#2}%
\egroup%
}
\makeatother
\begin{document}
\unicodetable{greek}{"1F00,"1F10,"1F20,"1F60}
\end{document}
答案1
使用\iffontchar
:
\def\putchar@cx#1{%
\iffontchar\font\n
\char\n$_{\the\r}$%
\else
*%
\fi
}
\iffontchar\font<number>
如果字符存在于插槽中,则条件为真<number>
,否则为假。
我还删除了 后面的虚假空格$
,但您的代码中还有其他问题。我将参考您原始代码中的行号。
第 27 行应为
\parindent=0pt
(无尾随%
)第 32 行应该是
\ifnum\n<\numexpr#1+16\relax
第 34 行和第 36 行应为
\advance\r by1
(无尾随%
)或\advance\r by\@ne
第 35 行应该是
\ifnum\r>16 \r=1 \else\fi
第 50 行和第 51 行,应该
\newcount\n
是\newcount\r
外部的定义\unicodetable
。使用\r
并不是一个好的选择。第 52 行和第 55 行应该是
\r=1
(没有尾随%
)第 58 行应为
\ifnum\r<17
(无尾随%
)第 60 行应为
\advance\r by1
(无尾随%
)
我建议删除的字符%
可能会导致不合时宜的扩展。仅当指定的名称取决于宏参数时,才应在宏定义中分配寄存器:在任何调用时,\unicodetable
您都会浪费两个计数器寄存器。