上一篇文章我们了解到了如何在 AHK
中比较字符串,但有一个细节我故意忽略了,也就是如何判断一个字符串是否为空(或者说一个变量是否为空,AHK
中空变量、空字符串和未定义变量是一回事)。按理说这应该是一个很简单的问题,一笔带过即可,无需单独写一篇文章来介绍。对其他语言也许是这样,但
AHK 在这个问题上存在一些麻烦,值得一提。
<h2>常规的字符串判空</h2>
<pre class="lang:autoit decode:true ">a := ""
; 方法一:
; = 也可替换成 ==,因为空字符串无大小写问题,不赘述
if (a = "")
{
; 条件成立
}
; 方法二:
if (a)
{
; 做正常的事情
}
else
{
; 条件成立
}</pre>
方法一就是其他编程语言中的方法,无需过多解释。方法二是一种简化的写法,在多数情况看起来也是正常的,但存在一些特殊情况。
<h2>特殊情况一:数字 0</h2>
在一些特殊情况,方法二存在问题。
如果变量为字符串 "0",或者整数 0,或者浮点数 0.0:
<pre class="lang:autoit decode:true ">a := "0"
; 或者
; a := 0
; 或者
; a := 0.0
; 方法一:
; = 也可替换成 ==,因为空字符串无大小写问题,不赘述
if (a = "")
{
; 条件不成立
}
; 方法二:
if (a)
{
; 做正常的事情
}
else
{
; 条件成立,判断错误
}</pre>
恐怕没有人认为一个长度为一的字符串 "0" 是空字符串。但第二种方法给出了错误的结果。原因是 0 被认为是布尔值 false,而且 AHK
中的字符串和数字并没有那么确切的区别,很多情况可以自动相互转换,直接用 if 判断自然不通过,看来这个简化还是要不得。
<h2>特殊情况二:Object()</h2>
还有一种特殊情况是空对象 Object()。通常来说,我们不应该认为 Object()
是空变量,但某些库的作者可能不严谨,在本应返回空变量的地方返回了
Object()(我印象中遇到过这样的问题,但今天没有复现出来,如果以后发现了再举例)。如果用方法一判断,就可能出问题。
<pre class="lang:autoit decode:true ">a := Object()
; 方法一
; = 也可替换成 ==,因为空字符串无大小写问题,不赘述
if (a = "")
{
; 条件不成立
}
; 方法三
if (StrLen(a) = 0)
{
; 条件成立
}</pre>
方法一认为 Object() 不是空变量,那么继续将 a 传递下去处理,就可能出问题。方法三是调用 StrLen() 函数来检查字符串的长度,它成功发现了这不是一个有效的字符串。
但用 StrLen() 函数判断也存在问题,一个很严重的问题是方法三的耗时要比方法一长一倍以上。因为调用函数需要一些额外开销,在几乎所有语言都是如此。如果这个判断在一个很大的循环里边,额外的开销是很大的。
另外 Object() 是否算空变量或者空字符串,这其实是有争议的。我个人是认为不应该算,但在某些语言中,所有变量类型都是从 Object 类型继承来的,那么就应该算。在用一些库时,还是需要验证一下是否存在 Object() 的问题,以免以后出了问题没有头绪。
<h2>总结</h2>
通常情况,用方法一判断空字符串或者空变量就足够了,简单易懂。在某些特殊情况,可能需要用方法三来判断,但要付出额外的开销。另外本文可能还有一些细节没有提到,我想起来后再补充。
网友评论