我正在尝试对一个命令编写一些对用户输入的基本验证\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}
?
打印输出为