在 minipage 或 tabular 中使用“\ifthenelse”并在命令参数中使用“\\”

在 minipage 或 tabular 中使用“\ifthenelse”并在命令参数中使用“\\”
\documentclass[a4paper,12pt]{article}
\usepackage[utf8]{inputenc}
\RequirePackage{ifthen}

\begin{document}

\makeatletter
\newcommand{\coreitem}[3]{%
  \ifthenelse{\equal{#1}{}}{}{#1 \\}%
  \begin{tabular}{l}
    \ifthenelse{\equal{#2}{}}{}{#2 \\}%
    #1
    \begin{minipage}[t]{\textwidth}%
      \ifthenelse{\equal{#3}{}}{}{\\ %
    \raggedright{#3}}
    \end{minipage}
  \end{tabular}
}
\coreitem{one \\ one 2}{two -- two 2}{tres -- tres 2}  % successful
\makeatother

\end{document}

这是第一次尝试使用\coreitem:它\\在第一个参数中涉及一个\ifthenelse测试并且可以很好地编译。

第二次尝试如下:

\coreitem{one \\ one 2}{two \\ two 2}{tres -- tres 2}  % failing

这里唯一的区别是第二个参数中的替换是--with 。它涉及内部测试,并且编译失败。错误如下:\\\ifthenelsetabular

! Argument of \@firstoftwo has an extra }.
<inserted text> 
                 \par 
l.23 ...item{one \\ one 2}{two \\ two 2}{tres -- tres 2}  % failing

第三次尝试:

\coreitem{one \\ one 2}{two -- two 2}{tres \\ tres 2}  % failing

与第一次成功尝试相比,此处的变化是将第三个参数中的替换为--\\\ifthenelse在 内包含minipage,而 本身又在 内tabular。它在编译时失败并产生以下错误:

...
! Use of \@newline doesn't match its definition.
\@ifnextchar ... \reserved@d =#1\def \reserved@a {
                                                  #2}\def \reserved@b {#3}\f...
l.23 ...m{one -- one 2}{two -- two 2}{tres \\ tres 2}

具有相同错误的失败代码的简化版本

\documentclass[a4paper,12pt]{article}
\usepackage[utf8]{inputenc}
\RequirePackage{ifthen}

\begin{document}

\makeatletter
\newcommand{\coreitem}[3]{%
  \ifthenelse{\equal{#1}{}}{}{#1 \\}
  \begin{minipage}[t]{\textwidth}
    \ifthenelse{\equal{#2}{}}{}{#2 \\}
  \end{minipage}
}
\noindent
\coreitem{one \\ one 2}{two \\ two 2}  % error
\makeatother

\end{document}

下面是一段代码,展示了其中一个答案的问题

\MyIfEmptyF\\如果存在的话,即使第一个参数中的引用为空,也会打印其第二个参数:

\documentclass[a4paper,12pt]{article}
\usepackage[utf8]{inputenc}
\NeedsTeXFormat{LaTeX2e}

\begin{document}
\makeatletter
\newcommand{\MyIfEmptyF}[1]{
  \if\relax\detokenize{#1}\relax%
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi}
\makeatother

\makeatletter
\newcommand{\coreitem}[1][2em]{
  \def\coreitem@arg@i{#1}
  \@ifnextchar[{\coreitem@i}{\coreitem@i[{2em}]}
}

\def\coreitem@i[#1]{
  \def\coreitem@arg@ii{#1}
  \@ifnextchar[{\coreitem@ii}{\coreitem@ii[{0.2em}]}
}

\def\coreitem@ii[#1]#2#3{
  \def\coreitem@arg@iii{#1}
  \def\coreitem@arg@iv{#2}
  \def\coreitem@arg@v{#3}
  \coreitem@iii
}

\def\coreitem@iii#1{
  \def\coreitem@arg@vi{#1}
  \begin{tabular}{l}
    \MyIfEmptyF{\coreitem@arg@iv}{
      \coreitem@arg@iv}
    \MyIfEmptyF{\coreitem@arg@vi}{\\}
    \MyIfEmptyF{\coreitem@arg@vi}{\\}
    \coreitem@arg@v
  \end{tabular}
}
\makeatother

\noindent
\coreitem{one -- one 2}{two --- two 2}{}
\end{document}

注意,如果至少有两个连续的满足上述条件 i ,则会出现问题\MyIfEmptyF...。那么打印的数量\\为 n - 1,n 为连续的数量\MyIfEmptyF...

答案1

我认为问题在于tabular单元格的性质。这些单元格是一个环境,因此包含不同表格单元格内容的参数\ifthen失败了。对于参数和来说这是正确的#2,但对于和因为在第一个参数中起作用来说则#3不是。#1\\

请注意,我对上述内容完全没有把握,这只是一个猜测。

但是下面的方法确实有效:

\documentclass[a4paper,12pt]{article}
\usepackage[utf8]{inputenc}

\makeatletter
\newcommand{\MyIfEmptyF}[1]{%
  \if\relax\detokenize{#1}\relax%
    \expandafter\@gobble%
  \else%
    \expandafter\@firstofone%
  \fi}
\makeatother

\newcommand{\CoreItem}[3]{%
  \MyIfEmptyF{#1}{#1\\}%
  \begin{tabular}{l}%
    \MyIfEmptyF{#2}{#2\\}%
    \MyIfEmptyF{#1}{#1\\}%
    \begin{minipage}[t]{\textwidth}%
      \raggedright #3%
    \end{minipage}%
  \end{tabular}}

\begin{document}
\noindent
\CoreItem{one -- one 2}{two -- two 2}{tres -- tres 2}  % successful
\CoreItem{one \\ one 2}{two -- two 2}{tres -- tres 2}  % successful
\CoreItem{one -- one 2}{two \\ two 2}{tres -- tres 2}  % successful
\CoreItem{one -- one 2}{two -- two 2}{tres \\ tres 2}  % successful

\end{document}

答案2

etoolbox 包命令似乎比 ifthen 更强大。这里 \ifstrequal 和 \ifdefempty 似乎可以很好地替代 \ifthenelse。以下示例使用 \ifstrequal。但它似乎不适用于 \myfunc@arg@iv、\myfunc@arg@v 等参数,其中 \ifdefempty 进入该字段。第二个示例使用后者。该示例显示了 \ifdefempty 在表格中的用法,但它甚至可以在表格中的小页面中工作。

简单命令的解决方案:

\documentclass[a4paper,12pt]{article}
\usepackage[utf8]{inputenc}
\RequirePackage{etoolbox}

\begin{document}

\makeatletter
\newcommand{\coreitem}[3]{%
  \ifstrequal{#1}{}{}{#1 \\}
  \begin{minipage}[t]{\textwidth}
    \ifstrequal{#2}{}{}{#2 \\}
  \end{minipage}
}
\noindent
\coreitem{one \\ one 2}{two \\ two 2}  % error
\makeatother

\end{document}

复杂命令的解决方案:

\documentclass[a4paper,12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{etoolbox}

\begin{document}

\makeatletter
\newcommand{\coreitem}[1][2em]{%
  \def\coreitem@arg@i{#1}
  \@ifnextchar[{\coreitem@i}{\coreitem@i[{2em}]}
}

\def\coreitem@i[#1]{%
  \def\coreitem@arg@ii{#1}
  \@ifnextchar[{\coreitem@ii}{\coreitem@ii[{0.2em}]}
}

\def\coreitem@ii[#1]#2#3{%
  \def\coreitem@arg@iii{#1}
  \def\coreitem@arg@iv{#2}
  \def\coreitem@arg@v{#3}
  \coreitem@iii
}

\def\coreitem@iii#1{%
  \def\coreitem@arg@vi{#1}
  \begin{tabular}{l}
    \ifdefempty{\coreitem@arg@iv}{}{%
      \coreitem@arg@iv \\}
    \ifdefempty{\coreitem@arg@vi}{}{\\}
    \ifdefempty{\coreitem@arg@vi}{}{\\}
    \coreitem@arg@v
  \end{tabular}
}
\makeatother

\noindent
\coreitem{one \\ one 2}{two --- two 2}{}
\end{document}

相关内容