我很难理解如何使用各种选项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
也无济于事,因为\Natioanlity
never 的定义与你用来测试它的字符串相同。在某个时候你必须完全扩展它前比较。最简单的方法是\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}