如何定义具有多个可选参数的宏?

如何定义具有多个可选参数的宏?

在我有了一个可以工作的宏之后,我尝试通过使一些参数可选来改进它。不幸的是,这个宏不再起作用。相反,我得到了我无法理解的错误,例如:

LaTeX Warning: Label `####5' multiply defined.
LaTeX Warning: Label `####5' multiply defined.
! LaTeX Error: \fLab undefined.
! Illegal parameter number in definition of \fLab.
! Illegal parameter number in definition of \reserved@a.
! LaTeX Error: \fCap undefined.

...等等。我尝试的最后一个代码如下所示:

%% Graphics figure with caption and label
% [1:placement,] 2:relative width, 3:file name[, 4:caption[, 5:label]]
\newcommand{\figCapLab}[5][htbp]{%
\ifthenelse{\equal{#5}{}}%
{\renewcommand{\fLab}{}}%
{\renewcommand{\fLab}{\label{##5}}}%
\ifthenelse{\equal{#4}{}}%
{\renewcommand{\fCap}{\fLab}}%
{\renewcommand{\fCap}{\caption{\fLab{\small{}##4}}}}%
\begin{figure}[#1]%
\centering%
\begin{minipage}[t]{#2\textwidth}%
\includegraphics[width=\textwidth]{#3}% is width of surrounding minipage
\fCap%
\end{minipage}%
\end{figure}
}
%% Graphics figure with caption
% [1:placement,] 2:relative width, 3:file name, 4:caption
\newcommand{\figCap}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{#4}{}}%
{\figCapLab[#1]{#2}{#3}{#4}{}}%
}
%% Graphics figure with label
% [1:placement,] 2:relative width, 3:file name, 4:label
\newcommand{\figLab}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{}{#4}}%
{\figCapLab[#1]{#2}{#3}{}{#4}}%
}

谁能解释一下哪里出了问题?

喜欢完整示例的人应该添加这个序言:

\documentclass[a4paper,twoside]{report}
\usepackage{german}
\usepackage[latin1]{inputenc}
\usepackage{a4}
\usepackage{amsmath}
\usepackage{url}
\usepackage{graphicx}
\usepackage{ifthen}

...还有这个结语:

\begin{document}
See \ref{foo}.
\figCapLab{0.9}{whatever.pdf}{Caption}{foo}
\end{document}

答案1

当我按照你的模糊指示自己创建一个可编译的示例时,却出现了错误的行为

\documentclass[a4paper,twoside]{report}
\usepackage{german}
\usepackage[latin1]{inputenc}
\usepackage{a4}
\usepackage{amsmath}
\usepackage{url}
\usepackage{graphicx}
\usepackage{ifthen}

%% Graphics figure with caption and label
% [1:placement,] 2:relative width, 3:file name[, 4:caption[, 5:label]]
\newcommand{\figCapLab}[5][htbp]{%
\ifthenelse{\equal{#5}{}}%
{\renewcommand{\fLab}{}}%
{\renewcommand{\fLab}{\label{##5}}}%
\ifthenelse{\equal{#4}{}}%
{\renewcommand{\fCap}{\fLab}}%
{\renewcommand{\fCap}{\caption{\fLab{\small{}##4}}}}%
\begin{figure}[#1]%
\centering%
\begin{minipage}[t]{#2\textwidth}%
\includegraphics[width=\textwidth]{#3}% is width of surrounding minipage
\fCap%
\end{minipage}%
\end{figure}
}
%% Graphics figure with caption
% [1:placement,] 2:relative width, 3:file name, 4:caption
\newcommand{\figCap}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{#4}{}}%
{\figCapLab[#1]{#2}{#3}{#4}{}}%
}
%% Graphics figure with label
% [1:placement,] 2:relative width, 3:file name, 4:label
\newcommand{\figLab}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{}{#4}}%
{\figCapLab[#1]{#2}{#3}{}{#4}}%
}

\begin{document}
See \ref{foo}.
\figCapLab{0.9}{whatever.pdf}{Caption}{foo}
\end{document}

,我没有收到您描述的任何错误,但我收到了:

LaTeX Warning: Reference `foo' on page 1 undefined on input line 43.


! LaTeX Error: \fLab undefined.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}

? 
! Illegal parameter number in definition of \fLab.
<to be read again> 
                   5
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}

? 

! LaTeX Error: \fCap undefined.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}

? 
! Illegal parameter number in definition of \fCap.
<to be read again> 
                   4
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}

? 

LaTeX Warning: File `whatever.pdf' not found on input line 44.


! Package pdftex.def Error: File `whatever.pdf' not found: using draft setting.


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

l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}

? 
! Illegal parameter number in definition of \reserved@a.
<to be read again> 
                   4
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}

? 
! Illegal parameter number in definition of \reserved@a.
<to be read again> 
                   5
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}

? 
! You can't use `macro parameter character #' in restricted horizontal mode.
<argument> ...e : \ignorespaces \fLab {\small {}##
                                                  4}
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}

? 
[1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] (./test.aux)

LaTeX Warning: There were undefined references.

当我这样做的时候:

\documentclass[a4paper,twoside]{report}
\usepackage{german}
\usepackage[latin1]{inputenc}
\usepackage{a4}
\usepackage{amsmath}
\usepackage{url}
\usepackage{graphicx}
\usepackage{ifthen}

% As later \renwecommand is done on these macros, 
% they should be defined: !!!!!!!!!!!!
\newcommand{\fLab}{}
\newcommand{\fCap}{}

%% Graphics figure with caption and label
%  #1: optional: placement
%  #2: non-optional: relative width
%  #3: non-optional: file name
%  #4: non-optional: in case not empty: caption
%  #5: non-optional: in case not empty: label
\newcommand{\figCapLab}[5][htbp]{%
\ifthenelse{\equal{#5}{}}%
{\renewcommand{\fLab}{}}%
{\renewcommand{\fLab}{\label{#5}}}% !!!!Don't double the hash!!!!
\ifthenelse{\equal{#4}{}}%
{\renewcommand{\fCap}{\fLab}}%
{\renewcommand{\fCap}{\caption{\fLab{\small{}#4}}}}% !!!!Don't double the hash!!!!
\begin{figure}[#1]%
\centering
\begin{minipage}[t]{#2\textwidth}%
\includegraphics[width=\textwidth]{#3}% is width of surrounding minipage
\fCap
\end{minipage}%
\end{figure}%%%%%%%
}
%% Graphics figure with caption
% [1:placement,] 2:relative width, 3:file name, 4:caption
\newcommand{\figCap}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{#4}{}}%
{\figCapLab[#1]{#2}{#3}{#4}{}}%
}
%% Graphics figure with label
% [1:placement,] 2:relative width, 3:file name, 4:label
\newcommand{\figLab}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{}{#4}}%
{\figCapLab[#1]{#2}{#3}{}{#4}}%
}

\begin{document}
See \ref{foo}.
\figCapLab{0.9}{example-grid-100x100pt.pdf}{Caption}{foo}
\end{document}

,那么第二次编译时我不会收到任何错误或警告。


顺便说一下1:

我没有随便.pdf在我的系统的 texmf-trees 中。

如果您希望提供处理图像的示例,则可以使用现代 LaTeX 系统为您提供的现成图像:

例如,Martin Scharrer 的MWE 包列出该软件包提供的所有图像。使用当前的 TeX 平台和当前版本的MWE 包,由于图像已集成到 texmf 树和文件名数据库中,因此无需加载包即可使用。

顺便说一下2:

在正常情况下,您可以缩进 TeX 源代码的行以提高可读性。;-) 这是因为当 (La)TeX 开始读取一行输入时,读取装置的状态为状态 N(新行),而在状态 N 中,类别代码 10(空格)的字符将不会被标记为空格标记,但根本不会产生任何标记。

顺便说一下3:

提供可供人们编译的示例以准确重现错误行为是一种很好的做法。能够重现错误行为对于调试产生错误行为的代码非常重要。


Nicola Talbot 博士的创建 LaTeX 最小示例提供了一些指导方针。

还有如何制作“最小示例”来自 texfaq.org,其中还包含一些有关提问的建议的链接。

什么是最小工作示例?Christian Faulhammer 没有使用“最小示例”这一术语,但他使用了“最小工作示例”这一术语,即使对于仅在足以表现出错误行为的意义上起作用的示例。

您可能还对以下问题的答案感兴趣我刚刚被要求写一个最简单的例子,那是什么?

答案2

OP 要求我对这个答案进行一些解释,所以我将在这里添加一些文字。可选参数的标准 LaTeX 机制允许一个可选参数位于强制参数之前。因此,要创建一个提供可选参数、2 个强制参数,然后是 2 个可选参数的语法,需要连续串接 3 个宏,因为请求了 3 个可选参数。

第一个宏吸收了一个可选参数和两个强制参数,然后它必须调用第二个宏,关键是,作为它的最后行动! 第二个宏调用必须是第一个宏的最后一个操作,原因是第二个宏必须吸收可选参数。如果第一个宏中有任何标记位于链中第二个宏调用之后,那么第一个宏中的其他标记将被吸收为参数,而不是预期的参数。

同样,第二个宏必须调用第三个宏作为其最终操作。

一些奇特的亮点:

  1. 如果要在块内部调用连续宏\if,则必须\expandafter在连续宏之前调用,以便连续宏不会尝试吸收\else\fi

  2. 在此特定情况下,最后一个可选参数(标签)仅在指定了标题时才可调用。因此,链中的第二个宏仅在指定了标题时才会调用第三个宏。否则,它将截断序列。

妇女权利委员会:

\documentclass{article}
\usepackage{graphicx}
\newcommand\addtofigtoks[1]{\expandafter\figtoks\expandafter
  {\the\figtoks#1}}
\newtoks\figtoks
\newcommand\figCapLab[3][htbp]{%
  \figtoks{\begin{figure}[#1]}
  \addtofigtoks{\centering}
  \addtofigtoks{\includegraphics[width=#2\textwidth]{#3}}
  \optcap
}
\newcommand\optcap[1][\relax]{%
  \ifx\relax#1\relax
    \addtofigtoks{\end{figure}}
    \the\figtoks
  \else
    \addtofigtoks{\caption{#1}}%
    \expandafter\labelopt
  \fi
}
\newcommand\labelopt[1][\relax]{%
  \ifx\relax#1\relax\else\addtofigtoks{\label{#1}}\fi
  \addtofigtoks{\end{figure}}
  \the\figtoks
}
\begin{document}
\figCapLab{.2}{example-image-a}
\figCapLab{.2}{example-image-b}[My caption]
\figCapLab{.2}{example-image-c}[My caption][fg:label1]
\figCapLab[p]{.2}{example-image}[Other caption][fg:label2]

In figures \ref{fg:label1} and \ref{fg:label2}...
\end{document}

在此处输入图片描述

Ack-shu-ally,我越想越觉得,代币甚至都不需要:

\documentclass{article}
\usepackage{graphicx}
\newcommand\figCapLab[3][htbp]{%
  \begin{figure}[#1]
  \centering
  \includegraphics[width=#2\textwidth]{#3}
  \optcap
}
\newcommand\optcap[1][\relax]{%
  \ifx\relax#1\relax
    \end{figure}
  \else
    \caption{#1}%
    \expandafter\labelopt
  \fi
}
\newcommand\labelopt[1][\relax]{%
  \ifx\relax#1\relax\else\label{#1}\fi
  \end{figure}
}
\begin{document}
\figCapLab{.2}{example-image-a}
\figCapLab{.2}{example-image-b}[My caption]
\figCapLab{.2}{example-image-c}[My caption][fg:label1]
\figCapLab[p]{.2}{example-image}[Other caption][fg:label2]

In figures \ref{fg:label1} and \ref{fg:label2}...
\end{document}

答案3

您可以使用以下方法实现您的目标xparse

在此处输入图片描述

\documentclass{article}

\usepackage{graphicx,xparse}

% \figCapLab
%   [<float spec>]   #1
%   {<width factor>} #2
%   {<image>}        #3
%   [<caption>]      #4
%   [<label>]        #5
\NewDocumentCommand{\figCapLab}{ O{htbp} m m o o }{%
  \begin{figure}[#1]
    \centering
    \includegraphics[width=#2\linewidth]{#3}% Set image at width
    \IfValueT{#4}
      {\caption{#4}\IfValueT{#5}{\label{#5}}}% Set possible \caption and \label
  \end{figure}
}

\begin{document}

\figCapLab{.2}{example-image-a}
\figCapLab{.2}{example-image-b}[My caption]
\figCapLab{.2}{example-image-c}[My caption][fg:label1]
\figCapLab[p]{.2}{example-image}[Other caption][fg:label2]

In figures \ref{fg:label1} and \ref{fg:label2}\ldots

\end{document}

带有默认值的可选参数使用 指定,O{<default>}而没有默认值的可选参数使用o指定。判断是否提供值的条件是使用\IfValueTF{<parameter>}{<true>}{<false>}。还有单数条件\IfValueT\IfValueF,前者在上面已经用过。

上述代码假设空标题(空白的第四个参数)不需要\label(第五个)参数。如果需要,请将 移出\IfValueT{#5}{\label{#5}}分支<true>内部\IfValueT{#4}

\NewDocumentCommand{\figCapLab}{ O{htbp} m m o o }{%
  \begin{figure}[#1]
    \centering
    \includegraphics[width=#2\textwidth]{#3}% Set image at width
    \IfValueT{#4}{\caption{#4}}% Possible \caption
    \IfValueT{#5}{\label{#5}}% Possible \label
  \end{figure}
}

相关内容