2014-11-28 7 views
3

Я пытался найти совпадение подстроки в строке и получить совпадающую позицию.Метод swift distance() вызывает фатальную ошибку: не может увеличивать endIndex

Я не могу понять, что случилось со следующим кодом:

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 имели действительные значения, метод расстояния() бросил фатальную ошибку.

Если я ошибаюсь в отношении использования расстояния(), какой метод следует использовать для архивирования цели? Любой совет будет полезен. Благодарю.

+0

Для того, чтобы работать, 'distance' нуждается в пусковом и конечном диапазоне от одного и того же контейнера. Вам нужна функция поиска, но Swift не имеет ее в своей библиотеке, которая будет делать то, что вы хотите. –

+0

что вы пытаетесь сделать? получить диапазон подстроки? – kap

ответ

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 рассматривается как «Собрание Character s» в Swift, "゚Д゚" не должно быть подстрока "hello#゚Д゚".

Я думаю, .rangeOfString() использует NSString реализация, которая обрабатывает строку как последовательность unichar. Я не знаю, что это следует рассматривать как ошибку или нет.

+0

Вы правы, «゚» (HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK) - это своего рода комбинирующий символ, а «# ゚» - это расширенный кластер графем. Swift.String.rangeOfString() должен возвращать нуль. –

+0

От вашего ответа, я думаю, я знаю, что я неправильно понял. Я застрял в поиске того, что не так с методом distance(), но забыл, что существуют несовпадения между миром Swift и миром Cocoa. Поэтому, хотя 'rangeOfString' принимает параметры Swift, сам поступает из Cocoa и может опровергнуть политику Swift. Я согласен с вами в том, что если есть некоторые ошибки, это должно быть 'rangeOfString'. И я думаю, что использование чистого NSString может быть обходным путем. – tyeen

+0

Да, в этом случае вы должны использовать 'NSString' и' NSRange'. – rintaro

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 
} 

поиск первого экземпляра col2 последовательности в col1. Если найдено, возвращает индекс начала подпоследовательности. Если не найден, возвращает nil. Если col2 пуст, возвращает startIndex из col1.

Смежные вопросы