2

第一次在这里发帖。请随时让我知道我是否应该将其发布到其他地方或其他地方。:)

我在 Google 上搜索了“字符串比较”和“字符串不等式”的变体,但它们的结果毫无用处。我的问题是我正在检查字符串不等式,当一侧为空而另一侧不是时,我得到了令人惊讶的结果。考虑以下演示代码:

TestStr "foo", "foo", "="
TestStr "foo", "bar", "<>"
TestStr Null, "foo", "<>"
TestStr "foo", Null, "<>"

Sub TestStr(left, right, expected)
    ' I actually don't care about this - it's here for reference
    If left = right Then
        WScript.Echo "left = right - expected " & expected
    Else
        WScript.Echo "left <> right - expected " & expected
    End If

    If left <> right Then
        WScript.Echo "left <> right - expected " & expected
    Else
        WScript.Echo "left = right - expected " & expected
    End If
    WScript.Echo ""
End Sub

运行此代码会产生以下输出(“已编码”,因此未格式化):

left = right - expected =
left = right - expected =

left <> right - expected <>
left <> right - expected <>

left <> right - expected <>
left = right - expected <>

left <> right - expected <>
left = right - expected <>

如您所见,当一侧为空而另一侧不为空时,字符串不等式会失败——我目前正在经历这种情况。我知道我可以做下面的事情,但我想知道我是否错过了更简单的方法:

If (left = right) Then
Else
    ' Do inequality stuff here...
End If

[编辑] 关于为什么会发生这种情况,我收到了很好的反馈。谢谢各位!但是,我也对如何避免这种情况感兴趣。

[编辑 2] 我希望的是一种简单的方法来了解字符串何时不同(感谢 Ekkehard.Horner 的建议)。

  • 如果两者都为空,那么人们可能会争辩说它们不一样,但它们对我来说已经足够了。
  • 如果一个为空而另一个不为空,那么它们是不同的——很明显。
  • 如果两者都不为空,那么如果它们完全相同,则它们是相同的——包括区分大小写。

因此,就我的目的而言,“预期”和我的演示代码中实际发生的事情一致就足够了。

4

3 回答 3

1

我认为您错过了VBScript 中比较运算符的基础。Null总是返回比较Null,而不是布尔值(真/假)。

更新:

字符串比较是区分大小写的,但是你的脚本在某些情况下会比较StringNull你的第二个问题是如何简化这个任务,对吧?在这种情况下,编写一个函数是一个好主意。

Function CompStr(sVal1, sVal2)
    CompStr = False
    If VarType(sVal1) <> vbString Then Exit Function
    If VarType(sVal2) <> vbString Then Exit Function
    CompStr = sVal1 = sVal2
End Function
于 2013-05-07T22:02:08.730 回答
1

为了说明 Panayot 的声明 (+1) 并使其易于实验:

  ' vbEmpty         0  Uninitialized (default)
  ' vbNull          1  Contains no valid data
  ' vbInteger       2  Integer subtype
  ' vbLong          3  Long subtype
  ' vbSingle        4  Single subtype
  ' vbDouble        5  Double subtype
  ' vbCurrency      6  Currency subtype
  ' vbDate          7  Date subtype
  ' vbString        8  String subtype
  ' vbObject        9  Object
  ' vbError        10  Error subtype
  ' vbBoolean      11  Boolean subtype
  ' vbVariant      12  Variant (used only for arrays of variants)
  ' vbDataObject   13  Data access object
  ' vbDecimal      14  Decimal subtype
  ' vbByte         17  Byte subtype
  ' vbArray      8192  Array
  Dim aData : aData = Array(Empty, Null, CInt(0), CLng(0), "", "a", Nothing)
  Dim sXfx  : sXfx  = Space(25)
  Dim k     : k     = 0
  Dim i, j
  For i = 0 To UBound(aData)
      For j = 0 To UBound(aData)
          WScript.Echo               _
               Right(1000 + k, 3)     _
             , Right(sXfx & toTypeStr(aData(i)), 25)   _
             , Left(toTypeStr(aData(j))& sXfx, 25)   _
             , compareX(aData(i), aData(j))
          k = k + 1
      Next
  Next

Function toTypeStr(vX)
  Dim aTmp : aTmp = Array(VarType(vX), TypeName(vX), "")
  Select Case aTmp(0)
    Case vbEmpty  : aTmp(2) = "<Empty>"
    Case vbNull   : aTmp(2) = "<Null>"
    Case vbString : aTmp(2) = """" & vX & """"
    Case vbObject : aTmp(2) = "<Object>"
    Case Else     : aTmp(2) = CStr(vX)
  End Select
  toTypeStr = Join(aTmp, ":")
End Function

Function compareX(vLHS, vRHS)
  Dim vEQ
 On Error Resume Next
  vEQ = vLHS = vRHS
  If Err.Number Then compareX = Err.Description : Exit Function : End If
 On Error GoTo 0
  Select Case True
    Case VarType(vEQ) = vbNull
      compareX = toTypeStr(vEQ) & " - can't compare with Null"
    Case VarType(vEQ) <> vbBoolean
      compareX = toTypeStr(vEQ) & " surprise"
    Case vEQ
      compareX = "equal"
    Case Else
      compareX = "not equal"
  End Select
End Function

输出:

