我正在嘗試編寫一些對使用者輸入的基本驗證,該命令\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}
?
列印輸出是