使用 etoolbox 比较字符串

使用 etoolbox 比较字符串

我很难理解如何使用各种选项etoolbox来比较字符串。让我们考虑一下这个 MWE:

\documentclass[11pt, a4paper]{article}

\usepackage{etoolbox}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\newcommand{\Nationality}{%
    \ifcase\value{ContNationality}\or%
        {ita}\or{eng}\or{fra}%
    \fi%
}%

\begin{document}

\expandafter\ifdefstring{\Nationality}{ita}{You are italian}{}%
\expandafter\ifdefstring{\Nationality}{eng}{You are english}{}%
\expandafter\ifdefstring{\Nationality}{fra}{You are french}{}%

\end{document}

根据软件包指南,我之所以这样写,\expandafter是因为\ifdefstrings不会扩展命令的内容。但是,如果我执行这样的代码,无论有没有\expandafter,生成的 pdf 都只会包含一个带有“b”的段落。我不得不说,这是一个相当令人惊讶的结果。

那么,我该如何处理这种情况并让条件按照我想要的方式发挥作用呢?

编辑:

正如您所指出的,我写的\ifvalue应该是\ifcase\value。我的错误。

编辑2:

我没有说明这一点,因为我认为这并不重要:的值\Nationality需要是动态的,因为实际上在我正在处理的主文档中它被调用了 100 次,并且计数器的值总是不同的ContNationality

存在这样的计数器这一事实或多或少是固定的,因为 的值\Nationality需要是随机的,而我使用的是lcg为计数器分配随机值的包。所以,基本上,我给该计数器一个随机值,然后用它来确定 的随机值\Nationality

更大的 MWE 如下。我实施了 Steven B. Segletes 的解决方案 - 我发现它运行完美 - 对我来说它看起来是最用户友好的选项。我看到了 egreg 的解决方案,我确信它有效,但如果我将其复制粘贴到我的文档中,我会收到一长串错误,这可能是因为我没有最新版本的 LaTeX,而且我不知道如何下载它。此外,我想避免使用基于 LaTeX3 的解决方案,因为我真的不了解该语言,我更愿意使用我了解其工作原理的答案,这样我当然可以在需要更改代码行为时使用它们。

\documentclass{article}

\usepackage{etoolbox}
\usepackage[last=2147483647]{lcg}
\usepackage{xifthen}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}
\newcounter{Cycles}
\newcounter{SEED}

\newcommand{\Random}[3]{%
    \providecommand{\NewSeed}{%
        \reinitrand[last=2147483647, seed=\value{SEED}]%
        \rand%
        \setcounter{SEED}{\therand}%
        \typeout{Il seed attualmente è \theSEED}%
    }%
    \reinitrand[first=#1,last=#2,seed=\value{SEED}]%
    \rand%
    \setcounter{#3}{\value{rand}}%
    \NewSeed%
}

\newcommand{\Nationality}{%
    \edef\theNationality{%
        \ifcase\value{ContNationality}%
            \or ita%
            \or eng%
            \or fra%
        \fi%
    }%
}

\begin{document}%
    %
    \rand%
    \setcounter{SEED}{\value{rand}}%
    \setcounter{Cycles}{0}%
    \whiledo{\value{Cycles}<10}{%
        \addtocounter{Cycles}{1}%
        \Random{1}{3}{ContNationality}%
        \Nationality%
        \ifdefstring{\theNationality}{ita}{You are Italian}{}%
        \ifdefstring{\theNationality}{eng}{You are English}{}%
        \ifdefstring{\theNationality}{fra}{You are French}{}%
    \\
    }%  
\end{document}

答案1

David 已经解释了为什么\epandafter是无用的。但第二个会扩展的\Nationality也无济于事,因为\Natioanlitynever 的定义与你用来测试它的字符串相同。在某个时候你必须完全扩展它比较。最简单的方法是\edef \Nationality(除非你不想修复它,但能够在文档中间更改它)。顺便说一句:\ifvalue据我所知没有。我猜你想要\ifcase\value{...}

\documentclass{article}

\usepackage{etoolbox}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\newcommand{\Nationality}{}
\edef\Nationality{%
  \ifcase\value{ContNationality}
  \or ita%
  \or eng%
  \or fra%
  \fi
}

\begin{document}

\ifdefstring{\Nationality}{ita}{You are Italian}{}%
\ifdefstring{\Nationality}{eng}{You are English}{}%
\ifdefstring{\Nationality}{fra}{You are French}{}%

\end{document}

附言:刚刚看到 egreg 已经解释了这些问题。无论如何我都会保留答案,因为它不使用 expl3。

答案2

\expandafter\ifdefstring{\Nationality

将扩展应用于{不扩展的部分,你的意思是

\expandafter\ifdefstring\expandafter{\Nationality

然而这仍然只能扩大\Nationality一步

答案3

你误解了它的\ifdefstring作用。它的第一个参数是一个宏,它的第一级扩展与第二个参数进行比较。 的第一级扩展\Nationality不是字符串,而是整个\ifcase\value...\fi

这是一个基于的可扩展测试expl3

\documentclass[11pt, a4paper]{article}

\usepackage{xparse}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\ExplSyntaxOn
\NewExpandableDocumentCommand{\Nationality}{}
 {
  \int_case:nn { \value{ContNationality} }
   {
    {1}{ita}
    {2}{eng}
    {3}{fra}
   }
 }

\NewExpandableDocumentCommand{\ifdefstringx}{mmmm}
 {
  \str_if_eq_x:nnTF { #1 } { #2 } { #3 } { #4 }
 }
\ExplSyntaxOff

\begin{document}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\setcounter{ContNationality}{1}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\end{document}

在此处输入图片描述

如果您想要基于的解决方案etoolbox,您可以执行以下操作(但与上述解决方案不同,这是不可扩展的)。

\documentclass[11pt, a4paper]{article}

\usepackage{etoolbox}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\newcommand{\Nationality}{%
  \ifcase\value{ContNationality}\or
  ita\or
  eng\or
  fra\fi
}

\makeatletter
\newcommand{\ifdefstringx}[2]{%
  \begingroup
  \edef\x{#1}%
  \ifdefstring{\x}{#2}{\endgroup\@firstoftwo}{\endgroup\@secondoftwo}%
}
\makeatother

\begin{document}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\setcounter{ContNationality}{1}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\end{document}

如果您想要可扩展的文本:

\documentclass[11pt, a4paper]{article}

\usepackage{etoolbox}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\newcommand{\Nationality}{%
  \ifcase\value{ContNationality}\or
  \expandafter\itastring\or
  \expandafter\engstring\or
  \expandafter\frastring\fi
}
\newcommand{\itastring}{ita}
\newcommand{\engstring}{eng}
\newcommand{\frastring}{fra}

\newcommand{\ifdefstringx}[1]{%
  \expandafter\ifstrequal\expandafter{\romannumeral-`Q#1}%
}

\begin{document}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\setcounter{ContNationality}{1}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\end{document}

或者

\documentclass[11pt, a4paper]{article}

\usepackage{pdftexcmds}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\newcommand{\Nationality}{%
  \ifcase\value{ContNationality}\or
  ita\or
  eng\or
  fra\fi
}

\makeatletter
\newcommand{\ifdefstringx}[2]{%
  \ifnum\pdf@strcmp{#1}{#2}=\z@
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
\makeatother

\begin{document}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\setcounter{ContNationality}{1}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\end{document}

相关内容