字符串比较

字符串比较
\documentclass{article}
\usepackage{xifthen, xstring}

\newcommand{\IfOne}[3]{
   \if\TokenIsIn#1
     #2
   \else
     #3
   \fi
}

\newcommand{\IfTwo}[3]{
\ifthenelse{\equal{\TokenIsIn}{#1}}{#2}{#3}
}

\newcommand{\IfThree}[3]{
\IfBeginWith{\TokenIsIn}{#1}{#2}{#3}
}
\newcommand{\TokenIsIn}{}
\newcommand{\settok}[1]{\global\let\TokenIsIn=#1}

\settok{a}

\begin{document}
\IfOne{a}{Yes}{No}\\
\IfTwo{a}{Yes}{No}\\
\IfThree{a}{Yes}{No}
\end{document}

输出

Yes
No
No

为什么\IfTwo和会\IfThree返回No

答案1

有了\let\TokenIsIn=a,控制序列\TokenIsIn就变成了不可扩展的标记;更准确地说,它变成了“隐式的a”。

测试\if\TokenIsIn a\ifx\TokenIsIn a返回 true,但\ifthenelse以不同的方式进行比较;基本上,\ifthenelse{\equal{X}{Y}}执行以下操作

\edef\first{X}\edef\second{Y}\ifx\first\second

X当 且\TokenIsInY,此测试返回 false a,因为\first\second没有相同的第一级扩展:隐式标记与标记不同。

对于情况来说,\IfBeginWith情况稍微复杂一些,但本质上测试失败,因为类似的操作\edef\first{\TokenIsIn}也会执行,并且\edef\TokenIsIn不是改变成a

\ifthen仅具有\IfBeginWith明确的应该使用令牌。

如果您执行以下三个测试,则返回 true

\newcommand{\settok}[1]{\gdef\TokenIsIn{#1}}

答案2

从另一个角度来看,该stringstrings包非常慢,主要用于正则表达式。但如果你的问题属于这种风格,那么它有一些有用的例程:

\documentclass{article}

\usepackage{stringstrings}

\begin{document}
\def\mystring{dcbadcbadcba}

\findchars{\mystring}{a} a's found in string

Position \whereischar{\mystring}{a} is where the first `a' is found

\testmatchingchar{\mystring}{3}{a}
Character 3 \ifmatchingchar is \else is not \fi an `a'. 

\testmatchingchar{\mystring}{4}{a}
Character 4 \ifmatchingchar is \else is not \fi an `a'. 
\end{document}

在此处输入图片描述

\whereischar我发现宏产生了一些杂散空格

答案3

\IfBeginWith使用此代码(显示\meaning\IfBeginWith

\long macro:->\@ifstar {\let \@xs@assign \@xs@expand@and@detokenize
\@xs@IfBeginWith@@ }{\let \@xs@assign \@xs@expand@and@assign \@xs@IfBeginWith@@

即,它对输入代码进行扩展和去标记化\TokenIsIn,但是\if... 会一直进行扩展直到找到不可扩展的标记,这就是 的情况(至少我认为如此)\global\let\...=#1,它不可扩展并且不能评估为true(或此处为“否”)。

但是,使用\newtoks寄存器并在其中扩展(或更好:使其可扩展)它\TokenIsIn\the\MyToken不能阻止\if...扩展构造。

参见字母 b 的示例输出,它应该No适用于所有宏。

\documentclass{article}
\usepackage{xifthen, xstring}

\newcommand{\IfOne}[3]{%
   \if\TokenIsIn#1
   #2%
   \else
   #3%
   \fi
}

\newcommand{\IfTwo}[3]{%
  \ifthenelse{\equal{\TokenIsIn}{#1}}{#2}{#3}%
}

\newcommand{\IfThree}[3]{%
  \IfBeginWith{\TokenIsIn}{#1}{#2}{#3}%
}

\newcommand{\TokenIsIn}{\the\MyToken}

\newtoks\MyToken

\newcommand{\settok}[1]{\MyToken={#1}}%

\settok{a}


\begin{document}



\IfOne{a}{Yes}{No}

\IfTwo{a}{Yes}{No}

\IfThree{a}{Yes}{No}

\IfOne{b}{Yes}{No}

\IfTwo{b}{Yes}{No}

\IfThree{b}{Yes}{No}


\end{document}

在此处输入图片描述

相关内容