000           0:Empty:<Empty> 0:Empty:<Empty>           equal
001           0:Empty:<Empty> 1:Null:<Null>             1:Null:<Null> - can't compare with Null
002           0:Empty:<Empty> 2:Integer:0               equal
003           0:Empty:<Empty> 3:Long:0                  equal
004           0:Empty:<Empty> 8:String:""               equal
005           0:Empty:<Empty> 8:String:"a"              not equal
006           0:Empty:<Empty> 9:Nothing:<Object>        Object variable not set
007             1:Null:<Null> 0:Empty:<Empty>           1:Null:<Null> - can't compare with Null
008             1:Null:<Null> 1:Null:<Null>             1:Null:<Null> - can't compare with Null
009             1:Null:<Null> 2:Integer:0               1:Null:<Null> - can't compare with Null
010             1:Null:<Null> 3:Long:0                  1:Null:<Null> - can't compare with Null
011             1:Null:<Null> 8:String:""               1:Null:<Null> - can't compare with Null
012             1:Null:<Null> 8:String:"a"              1:Null:<Null> - can't compare with Null
013             1:Null:<Null> 9:Nothing:<Object>        Object variable not set
014               2:Integer:0 0:Empty:<Empty>           equal
015               2:Integer:0 1:Null:<Null>             1:Null:<Null> - can't compare with Null
016               2:Integer:0 2:Integer:0               equal
017               2:Integer:0 3:Long:0                  equal
018               2:Integer:0 8:String:""               not equal
019               2:Integer:0 8:String:"a"              not equal
020               2:Integer:0 9:Nothing:<Object>        Object variable not set
021                  3:Long:0 0:Empty:<Empty>           equal
022                  3:Long:0 1:Null:<Null>             1:Null:<Null> - can't compare with Null
023                  3:Long:0 2:Integer:0               equal
024                  3:Long:0 3:Long:0                  equal
025                  3:Long:0 8:String:""               not equal
026                  3:Long:0 8:String:"a"              not equal
027                  3:Long:0 9:Nothing:<Object>        Object variable not set
028               8:String:"" 0:Empty:<Empty>           equal
029               8:String:"" 1:Null:<Null>             1:Null:<Null> - can't compare with Null
030               8:String:"" 2:Integer:0               not equal
031               8:String:"" 3:Long:0                  not equal
032               8:String:"" 8:String:""               equal
033               8:String:"" 8:String:"a"              not equal
034               8:String:"" 9:Nothing:<Object>        Object variable not set
035              8:String:"a" 0:Empty:<Empty>           not equal
036              8:String:"a" 1:Null:<Null>             1:Null:<Null> - can't compare with Null
037              8:String:"a" 2:Integer:0               not equal
038              8:String:"a" 3:Long:0                  not equal
039              8:String:"a" 8:String:""               not equal
040              8:String:"a" 8:String:"a"              equal
041              8:String:"a" 9:Nothing:<Object>        Object variable not set
042        9:Nothing:<Object> 0:Empty:<Empty>           Object variable not set
043        9:Nothing:<Object> 1:Null:<Null>             Object variable not set
044        9:Nothing:<Object> 2:Integer:0               Object variable not set
045        9:Nothing:<Object> 3:Long:0                  Object variable not set
046        9:Nothing:<Object> 8:String:""               Object variable not set
047        9:Nothing:<Object> 8:String:"a"              Object variable not set
048        9:Nothing:<Object> 9:Nothing:<Object>        Object variable not set

从#001 和#007-#013 可以看出,应用于 Null 值的操作(此处:=)的结果始终为 Null。

更新:

对于特殊情况(仅限 Null 或字符串,两者 Null 被视为相等):

  Dim aData : aData = Array(Null, "", "a")
  Dim sXfx  : sXfx  = Space(25)
  Dim k     : k     = 0
  Dim i, j
  For i = 0 To UBound(aData)
      For j = 0 To UBound(aData)
          WScript.Echo               _
               Right(1000 + k, 3)     _
             , Right(sXfx & toTypeStr(aData(i)), 25)   _
             , Left(toTypeStr(aData(j))& sXfx, 25)   _
             , CStr(compareStrNull(aData(i), aData(j)))
          k = k + 1
      Next
  Next

Function compareStrNull(vLHS, vRHS)
  Dim ntLHS : ntLHS = VarType(vLHS)
  Dim ntRHS : ntRHS = VarType(vRHS)
  Select Case True
'   If both are null, then one could argue that they aren't the same, but they're same enough for me.
    Case ntLHS = ntRHS And ntLHS = vbNull
      compareStrNull = True
'   If one is null and the other is not, then they're different - pretty obviously.
    Case ntLHS = vbNull Or ntRHS = vbNull
      compareStrNull = False
'   If both are not null, then they are the same if they're the exactly the same - including case sensitivity.
    Case ntLHS = ntRHS And ntLHS = vbString
      compareStrNull = vLHS = vRHS
    Case Else
      Err.Raise 4711, "compareStrNull", "surprise"
  End Select
End Function

输出:

000             1:Null:<Null> 1:Null:<Null>             True
001             1:Null:<Null> 8:String:""               False
002             1:Null:<Null> 8:String:"a"              False
003               8:String:"" 1:Null:<Null>             False
004               8:String:"" 8:String:""               True
005               8:String:"" 8:String:"a"              False
006              8:String:"a" 1:Null:<Null>             False
007              8:String:"a" 8:String:""               False
008              8:String:"a" 8:String:"a"              True

更新二:

比较功能的简化/优化版本:

Function compareStrNull02(vLHS, vRHS)
  compareStrNull02 = vLHS = vRHS                      ' native compare
  If VarType(compareStrNull02) = vbNull Then          ' at least one param is Null
     compareStrNull02 = VarType(vLHS) = VarType(vRHS) ' are both Null?
  End If
End Function

处理数组或对象需要进一步的工作。

于 2013-05-07T22:23:17.207 回答
-1

尝试将其添加为第一行:

如果 isnull (left) 或 isnull (right) 然后退出 sub

于 2013-05-07T22:25:12.203 回答