与号“&”导致 if-else-fi 失败

与号“&”导致 if-else-fi 失败

我今天遇到了一个很奇怪的问题。

我想用自动生成的数据填充表格。因此,我设计了一个宏,它需要四个参数(其中一个是可选的)。参数 1 和 4 可以为空,因此我\ifx#1\@empty在代码中加入了测试。

这是我的第一个版本的宏:

\newcommand{\admin}[4][]{%
  #2&#3&
  \def\@rzid{#4}\ifx\@rzid\@empty\relax ./. \else \texttt{\@rzid}\fi&
  \def\@ldap{#1}\ifx\@ldap\@empty\relax
    yes
  \else
    & no
  \fi%
  \\%
}

我很惊讶地发现,LaTeX 没有编译。结果如下:

! 额外的 \fi。
\\admin ...ldap @empty \relax yes \else & no \fi
\\
! 不完整 \ifx;第 51 行之后的所有文本均被忽略。
< 插入的文本>
\fi

经过两个小时的折腾,我发现,& 符号才是导致问题的原因。这个宏可以正常工作,并且 LaTeX 不会抛出错误:

\newcommand{\admin}[4][]{%
  #2&#3&
  \def\@rzid{#4}\ifx\@rzid\@empty\relax ./. \else \texttt{\@rzid}\fi&
  \def\@ldap{#1}\ifx\@ldap\@empty\relax
    yes
  \else 
    no
  \fi%
  \\%
}

缺点是,“否”这个词现在站在了错误的列中。:-( 我的 MWA(最小解决方法)现在如下,但我想知道哪里出了问题以及如何避免我想出的额外 if 子句。

\documentclass{article}

\makeatletter
%% This did not work due to the "&".  Removing the ampersand will get
%% the macro working, but than the word "No" from the ifclause will be
%% printed in the wrong column.
% \newcommand{\admin}[4][]{%
%   #2&#3&
%   \def\@rzid{#4}\ifx\@rzid\@empty\relax ./. \else \texttt{\@rzid}\fi&
%   \def\@ldap{#1}\ifx\@ldap\@empty\relax
%     yes
%   %% The error starts here.  Comment out the next two lines, and the
%   %% error vanishes.  Remove the ampersand & and its also gone!
%   \else
%     & no
%   %% This would work
%   % \else 
%   %   no
%   \fi%
%   \\%
% }

%% Now: this works, but you have to have an extra if-clause!
\newcommand{\admin}[4][]{%
  #2&#3&%
  \def\@rzid{#4}\ifx\@rzid\@empty\relax ./. \else \@rzid\fi&%
  \def\@ldap{#1}\ifx\@ldap\@empty\relax
    Yes
  \fi
  &
  \newcommand{\admin}[4][]{%
  #2&#3&%
  \def\@rzid{#4}\ifx\@rzid\@empty\relax ./. \else \@rzid\fi&%
  \def\@ldap{#1}\ifx\@ldap\@empty\relax
    Yes
  \fi
  &
  \ifx\@ldap\@empty\relax\else
    No
  \fi%
  \\%
\def\@ldap{#1}\ifx\@ldap\@empty\relax\else
    No
  \fi%
  \\%
}
\makeatother

\begin{document}
  \begin{tabular}{@{}lllcc@{}}
    \hline
    \multicolumn{2}{@{}c}{Anwender}
    & \multicolumn{1}{c}{RZ-ID}
    & \multicolumn{2}{c@{}}{LDAP} \\
    \multicolumn{1}{@{}c}{Vorname}
    & \multicolumn{1}{c}{Nachname}
    &
    & \multicolumn{1}{c}{Yes}
    & \multicolumn{1}{c@{}}{No} \\
    \hline
    \admin{First}{Lastname}{fl19}
    \admin{Some}{Othername}{so97}
    \admin[false]{Not}{Listed}{}
    \hline
  \end{tabular}
\end{document}

附言:这是一个最小的例子。在我的实际文档中,宏更加复杂,因为我在倒数第二列和最后一列中添加了更多信息。因此,建议使用 \multicolumn{2}{c}{Yes}\multicolumn{2}{c}{NO}跨越最后两列以避免使用“与”符号,这对我来说是行不通的。

答案1

请注意,在您的实际 MWA 中(我喜欢这样!:-D)您将获得

在此处输入图片描述

这可能不是预期的结果。其背后的原因与第一个解决方案失败的原因相同:单元格是组,并且您的单元格\def\@ldap被限制在第四列。您应该改用\gdef来使其正常工作。

我个人认为没有必要不惜\if一切代价避免双重处罚,但这可能是一种可行的方法

\newcommand{\admin}[4][]{%
  #2&#3&%
  \def\@rzid{#4}\ifx\@rzid\@empty\relax ./. \else \@rzid\fi &
  \def\@ldap{#1}%
  \ifx\@ldap\@empty\relax % I prefer \if\relax\detokenize{#1}\relax
     \def\@tempa{\textcolor{green}{\ding{51}}&}%
  \else
     \def\@tempa{&\textcolor{red}{\ding{55}}}%
  \fi
  \@tempa
  \\
}

在此处输入图片描述

基本上,\if只是设定了的定义,只有在解决了\@tempa之后才会进行扩展。\if

答案2

条件语句不能跨越对齐单元格,但您可以在发出之前删除条件&;该技术使用\@firstoftwo\@secondoftwo。请参阅为什么使用 \expandafter\@firstoftwo 习语?

\documentclass{article}

\makeatletter

\newcommand{\admin}[4][]{%
  #2&#3&%
  \if\relax\detokenize{#4}\relax
    ./.%
  \else
    #4%
  \fi&%
  \if\relax\detokenize{#1}\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {Yes}{&No}%
  \\%
}
\makeatother

\begin{document}
  \begin{tabular}{@{}lllcc@{}}
    \hline
    \multicolumn{2}{@{}c}{Anwender}
    & \multicolumn{1}{c}{RZ-ID}
    & \multicolumn{2}{c@{}}{LDAP} \\
    \multicolumn{1}{@{}c}{Vorname}
    & \multicolumn{1}{c}{Nachname}
    &
    & \multicolumn{1}{c}{Yes}
    & \multicolumn{1}{c@{}}{No} \\
    \hline
    \admin{First}{Lastname}{fl19}
    \admin{Some}{Othername}{so97}
    \admin[false]{Not}{Listed}{}
    \hline
  \end{tabular}
\end{document}

我还删除了两个辅助宏,选择使用不同的安全空值测试。

在此处输入图片描述

相关内容