【问题标题】:LaTeX Optional ArgumentsLaTeX 可选参数
【发布时间】:2010-12-21 04:44:59
【问题描述】:

如何在 LaTeX 中创建带有可选参数的命令? 比如:

\newcommand{\sec}[2][]{
    \section*{#1
        \ifsecondargument
            and #2
        \fi}
    }
}

那么,我可以这样称呼它

\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi

【问题讨论】:

标签: latex optional-arguments


【解决方案1】:

您只需要以下内容:

\makeatletter
\def\sec#1{\def\tempa{#1}\futurelet\next\sec@i}% Save first argument
\def\sec@i{\ifx\next\bgroup\expandafter\sec@ii\else\expandafter\sec@end\fi}%Check brace
\def\sec@ii#1{\section*{\tempa\ and #1}}%Two args
\def\sec@end{\section*{\tempa}}%Single args
\makeatother

\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi

【讨论】:

  • 我认为 TeX 理解为参数,命令后第一个“框”的适当计数。这个“盒子”写在花括号中,或者它是一个符号。 IE。 x^2+1x^{2+1} 所以我有问题,你的命令是否测试大括号的存在?是否可以创建 LaTeX 命令\sec 为命令\sec{A}[b,c,d] 生成“A、b、c 和 d”,为\sec{A}[b] and "A" for \sec{A}` 生成“A 和 b”?
  • 您有两个问题。 1)是的,我的命令测试大括号的存在。 2) 是的,可以为\sec{A}[b,c,d]\sec{A}[b]\sec{A} 创建宏。
【解决方案2】:

当我想创建一个命令 \dx 以缩写 \;\mathrm{d}x 时,我遇到了类似的问题(即,在积分的微分之前放置一个额外的空格,并使“d”也直立)。但是我也想让它足够灵活,以将积分变量作为可选参数包含在内。我将以下代码放在序言中。

\usepackage{ifthen}

\newcommand{\dx}[1][]{%
   \ifthenelse{ \equal{#1}{} }
      {\ensuremath{\;\mathrm{d}x}}
      {\ensuremath{\;\mathrm{d}#1}}
}

然后

\begin{document}
   $$\int x\dx$$
   $$\int t\dx[t]$$
\end{document}

\dx with optional argument

【讨论】:

    【解决方案3】:

    来自guide的示例:

    \newcommand{\example}[2][YYY]{Mandatory arg: #2;
                                     Optional arg: #1.}
    
    This defines \example to be a command with two arguments, 
    referred to as #1 and #2 in the {<definition>}--nothing new so far. 
    But by adding a second optional argument to this \newcommand 
    (the [YYY]) the first argument (#1) of the newly defined 
    command \example is made optional with its default value being YYY.
    
    Thus the usage of \example is either:
    
       \example{BBB}
    which prints:
    Mandatory arg: BBB; Optional arg: YYY.
    or:
       \example[XXX]{AAA}
    which prints:
    Mandatory arg: AAA; Optional arg: XXX.
    

    【讨论】:

    • 我认为问题是关于如何确定是否给出了可选参数,而不是提供默认值。
    • 虽然这是真的,但我在寻找提供默认参数的方法时发现了这个问题,所以这个答案对我来说是最有用的。
    【解决方案4】:

    以上所有内容都表明很难在 LaTeX 中创建一个好的、灵活的(或禁止重载的)函数!!! (在我看来,TeX 代码看起来像希腊语)

    好吧,只是为了添加我最近(虽然不是那么灵活)的开发,这是我最近在我的论文文档中使用的,与

    \usepackage{ifthen}  % provides conditonals...
    

    启动命令,“可选”命令默认设置为空白:

    \newcommand {\figHoriz} [4] []  {
    

    然后我让宏设置一个临时变量 \temp{},根据可选参数是否为空而有所不同。这可以扩展到任何传递的参数。

    \ifthenelse { \equal {#1} {} }  %if short caption not specified, use long caption (no slant)
        { \def\temp {\caption[#4]{\textsl{#4}}} }   % if #1 == blank
        { \def\temp {\caption[#1]{\textsl{#4}}} }   % else (not blank)
    

    然后我针对这两种情况使用 \temp{} 变量运行宏。 (这里它只是将短标题设置为等于长标题,如果它不是由用户指定的)。

    \begin{figure}[!]
        \begin{center}
            \includegraphics[width=350 pt]{#3}
            \temp   %see above for caption etc.
            \label{#2}
        \end{center}
    \end{figure}
    }
    

    在这种情况下,我只检查 \newcommand{} 提供的单个“可选”参数。如果你要为 3 个“可选”参数设置它,你仍然需要发送 3 个空白参数...例如。

    \MyCommand {first arg} {} {} {}
    

    这很愚蠢,我知道,但这就是我将要使用 LaTeX 的程度——一旦我开始查看 TeX 代码,它就不是那么有意义了……我确实喜欢 Robertson 先生的 xparse 方法,也许我会试试...

    【讨论】:

    • 我喜欢这种方法。更像“编程”,因此更容易阅读。干得好!
    【解决方案5】:

    这是我的尝试,但它并不完全符合您的规格。未经过全面测试,因此请谨慎。

    \newcount\seccount
    
    \def\sec{%
        \seccount0%
        \let\go\secnext\go
    }
    
    \def\secnext#1{%
        \def\last{#1}%
        \futurelet\next\secparse
    }
    
    \def\secparse{%
        \ifx\next\bgroup
            \let\go\secparseii
        \else
            \let\go\seclast
        \fi
        \go
    }
    
    \def\secparseii#1{%
        \ifnum\seccount>0, \fi
        \advance\seccount1\relax
        \last
        \def\last{#1}%
        \futurelet\next\secparse
    }
    
    \def\seclast{\ifnum\seccount>0{} and \fi\last}%
    
    \sec{a}{b}{c}{d}{e}
    % outputs "a, b, c, d and e"
    
    \sec{a}
    % outputs "a"
    
    \sec{a}{b}
    % outputs "a and b"
    

    【讨论】:

      【解决方案6】:

      创建“可选参数”背后的一般想法是首先定义一个中间命令,该命令向前扫描以检测令牌流中接下来出现的字符,然后插入相关的宏来处理出现的参数合适的。使用通用 TeX 编程可能会非常乏味(尽管并不困难)。 LaTeX 的\@ifnextchar 对这类事情非常有用。

      您问题的最佳答案是使用新的xparse 包。它是 LaTeX3 编程套件的一部分,包含用于定义带有任意可选参数的命令的广泛功能。

      在您的示例中,您有一个 \sec 宏,它接受一个或两个大括号参数。这将使用xparse 来实现,如下所示:

      \documentclass{文章} \使用包{xparse} \开始{文档} \DeclareDocumentCommand\sec{ m g }{% {#1% \IfNoValueF {#2} { 和 #2}% }% } (\sec{你好}) (\sec{你好}{你好}) \结束{文档}

      参数{ m g }定义了\sec的参数; m 表示“强制参数”,g 是“可选的大括号参数”。 \IfNoValue(T)(F) 然后可用于检查第二个参数是否确实存在。有关允许的其他类型的可选参数,请参阅文档。

      【讨论】:

      • 会的!这是行不通的。输出:(Hello and ) (Hello and Hi)
      • 感谢您的反馈,阿列克谢。我怀疑您使用的是旧版本的 xparse;最近在这方面做了很多工作。 TeX Live 2009 刚刚发布 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多