Swift distance()方法抛出致命错误:无法递增endIndex

时间:2014-11-28 15:33:49

标签: xcode swift

我试图在字符串中找到子字符串匹配,并获得匹配的位置。

我无法弄清楚以下代码的错误:

let str1 = "hello#゚Д゚"
let cmp = "゚Д゚"
let searchRange = Range(start: str1.startIndex, end: str1.endIndex)
let range = str1.rangeOfString(cmp, options: .allZeros, range: searchRange)

println("\(searchRange), \(range!)") // output: 0..<9, 6..<9

let dis = distance(searchRange.startIndex, range!.startIndex) // fatal error: can not increment endIndex! reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
// let dis = distance(searchRange.startIndex, range!.endIndex) // This will go and output: distance=7

println("distance=\(dis)")

正如评论所建议的那样,虽然range具有有效值,但distance()方法会引发致命错误。

如果我对distance()的使用有误,我应该用什么方法来存档目标?  任何意见将是有益的。感谢。

2 个答案:

答案 0 :(得分:3)

range!.startIndex点在这里:

"hello#゚Д゚"
       ^

但是,在这种情况下,#゚是Swift中的单个字符。

因此,此代码:

for var idx = searchRange.startIndex; idx != range!.startIndex; idx = idx.successor() {
    println("\(idx): \(str1[idx])");
}

打印:

0: h
1: e
2: l
3: l
4: o
5: #゚
7: Д゚
fatal error: Can't form a Character from an empty String
// and emits BAD_INSTRUCTION exception

正如您所看到的,range!.startIndex永远不会与字符边界匹配,for循环会用完字符串。这就是你看到异常的原因。

理论上,由于String在Swift中被视为“Character s的集合”,"゚Д゚"不应该是"hello#゚Д゚"的子字符串。

我认为.rangeOfString()使用NSString实现,将字符串视为unichar的序列。我不知道这应该被认为是一个错误。

答案 1 :(得分:1)

试试这个:

func search<C: CollectionType where C.Generator.Element: Equatable>(col1: C, col2: C) -> C.Index? {
    if col2.startIndex == col2.endIndex {
        return col1.startIndex
    }

    var col1Ind = col1.startIndex
    while col1Ind != col1.endIndex {
        var ind1 = col1Ind
        var ind2 = col2.startIndex
        while col1[ind1] == col2[ind2] {
            ++ind1; ++ind2
            if ind2 == col2.endIndex { return col1Ind }
            if ind1 == col1.endIndex { return nil }
        }
        ++col1Ind
    }
    return nil
}

在col1中搜索col2序列的第一个实例。如果找到,则返回子序列开头的索引。如果未找到,则返回nil。如果col2为空,则返回col1的startIndex。