如何测试宏是否具有 TikZ 坐标的形状?

如何测试宏是否具有 TikZ 坐标的形状?

如何知道宏是否包含坐标,即是否具有坐标形状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}

这将打印



重要变更

由于expl32012 年夏季对 进行了更改,上述代码中\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}

相关内容