我正在尝试测试一个字符子字符串(TeX或LaTeX):
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{fp,stringstrings}
\newcommand*{\mytest}[1]{%
\def\firstChar{\substring{#1}{1}{1}}%
\ifx M\firstChar\textit{M has been recognized}\else\textbf{M has NOT been recognized, firstChar='\firstChar'}\fi
}
\begin{document}\thispagestyle{empty}
Test with Matching: \mytest{Matching}\par
Test with M: \mytest{M}\par
Test with No: \mytest{No}\par
Test with N: \mytest{N}\par
\end{document}
预期结果是“M 已被认可”对于前两次通话。我得到的结果是:
如何使用 ifx 与常量进行比较?
答案1
\ifx
比较以下两个标记的含义没有扩展它们。因此,您要测试令牌是否M
具有与相同的含义,\firstChar
并且它们不具有相同的含义,即使\def\firstChar{M}
已发出,因为M
是一个字符并且\firstChar
是一个宏。
你必须扩展\firstChar
:
\expandafter\ifx\expandafter M\firstChar
但这不适用于字符串提取,因为\firstChar
扩展为提取第一个字符的指令,而不是第一个字符。一个更好(更简单)的测试是
\makeatletter
\def\extract@first#1#2\@nil{#1}
\newcommand*{\mytest}[1]{%
\expandafter\ifx\expandafter M\extract@first#1\@empty\@nil
\textit{M has been recognized}%
\else
\textbf{M has NOT been recognized, firstChar=`\extract@first#1\@empty\@nil'}%
\fi
}
\makeatother
这也适用于空字符串。但是,这不适用于多字节 UTF-8 字符,除非使用 UTF-8 智能引擎(XeLaTeX 或 LuaLaTeX)。使用 UTF-8 更加困难。
完整示例:
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\makeatletter
\def\extract@first#1#2\@nil{#1}
\newcommand*{\mytest}[1]{%
\expandafter\ifx\expandafter M\extract@first#1\@empty\@nil
\textit{M has been recognized}%
\else
\textbf{M has NOT been recognized, firstChar=`\extract@first#1\@empty\@nil'}%
\fi
}
\makeatother
\begin{document}\thispagestyle{empty}
Test with Matching: \mytest{Matching}\par
Test with M: \mytest{M}\par
Test with No: \mytest{No}\par
Test with N: \mytest{N}\par
Test with empty: \mytest{}\par
\end{document}
答案2
如果您希望继续使用stringstrings
,则该\isnextbyte
函数就是您要找的函数。由于\theresult
是一个\edef
'ed 字符串,因此您不想将其用于\ifx
比较,而是\if
。
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{fp,stringstrings}
\newcommand*{\mytest}[1]{%
\isnextbyte[q]{M}{#1}%
\if T\theresult\textit{M has been recognized}\else%
\textbf{M has NOT been recognized. firstChar=\substring{#1}{1}{1}}\fi
}
\begin{document}\thispagestyle{empty}
Test with Matching: \mytest{Matching}\par
Test with M: \mytest{M}\par
Test with No: \mytest{No}\par
Test with N: \mytest{N}\par
\isnextbyte{M}{Matching}
\isnextbyte{M}{M}
\isnextbyte{M}{No}
\isnextbyte{N}{M}
\end{document}
但是,如果您希望逻辑提取第一个字符并进行比较(如 MWE 中所示),则可以这样做。与其尝试将子字符串分配给,不如在安静模式下\def
运行。这不会打印出子字符串,尽管如此,它还是通过 放入中。此时,正确的测试变为。\substring
[q]
\edef
\thestring
\if M\thestring...\else...\fi
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{fp,stringstrings}
\newcommand*{\mytest}[1]{%
\substring[q]{#1}{1}{1}%
\if M\thestring\textit{M has been recognized}\else\textbf{M has NOT been recognized, firstChar='\thestring'}\fi
}
\begin{document}\thispagestyle{empty}
Test with Matching: \mytest{Matching}\par
Test with M: \mytest{M}\par
Test with No: \mytest{No}\par
Test with N: \mytest{N}\par
\end{document}
OP 在评论中正确地指出,如果字符串的第一个字符是,那么这两个测试都可能被欺骗\$
。对于这种可能性,可以调用ifthen
包中的一些语法来进行测试:
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{fp,stringstrings,ifthen}
\newcommand*{\mytest}[1]{%
\substring[q]{#1}{1}{1}%
\ifthenelse{\equal{M}{\thestring}}%
{\textit{M has been recognized}}%
{\textbf{M has NOT been recognized, firstChar='\thestring'}}%
}
\begin{document}\thispagestyle{empty}
Test with Matching: \mytest{Matching}\par
Test with M: \mytest{M}\par
Test with No: \mytest{No}\par
Test with N: \mytest{N}\par
Test with \$N: \mytest{\$N}\par
\end{document}
该包的理念是将操作过的字符串放入\thestring
via\edef
中,以便可以对给定的文本设置连续的操作。例如,在这个 MWE 中,短语“Four score and seven years ago”按顺序执行了以下操作:1) 将“seven”更改为“7”,2) 反转所有字母大小写;3) 将第一个单词旋转到字符串的末尾;4) 吞掉第一个字符。
\documentclass{article}
\usepackage{stringstrings}
\begin{document}
\edef\phrase{Four score and seven years ago}
\convertword[q]{\phrase}{seven}{7}
\changecase[q]{\thestring}
\rotateword[q]{\thestring\ }
\gobblechar[q]{\thestring}
\thestring
\end{document}