如何知道宏是否包含坐标,即是否具有坐标形状num,num
。
我想要做的是知道给定的宏是否\pos
具有坐标的形状(在解析意义上),然后如果它具有坐标,则执行某些操作,如果形状不是坐标,则执行其他操作。例如,我正在寻找一种实现方法:
\pos{0,0}
\ifcoordinate\pos
It is a coordinate
\else
It is not a coordinate
\fi
那么\ifcoordinate
应该怎么做呢?换句话说,我如何知道给定宏的内容是否符合以下序列:number, coma, number
?。
请注意,我想稍后在一些 TikZ 相关代码中使用此验证,因此感谢提供与 TikZ 相关的解决方案。
答案1
这是一个使用包裹xstring
根据@egreg 的例子:
这也产生了
是
否
是
已知的问题:
\IfDecimal
允许小数分隔符为点或逗号。由于我们使用逗号作为两个数字的分隔符,因此第一个坐标可以不是使用逗号作为小数分隔符,但第二个可以。这种不一致是不好的,因此需要一种方法将小数分隔符更改为xtring
句点。
代码:
\documentclass{article}
\usepackage{xstring}
\usepackage{etoolbox}
\newtoggle{wasCoordinate}
\newcommand*{\ifcoordinate}[3]{%
\toggletrue{wasCoordinate}%
\StrBefore{#1}{,}[\StringBeforeComma]
\StrBehind{#1}{,}[\StringBehindComma]
\IfDecimal{\StringBeforeComma}{}{\togglefalse{wasCoordinate}}
\IfDecimal{\StringBehindComma}{}{\togglefalse{wasCoordinate}}
\iftoggle{wasCoordinate}{#2}{#3}
}%
\begin{document}
\def\pos{1.23,1}
\ifcoordinate{\pos}{YES}{NO}
\def\pos{1.23}
\ifcoordinate{\pos}{YES}{NO}
\def\pos{1.23,-1}
\ifcoordinate{\pos}{YES}{NO}
\end{document}
\end{document}
答案2
\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand\ifcoordinate{ m m m }
{
\bool_set_true:N \l_iscoord_bool
\seq_set_split:Nnx \l_tmpa_seq {,} {#1}
\int_compare:nTF { \seq_length:N \l_tmpa_seq = 2 }
{
\seq_map_inline:Nn \l_tmpa_seq
{ \bool_if:NT \l_iscoord_bool { \iscoord_checkfornumber:n { ##1 } } }
}
{ \bool_set_false:N \l_iscoord_bool }
\bool_if:NTF \l_iscoord_bool {#2} {#3}
}
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }
\cs_new:Npn \iscoord_checkfornumber:n #1
{
\regex_match:nnTF {\A \-? \d+ (\.\d+)? \Z}{#1}
{\bool_set_true:N \l_iscoord_bool}
{\bool_set_false:N \l_iscoord_bool}
}
\bool_new:N \l_iscoord_bool
\ExplSyntaxOff
\begin{document}
\def\pos{1.23,1}
\ifcoordinate{\pos}{YES}{NO}
\def\pos{1.23}
\ifcoordinate{\pos}{YES}{NO}
\def\pos{1.23,-1}
\ifcoordinate{\pos}{YES}{NO}
\end{document}
这将打印
是
否
是
重要变更
由于expl3
2012 年夏季对 进行了更改,上述代码中\seq_length:N
的 应替换为\seq_count:N
。以下是新的完整实现。
\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand\ifcoordinate{ m m m }
{
\iscoord_main:nnn { #1 } { #2 } { #3 }
}
\bool_new:N \l__iscoord_iscoord_bool
\seq_new:N \l__iscoord_arg_seq
\cs_new_protected:Npn \iscoord_main:nnn #1 #2 #3
{
\bool_set_true:N \l__iscoord_iscoord_bool
\seq_set_split:Nnx \l__iscoord_arg_seq {,} {#1}
\int_compare:nTF { \seq_count:N \l__iscoord_arg_seq = 2 }
{
\seq_map_inline:Nn \l__iscoord_arg_seq
{ \bool_if:NT \l__iscoord_iscoord_bool { \__iscoord_checkfornumber:n { ##1 } } }
}
{ \bool_set_false:N \l__iscoord_iscoord_bool }
\bool_if:NTF \l__iscoord_iscoord_bool {#2} {#3}
}
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }
\cs_new_protected:Npn \__iscoord_checkfornumber:n #1
{
\regex_match:nnTF {\A \-? \d+ (\.\d+)? \Z}{#1}
{\bool_set_true:N \l__iscoord_iscoord_bool}
{\bool_set_false:N \l__iscoord_iscoord_bool}
}
\ExplSyntaxOff
\begin{document}
\def\pos{1.23,1}
\ifcoordinate{\pos}{YES}{NO}
\def\pos{1.23}
\ifcoordinate{\pos}{YES}{NO}
\def\pos{1.23,-1}
\ifcoordinate{\pos}{YES}{NO}
\end{document}