如何定义具有两个可选参数的命令?

如何定义具有两个可选参数的命令?

我想要一个可以接受 1、2 或 3 个参数的命令,并且针对每个参数数量执行不同的操作。

\c{a}       -> C_a
\c{a}{b}    -> C_{a}^{[b]}
\c{a}{b}{c} -> C_{a,c}^{[b]}

由于 Latex 没有命令重载,我认为可选参数就足够了:

\c{a}       -> C_a
\c[b]{a}    -> C_{a}^{[b]}
\c[c][b]{a} -> C_{a,c}^{[b]}

我找到这个很好的答案使用xparse可能正是我需要的。但是他的答案仅适用于 2 个可选参数。他提到了如何将其扩展到任意数量的参数,但我不知道该怎么做。我试过:

\usepackage{xparse}
....
\DeclareDocumentCommand \c { o o m } {%
  \IfNoValueTF {#1} {%
    \IfNoValueTF {#2} {%
      C_{#3}%
     }{%
      C_{#3}^{[#2]}%
  }%
  }{%
    C_{#2, #3}^{[#1]}%
  }% 
}

$\c{a} \c[b]{a} \c[c][b]{a}$ 

但似乎我无法让带有两个参数的分支起作用:

在此处输入图片描述

我究竟做错了什么?

答案1

您应该从检查开始#2而不是开始#1,因为#2只有有才会有值#1

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand \C { o o m } {%
  \IfNoValueTF{#2}
   {%
    \IfNoValueTF {#1}
     {%
      C_{#3}%
     }
     {%
      C_{#3}^{[#1]}%
     }%
   }
   {%
    C_{#3, #1}^{[#2]}%
   }% 
}

\begin{document}

$\C{a} \quad \C[b]{a} \quad \C[c][b]{a}$ 

\end{document}

用来\DeclareDocumentCommand覆盖的含义\c:当你必须引用某些名字中带有“ç”的法国或土耳其作家时,你会后悔的。

在此处输入图片描述

答案2

您希望定义一个宏\c。但\c已经在 LaTeX 中定义。
因此,我今后将不再将该宏称为\c
相反,我将将该宏称为\macroc


您是否知道在 TeX/LaTeX 中由单个标记组成的未限定参数不需要嵌套在括号中?

定义后\newcommand\foo[1]{This is argument 1: #1.}
\foo{b}将产生与相同的结果
\foo b

定义之后\newcommand\bar[2]{This is argument 1: #1. This is argument 2: #2.},以下调用都会产生相同的结果:
\bar{a}{b}
\bar a{b}
\bar {a}b
\bar ab
\bar{a} {b}
\bar a {b}
\bar {a} b
\bar a b

这是因为

  1. 当未限定的参数由单个标记组成时,不需要括号。
  2. (La)TeX 确实会丢弃未限定参数前面的空格标记。

当被调用时 \macroc{a}{b}c——如何\macroc“知道”用户是否打算使用c\macroc单个标记组成的第三个参数c,或者用户是否打算\macroc仅使用两个参数进行调用,即{a}{b}而不应c被视为第三个参数?

形势很不明朗。

\macroc你可以通过只处理一个未限定的参数并\macroc检查该参数是否属于其中一种模式,从而将情况变得明确

{⟨argument 1⟩}

{⟨argument 1⟩}{⟨argument 2⟩}

{⟨argument 1⟩}{⟨argument 2⟩}{⟨argument 3⟩}

\macroc如果检测到其中一种模式,则采取相应行动,\macroc否则发出错误消息。

IE,

\macroc{{⟨argument 1⟩}}

\macroc{{⟨argument 1⟩}{⟨argument 2⟩}}

\macroc{{⟨argument 1⟩}{⟨argument 2⟩}{⟨argument 3⟩}}


通过下面的例子,\macroc处理一个未限定的参数。

句法:\macroc{⟨argument⟩}

如有⟨argument⟩模式{⟨argument 1⟩}
\macrocatonearg{⟨argument 1⟩}将会执行。

如有⟨argument⟩模式{⟨argument 1⟩}{⟨argument 2⟩}\macrocattwoargs{⟨argument 1⟩}{⟨argument 2⟩}将会执行。

如有⟨argument⟩模式{⟨argument 1⟩}{⟨argument 2⟩}{⟨argument 3⟩}\macrocatthreeargs{⟨argument 1⟩}{⟨argument 2⟩}{⟨argument 3⟩}将会执行。

在所有其他情况下,错误消息都会通知用户有关语法错误。

因此你可以这样做,例如:

\macroc{{a}}

\macroc{{a}{b}}

\macroc{{a}{b}{c}}

\documentclass{article}

\makeatletter
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo,
%%    \UD@gobble, \UD@gobbletwo, \UD@gobblethree
%%    \UD@CheckWhetherNull, \UD@CheckWhetherBrace,
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@gobble[1]{}%
\newcommand\UD@gobbletwo[2]{}%
\newcommand\UD@gobblethree[3]{}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% \UD@CheckWhetherBrace{<Argument which is to be checked>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has leading
%%                        catcode-1-token>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has no leading
%%                        catcode-1-token>}%
\newcommand\UD@CheckWhetherBrace[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\expandafter{\expandafter{%
  \string#1.}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@firstoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}%
}%
%%=============================================================================
%% \macroc for processing one argument within which
%%  you may have one or two or three brace-nested arguments:
%%-----------------------------------------------------------------------------
\newcommand\macrocatonearg[1]{C_#1}%
\newcommand\macrocattwoargs[2]{C_{#1}^{[#2]}}%
\newcommand\macrocatthreeargs[3]{C_{#1,#3}^{[#2]}}%
\newcommand\macrocatsyntaxerror{%
  \@latex@error{Incorrect Syntax}{Specify either one or two or three arguments that are nested in braces.}%
}%
\newcommand\macroc[1]{%
   \UD@CheckWhetherBrace{#1}{%
      \expandafter\UD@CheckWhetherNull\expandafter{\UD@gobble#1}{%
         \macrocatonearg#1%
      }{%
        \expandafter\UD@CheckWhetherBrace\expandafter{\UD@gobble#1}{%
          \expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletwo#1}{%
            \macrocattwoargs#1%
          }{%
            \expandafter\UD@CheckWhetherBrace\expandafter{\UD@gobbletwo#1}{%
               \expandafter\UD@CheckWhetherNull\expandafter{\UD@gobblethree#1}{%
                 \macrocatthreeargs#1%
               }{\macrocatsyntaxerror}%
            }{\macrocatsyntaxerror}%
          }%
        }{\macrocatsyntaxerror}%
      }%
   }{\macrocatsyntaxerror}%
}%
\makeatother
\begin{document}

\verb|$\macroc{{a}}$|: $\macroc{{a}}$ \bigskip

\verb|$\macroc{{a}{b}}$|: $\macroc{{a}{b}}$ \bigskip

\verb|$\macroc{{a}{b}{c}}$|: $\macroc{{a}{b}{c}}$ \bigskip

% Syntax-errors:
% 
% $\macroc{{a}{b}{c}{d}}$
%
% $\macroc{ {a}}$
% 
% $\macroc{{a} {b}}$
%
% $\macroc{a}$
%
% $\macroc{}$

\end{document}

在此处输入图片描述

相关内容