從 xstring 賦值

從 xstring 賦值

我正在嘗試編寫一些對使用者輸入的基本驗證,該命令\noinsuit採用兩個參數,一個 [0, 13] 中的整數和一個表示花色的字母。

所以我希望\noinsuit{1}{C}既有效又\noinsuit{Q}{C}無效\noinsuit{1}{Q}。這工作正常,但我在使用xstring's\StrLeft{#1}{1}測試第一個字元是否是整數時遇到問題。以下 MWE 正確列印其值,但如果我取消註解測試行,它會拋出

! Undefined control sequence.
\xs_StrLeft__ ...ef \xs_arg_ii {#2}\edef \xs_call 
                                                  {\noexpand \xs_testopt {\n...

我認為擴展有問題。

\documentclass{article}

\usepackage{xparse}
\usepackage{xstring}

\newcommand{\singpl}{bad}
\newcommand{\test}{bad}

\NewDocumentCommand\noinsuit{mm}{%
    \renewcommand{\test}{\StrLeft{#1}{1}}
%   \IfInteger{\test}{\renewcommand{\singpl}{cards}}{[\PackageError{BridgeStyle : \noinsuit}{Invalid integer (#1)}{}]}%
    \IfEqCase{#1}{%
        {1}{\renewcommand{\singpl}{card}}%
    }
    \IfEqCase{#2}{%
        {C}{#1 \singpl{}\quad\test in Clubs}%
        {D}{#1 \singpl{} in Diamonds}%
        {H}{#1 \singpl{} in Hearts}%
        {S}{#1 \singpl{} in Spades}%
    }[\PackageError{BridgeStyle : \noinsuit}{Unknown suit (#2)}{}]%
}%

\begin{document}

\noinsuit{1}{C}

\noinsuit{2}{C}

%    \noinsuit{Q}{H}

%    \noinsuit{3}{Q}

    \end{document}  

答案1

您不能\StrLeft在 的參數內部使用\IfInteger。您正在傳遞建立字串的指令而不是字串。

而是做

  \StrLeft{#1}{1}[\test]
  \IfInteger{\test}
    {\renewcommand{\singpl}{cards}}
    {\PackageError{BridgeStyle : \noinsuit}{Invalid integer (#1)}{}}%

另一方面,您可以透過使用來獲得更多控制expl3

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand\noinsuit{mm}
 {
  \bridgestyle_noinsuit_checknumber:nn { #1 } { #2 }
 }

\cs_new_protected:Nn \bridgestyle_noinsuit_checknumber:nn
 {
  \regex_match:nnTF { \A [0-9]{1,2} \Z } { #1 }
   {% we have one or two digits
    \int_compare:nTF { #1 <= 13 }
     {% the integer is between 0 and 13
      \bridgestyle_noinsuit_checksuit:nn { #1 } { #2 }
     }
     {% error
      \bridgestyle_noinsuit_invalid:nn { integer } { #1 }
     }
   }
   {% invalid input for the integer
    \bridgestyle_noinsuit_invalid:nn { integer } { #1 }
   }
 }

\cs_new_protected:Nn \bridgestyle_noinsuit_checksuit:nn
 {
  \regex_match:nnTF { \A [CDHS] \Z } { #2 }
   {% valid suit
    #1~card\int_compare:nF { #1=1 } {s}~in~\bridgestyle_suit:n { #2 }
   }
   {% invalid suit
    \bridgestyle_noinsuit_invalid:nn { suit } { #2 }
   }
 }

\cs_new:Nn \bridgestyle_suit:n
 {
  \str_case:nn { #1 }
   {
    {C}{Clubs}
    {D}{Diamonds}
    {H}{Hearts}
    {S}{Spades}
   }
 }

\cs_new_protected:Nn \bridgestyle_noinsuit_invalid:nn
 {
  \PackageError{bridgestyle}{(\string\noinsuit)~invalid~#1~(#2)}{}
 }
\ExplSyntaxOff

\begin{document}

\noinsuit{0}{D}

\noinsuit{1}{C}

\noinsuit{2}{C}

\noinsuit{Q}{H}

\noinsuit{3}{Q}

\noinsuit{14}{H}

\end{document}  

控制台輸出是

! Package bridgestyle Error: (\noinsuit) invalid integer (Q).

See the bridgestyle package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.65 \noinsuit{Q}{H}

? 

! Package bridgestyle Error: (\noinsuit) invalid suit (Q).

See the bridgestyle package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.67 \noinsuit{3}{Q}

? 

! Package bridgestyle Error: (\noinsuit) invalid integer (14).

See the bridgestyle package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.69 \noinsuit{14}{H}

? 

列印輸出是

在此輸入影像描述

相關內容