ifthenelse 相等字符串比较失败

ifthenelse 相等字符串比较失败

我正在尝试修复 www.babs.gmxhome.de 中的 accessibility.sty 包的一些问题

有一个字符串比较的结果总是为假,也就是说,语言代码定义将不会被执行。

\ifthenelse{\equal{#1}{\string german}}{\gdef\LanguageCode{/Lang(DE)}}{}%

现在如果我尝试

\message{#1}
\message{\string german}

编译文档时的输出将是:

德语 德语

我真的很迷茫,为什么#1和字符串german在这里不能与true进行比较...可能是什么原因?

答案1

\ifthenelse测试进行基于 token 的比较。因此,当你这样做时

\documentclass{article}
\usepackage{ifthen}
\newcommand{\foo}[1]{%
  \ifthenelse{\equal{#1}{\string german}}
    {TRUE}
    {FALSE}%
}
\begin{document}

\foo{german}

\end{document}

发生的事情是\string应用于第一个标记在这种情况下,它会看到一个g。比较两个结果,它们是不一样的:一个有一个非字母然后五个字母,第二个有六个字母。这两种情况的排版方式不同:g类别代码 12(“其他”)排版的字形与g类别代码 11(“字母”)排版的字形相同,因此两者看起来相同。

在 TeX 中有多种方法可以进行真正的“字符串”比较。使用现代 TeX 引擎,迄今为止最简单的方法是使用\pdfstrcmp或等效方法:

\documentclass{article}
\usepackage{pdftexcmds}
\makeatletter
\newcommand\foo[1]{%
  \ifnum\pdf@strcmp{\unexpanded{#1}}{german}=0 %
     \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
    {TRUE}
    {FALSE}%
}
\makeatother
\begin{document}

\foo{german}

\end{document}

这确实会进行字符串比较,忽略类别代码。如果你想坚持使用\ifthenelse但可以假设 e-TeX,那么

\documentclass{article}
\usepackage{ifthen}
\newcommand{\foo}[1]{%
  \ifthenelse{\equal{\detokenize{#1}}{\detokenize{german}}}
    {TRUE}
    {FALSE}%
}
\begin{document}

\foo{german}

\end{document}

将作为\detokenize全部的参数变成字符串。

另一种不需要任何传统 TeX 基元的方法是使用类似

\documentclass{article}
\usepackage{pdftexcmds}
\makeatletter
\newcommand\foo[1]{%
  \begingroup
    \def\@tempa{#1}%
    \@onelevel@sanitize\@tempa
    \def\@tempb{german}%
    \@onelevel@sanitize\@tempb
    \ifx\@tempa\@tempb
       \aftergroup\@firstoftwo
    \else
      \aftergroup\@secondoftwo
    \fi
  \endgroup
    {TRUE}
    {FALSE}%
}
\makeatother
\begin{document}

\foo{german}

\end{document}

\@onelevel@sanitize利用将事物转换为字符串的事实。

当然,如果你知道输入是有意义的,那么根本就没有必要使用任何去标记化

\documentclass{article}
\usepackage{ifthen}
\newcommand{\foo}[1]{%
  \ifthenelse{\equal{#1}{german}}
    {TRUE}
    {FALSE}%
}
\begin{document}

\foo{german}

\end{document}

答案2

我想添加另一种简单的方法,在纯 TeX 中进行基于字符串的选择,而无需额外的软件包。它利用 TeX 宏扩展并用于\csname ... \endcsname构建宏名称。

\documentclass[11pt,a4paper]{article}

\makeatletter
% define macros that are executed for every given string
\def\setlang@english{\gdef\LanguageCode{/Lang(EN)}}
\def\setlang@german{\gdef\LanguageCode{/Lang(DE)}}
\def\setlang@dutch{\gdef\LanguageCode{/Lang(NL)}}
\newcommand{\setlang}[1]{
  % call the macro corresponding to argument #1
  \csname setlang@#1\endcsname
}
\makeatother

% test the macro
\begin{document}
  \setlang{english}
  \LanguageCode
  \setlang{dutch}
  \LanguageCode
\end{document}

答案3

另一个选择是使用包etoolbox(与 XeLaTeX 一起使用),这是一个 MWE

\documentclass{article}

\usepackage{etoolbox}

\begin{document}
\renewcommand{\language}{german}
\ifdefstring{\language}{german}{German}{Other}
\\

\renewcommand{\language}{english}
\ifdefstring{\language}{german}{German}{Other}
\end{document}

产生

德语

使用的优点\ifdefstring是,你可以将花括号留空以“执行没有什么

\ifdefstring
{\language}{german}
{German}
{} %% do nothing

相关内容