Algorithm2e 关于字母 Q 的问题是什么?

Algorithm2e 关于字母 Q 的问题是什么?

不,说真的。

以下 LaTeX 文档排版没有问题:

\documentclass{article}
\usepackage{algorithm2e}

\begin{document}

\begin{minipage}{\textwidth}
    \begin{algorithm}[H]
        \Begin(F){
        }
    \end{algorithm}
\end{minipage}

\end{document}

我想重点说一下这条\Begin(F)线。以下是我的实验结果:

  1. 如果我用 替换它\Begin(Q),则没有任何问题。

  2. 如果我用 替换它\Begin([x]),仍然没有问题。

  3. 但是,如果我将其替换为\Begin([Q]),就会发生奇怪的事情。我最终得到了一个以 开头的算法beginQ [Q],如下图所示:

    确实是一个非常奇怪的算法

  4. 如果我用 替换它\Begin($[Q]$),pdflatex 就会开始抱怨并且不知道如何排版文档。

  5. 如果我用 pdflatex 替换它\Begin($[x,Q]$)仍然失败。

  6. 如果我用 替换它\Begin($[Q,x,r]$),pdflatex 会生成一个以 开头的算法beginx [Q,x,r]

如果我使用 Q 以外的字母,就不会出现这些问题。到底发生了什么?

编辑:我使用 TeX Live 2013 和最新版本(2013/01/06 v5.00)algorithm2e

答案1

我刚刚看了algorithm2e源代码。您报告的行为可以追溯到名为\ifArgumentEmpty(在 中定义algorithm2e.sty) 的宏的定义,该宏会更改 (或者更确切地说,尝试改变) 大写字母的 catcode Q

\long\def\ifArgumentEmpty#1{\bgroup
    \catcode`\Q=3
    \catcode`\T=3
    \long\def\@tempa##1##2Q##3##4##5T{##4}%
    \xdef\@tempa{\@tempa#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T}%
\egroup\@tempa}

Q如果通过用另一个字符替换所有实例来更改该宏的定义(A在下面的代码中),则问题将出现在该其他字符上,但不再出现在字母 Q 上。

在此处输入图片描述

我对源代码不够熟悉,algorithm2e无法给出比这个更好的解释。您可能应该就此问题与 Q 的维护者联系。

\documentclass{article}
\usepackage{algorithm2e}

\makeatletter
\long\def\ifArgumentEmpty#1{\bgroup
    \catcode`\A=3
    \catcode`\B=3
    \long\def\@tempa##1##2A##3##4##5B{##4}%
    \xdef\@tempa{\@tempa#1AA{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}B}%
\egroup\@tempa}
\makeatother

\begin{document}

\begin{minipage}{\textwidth}
    \begin{algorithm}[H]
        \Begin([A]){
        }
    \end{algorithm}
    \begin{algorithm}[H]
        \Begin([Q]){
        }
    \end{algorithm}
\end{minipage}

\end{document}

答案2

正如 Jubobs 正确诊断的那样,问题出在\ifArgumentEmpty。他应该为查明问题而受到赞扬。以下是对该问题的分析和一些解决方法。

让我们看看\ifArgumentEmpty应该做什么,至少在包作者的意图中。参数被吸收,并定义一个临时宏:

\long\def\@tempa#1#2Q#3#4#5T{#4}

因为我们在定义中,所以变成。然后的参数被#传递给##\ifArgumentEmpty

