2016-03-27 4 views
1

Я не могу понять, почему я получаю ошибку на второй итерации в цикле. Можете ли вы помочь мне понять, откуда эта проблема?Отрицательный ArraySlice: индекс за пределами допустимого диапазона

let NumTracks = 3 
let TrackBytes = 2 

func readBytes(input: [UInt8]?) { 
    if let input = input { 
     var input = input[0..<input.count] 
     for _ in 0..<NumTracks { 
      print(input[0..<TrackBytes]) // fatal error: Negative ArraySlice index is out of range 
      input = input[TrackBytes..<input.count] 
     } 
    } 
} 
let samples = [UInt8]?([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 
readBytes(samples) 

Существует another test case like this one и нет причин, почему это не происходит сбой, а также.

EDIT

Я не получаю ошибку, когда я использую этот вариант кода (и я до сих пор не знаю, почему):

let NumTracks = 3 
let TrackBytes = 2 

func readBytes(input: [UInt8]?) { 
    if let input = input { 
     var input = input[0..<input.count] 
     for _ in 0..<NumTracks { 
      print(input[input.startIndex..<input.startIndex.advancedBy(2)]) 
      input = input[input.startIndex.advancedBy(2)..<input.endIndex] 
     } 
    } 
} 
let samples = [UInt8]?([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 
readBytes(samples) 

ответ

4

Причина заключается в том, что принимая срез массива сохраняет исходные показатели массива:

let array = [1, 2, 3, 4] 
let slice = array[1 ..< 3] 

print(slice) // [2, 3] 
print(slice.startIndex) // 1 
print(slice.endIndex) // 3 

print(slice[1])   // 2 (the first element of the slice) 
print(slice[0])   // fatal error: Index out of bounds 

в вашем случае, после первого вызова

input = input[TrackBytes..<input.count] 

первый достоверный показатель для input является TrackBytes и не 0 и поэтому следующий вызов

input[0..<TrackBytes] 

вызывает ошибку во время выполнения.

Так startIndex коллекции не обязательно равна нулю, и вы уже нашли решение, еще один

func readBytes(input: [UInt8]?) { 
    if let input = input { 
     var input = input[0..<input.count] 
     for _ in 0..<NumTracks { 
      print([UInt8](input.prefix(TrackBytes))) 
      input = input.suffixFrom(input.startIndex + TrackBytes) 
     } 
    } 
} 

или даже короче, не изменяя локальный срез массива несколько раз:

func readBytes(input: [UInt8]?) { 
    if let input = input { 
     for start in 0.stride(to: NumTracks * TrackBytes, by: TrackBytes) { 
      print([UInt8](input[start ..< start + TrackBytes])) 
     } 
    } 
} 
+0

I должен был проверить индексы. Хорошо знать это и немного неожиданно. Благодаря! – Laurent

+0

Я попробовал другое решение, но оно возвращает неверный результат: [0, 1] [2, 3] [2, 3] – Laurent

+0

Ожидаемое [0, 1] [2, 3] [4, 5] – Laurent

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