为什么 if 语句中有些宏未定义?

为什么 if 语句中有些宏未定义?

我正在尝试检查一个字符串是否只有一个字符,但遇到了这个问题:LaTeX 抱怨说\StrLeft在比较中需要附加参数:

! Argument of \@secondoftwo has an extra }.
<inserted text> 
                \par 
l.11 \IfStrEq{A}{\StrLeft{AB}{1}}
                                 {True}{False}

然而,第一个却不是这样。

\documentclass[english]{article}
\usepackage[T1]{fontenc}
\usepackage[latin9]{inputenc}
\usepackage{xstring}
\begin{document}

\StrLeft{AB}{1}

\IfStrEq{A}{A}{True}{False}

\IfStrEq{A}{\StrLeft{AB}{1}}{True}{False}

\end{document}

我知道我可以接受额外的第三个输入并设置一个变量,但为什么不能像这样使用它?

答案1

“真正”的原因

\IfStrEq{A}{\StrLeft{AB}{1}}{True}{False}

不起作用的是,它\StrLeft{AB}{1}生成从字符串中提取第一个标记所需的一组指令AB,而不是第一个标记本身,而\IfStrEq需要查看该标记。

此类指令并非仅由“可扩展宏”编写,因为需要执行某些计算,这涉及将值分配给寄存器,因此无法通过 进行评估。这本质上就是为什么所有命令都有一个可选的最后一个参数来存储提取或替换的结果的\IfStrEq原因。xstring

对于您来说,必须使用两步程序:

\StrLeft{AB}{1}[\temp]
\IfStrEq{A}{\temp}{True}{False}

会起作用,因为\IfStrEq通常扩展并且\temp仅包含从字符串中获取的第一个标记AB

答案2

正如 Martin Scharrer 所说,您使用的是不可扩展的构造,因此它们并非在所有情况下都有效,即使避免了错误,您也需要确定是否\def\temp{a}\temp“等于”“a”(因此字符串长度为 1)。 任何一个答案都是合理的,但所需的编码完全不同,具体取决于您要考虑的字符串以及您想要的相等定义。

这是一个简单的可扩展测试,仅使用 TeX 原语,它给出了字符串长度 1 的测试定义:

$ tex one
This is TeX, Version 3.1415926 (Web2C 2010)
(./one.tex
: length 0
a: length 1
abc: longer than 1
abcd: longer than 1
 )
No pages of output.

由。。。生产:

\def\isone#1{\immediate\write20{#1: \xisone#1{}{}\isone}}

\def\xisone#1#2#3\isone{%
   \ifx\relax#1\relax
     length 0%
   \else
   \ifx\relax#2\relax
     length 1%
   \else
     longer than 1%
   \fi
\fi}

\isone{}

\isone{a}

\isone{abc}

\isone{abcd}

\bye

相关内容