\xdef\@tempa{\@tempa#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T}

请注意,#1当涉及到时,将是括号内的内容\Begin。因此,让我们看看参数为空或只有空格的情况(空格将被忽略,因为第一个参数是\@tempa无界的)。

如果#1为空,TeX 会认为

\@tempa QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T

因此的第一个参数\@tempaQ,第二个参数为空,第三个参数是\noexpand\@secondoftwo,第四个参数是\noexpand\@firstoftwo;第五个参数为空。

如果#1非空,则它的第一个标记是 的第一个参数\@tempa,其余(可能为零)标记是第二个参数,第三个参数是Q,第四个参数是\noexpand\@secondoftwo,第五个参数是\noexpand\@firstoftwo

所以\@tempa展开后,\noexpand\@firstoftwo在空的情况下保留,\noexpand\@secondoftwo在非空的情况下保留。

理论上,Q和的类别代码的改变T应该确保这些标记不包含在的参数中\ifArgumentEmpty。但在这个代码中,它们具有程序员认为的类别代码 3。类别代码在定义时固定,定义宏时,两个标记是字母。指令\catcode`Q=3\catcode`T=3根本不执行任何操作。

让我们看看当参数为[Q]:TeX 认为

\@tempa [Q]QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T

的第一个参数\@tempa[;第二个参数为空,第三个参数是],第四个参数是Q,第五个参数是 ,直到 为止的其余部分T。因此\@tempa定义为Q,而第二和第三个(明显的)参数\ifArgumentEmpty也保留在输入流中,因为没有\@firstoftwo\@secondoftwo来处理它们。

同样的问题也会出现,只要第二参数的标记\ifArgumentEmptyQ

这是一个正确的定义:

\makeatletter
\begingroup
\catcode`\Q=3
\catcode`\T=3
\long\gdef\ifArgumentEmpty#1{%      
  \long\def\@tempa##1##2Q##3##4##5T{##4}%
  \edef\@tempa{\@tempa#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T}%
  \@tempa
}
\endgroup
\makeatother

宏内部不需要组,也不需要\xdef

请注意,我们必须使用\gdef来定义\ifArgumentEmpty,以便本地化类别代码的变化。

测试例子。

\documentclass{article}
\usepackage{algorithm2e}

\begin{document}

\textbf{Original definition}

Empty: \ifArgumentEmpty{}{Empty}{Non empty}

Spaces: \ifArgumentEmpty{ }{Empty}{Non empty}

ABC: \ifArgumentEmpty{ABC}{Empty}{Non empty}

Q: \ifArgumentEmpty{Q}{Empty}{Non empty}

[Q]: \ifArgumentEmpty{[Q]}{Empty}{Non empty}

\bigskip

\makeatletter
\begingroup
\catcode`\Q=3
\catcode`\T=3
\long\gdef\ifArgumentEmpty#1{%
  \long\def\@tempa##1##2Q##3##4##5T{##4}%
  \edef\@tempa{\@tempa#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T}%
  \@tempa
}
\endgroup
\makeatother

\textbf{Fixed definition}

Empty: \ifArgumentEmpty{}{Empty}{Non empty}

Spaces: \ifArgumentEmpty{ }{Empty}{Non empty}

ABC: \ifArgumentEmpty{ABC}{Empty}{Non empty}

Q: \ifArgumentEmpty{Q}{Empty}{Non empty}

[Q]: \ifArgumentEmpty{[Q]}{Empty}{Non empty}

\end{document}

在此处输入图片描述

请注意,在[Q]原始定义行中,结果正是我所预测的:Q是排版,然后也是EmptyNon empty。这也证明,如果仍然不清楚,Q参数文本中的\@tempa没有类别代码 3。

解决方法

提交错误报告并执行,直到修复发布为止,

\usepackage{algorithm2e}
\makeatletter
\begingroup
\catcode`\Q=3
\catcode`\T=3
\long\gdef\ifArgumentEmpty#1{%      
  \long\def\@tempa##1##2Q##3##4##5T{##4}%
  \long\edef\@tempa{\@tempa#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T}%
  \@tempa
}
\endgroup
\makeatother

一个更简单的解决方法是

\usepackage{algorithm2e}
\usepackage{etoolbox}
\let\ifArgumentEmpty\ifblank

向软件包开发人员建议一个可能更好的修复方法:

\makeatletter
\begingroup
\catcode`\Q=3
\catcode`\T=3
\long\gdef\ALGOCF@argemptyaux#1#2Q#3#4#5T{#4}
\long\gdef\ifArgumentEmpty#1{%
  \begingroup\long\edef\@tempa{\endgroup
    \ALGOCF@argemptyaux#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T%
  }\@tempa
}
\endgroup
\makeatother

辅助宏定义一次即可,因为它总是会得到相同的定义;

\begingroup\edef\@tempa{\endgroup...}\@tempa

技巧,\@tempa只是临时设置,不会污染哈希内存。无需全局定义。

相关内容