obo.dev

SPL1

13 Oct 2022

SPL1

Оператор повторения for

Оператор for предназначен для цикличного выполнения блока кода для каждого элемента некоторой последовательности (Sequence). Т.е. для каждого элемента будет выполнен один и тот же блок кода. Данный оператор принимает на вход любую последовательность (включая коллекции). К примеру, с его помощью можно вывести все символы строки по одному на консоль, или же все элементы некоего диапазона (Range).

Синтаксис


for связанный_параметр in последовательность {
  //тело оператора
}

связанный_параметр - это локальный для тела оператора параметр, которому будет инициализироваться значение очередного элемента последовательности.

последовательность: Sequence - итерируемая последовательность, элементы которой будут доступны в теле оператора, через связанный параметр, по одному.

Примеры работы оператора for


for number in 1...5 {
    print(number)
} 
// В консоль последовательно выведутся числа от 1 до 5


for number in 1..<5 {
    print(number)
}
// В консоль последовательно выведутся числа от 1 до 4

В некоторых случаях может возникнуть задача, когда нет необходимости использовать значения элементов коллекции, например, когда нужно просто трижды вывести некоторое сообщение на консоль. В этом случае для экономии памяти имя связанного параметра можно заменить на нижнее подчеркивание (underscore).


for _ in 1...3 {
    print("Hello World!")
}
// На консоль трижды выведется строка "Hello World!"


for _ in 1... {
    print("Infinite cycle")
}
// На консоль будет бесконечно выводиться строка "Hello World!"


for number in (1...5).reversed() {
    print(number)
}
// На консоль выведутся элементы диапазона в обратном порядке 
// 5, 4, 3, 2, 1


for number in -3...0 {
    print(number)
}
// На консоль последовательно выведутся числа -3, -2, -1, 0

Ключевое слово where в конструкции for-in

Ключевое слово where используется для указания дополнительных условий итерации элементов последовательности. Например, код в теле оператора будет выполняться только в том случае, когда остаток от деления связанного параметра number на 2 будет равен 0 (то есть число чётное).


for number in 1...10 where number % 2 == 0 {
    print(number)
}
// 2, 4, 6, 8, 10

Оператор повторения while и repeat-while

Операторы while и repeat-while позволяют выполнять блок кода до тех пор, пока проверяемое выражение возвращает true

Синтаксис оператора while


while проверяемое_выражение {
   // тело оператора
}

проверяемое_выражение - выражение, при истинности которого выполняется код из тела оператора. Проверяется при каждой итерации цикла.

Пример работы оператора while


var a = 1

while a < 10 {
    print(a)
    a += 1
}
// Результат работы цикла: 1, 2, 3, 4, 5, 6, 7, 8, 9
// Как только переменная "а" равна 10, условие возвращает false

В отличии от while, оператор repeat-while является циклом с постпроверкой условия. Проверка значения выражения происходит в конце итерации. Разница с while заключается в том, что код тела оператора repeat-while выполняется не менее одного раза. То есть даже если условие при первой итерации вернет false, код тела цикла к этому моменту уже будет выполнен.

Синтаксис оператора repeat-while

repeat {
   // тело оператора
} while проверяемое_выражение

проверяемое_выражение - выражение, при истинности которого выполняется код из тела оператора. Проверяется при каждой итерации цикла.

Пример работы оператора repeat-while


var a = 1
repeat {
    a += 1
    print(a)
} while a < 10
// Результат работы цикла: 2, 3, 4, 5, 6, 7, 8, 9, 10

Оператор отложенных действий defer

Оператор defer откладывает выполнение определенного в его теле кода до момента выхода из области видимости, в которой он был использован

Пример работы оператора defer


func someFunction() {
    defer {
        print("action in defer")

        defer {
            print("another action in defer")
        }
    }
    print("action in function")
}
// Порядок вывода на консоли
// action in function
// action in defer
// another action in defer

Оператор continue

Предназначен для перехода к очередной итерации, игнорируя следующий за ним код. Если программа встречает continue, то она незамедлительно переходит к новой итерации.

Пример работы оператора continue


for number in 1...5 {
    if number == 3 || number == 2 {
        continue
    } else {
        print(number)
    }
}
// Вывод на консоли: 1, 4, 5

Оператор break

Предназначен для досрочного завершения работы цикла. При этом весь последующий код в теле цила игнорируется

Пример работы оператора break


for number in 1...5 {
    if number == 3 {
        break
    } else {
        print(number)
    }
}
// Вывод на консоли: 1, 2

Массивы (Array)

Массив - это упорядоченная коллекция однотипных элементов, для доступа к которым используются целочисленные индексы. Каждый элемент массива это пара “индекс-значение”.

Создание массива с помощью литерала


var array: [Int] = [1, 2, 3]
let anotherArray = [1, 2, 3, 4]
var stringArray: [String]
stringArray = ["One", "Two", "Three"]

Инициализация пустого массива


var emptyArray = [String]()
var emptyArray = Array<String>()
var emptyArray: [String] = []

Примеры работы с массивами


for element in stringArray where element != "Two" || element == "Three" {
    print(element)
}
// Вывод на консоли One, Three


for element in array.reversed() {
    print(element)
}
// Вывод элементов массива в обратном порядке


for index in 0..<array.count {
    print(array[index])
}
// 1, 2, 3


print(array[0]) // Печать элемента по индексу 0
print(array.count) // Печать количества элементов в массиве


var reversedArray: [Int] = array.reversed() 
// Метод reversed() возвращает новый массив
// Инициализация переменной reversedArray реверсивным массивом array
print(reversedArray)
// [3, 2, 1]


array.reverse()
// Метод reverse() реверсирует исходный массив
print(array)
// [3, 2, 1]


array.append(4)
// Метод append добавляет элемент в конец массива
print(array)
// [3, 2, 1, 4]


for number in 5...8 {
    array.append(number)
}
// Элементы 5, 6, 7, 8 будут добавлены в конец массива 
print(array)
// [3, 2, 1, 4, 5, 6, 7, 8]


// Слияние массивов и их инициализация переменной array
array += anotherArray 
//array = array + anotherArray
print(array)
// [3, 2, 1, 4, 5, 6, 7, 8, 1, 2, 3, 4]


array.append(contentsOf: anotherArray)
// Меттод append(contentsOf:) добавляет элементы последовательности в конец массива


array[2] = 42
// Замена элемента под индексом 2 на число 42


print(array[array.count - 1])
// Печать последнего элемента в массиве. Последний элемент в массиве на 1 меньше количества элементов массива.

Самостоятельно изучить методы: insert, remove…
https://developer.apple.com/documentation/swift/array

Системы счисления

Swift позволяет записывать числовые литералы в самых популярных системах счисления:

  1. Десятичной
  2. Двоичной
  3. Восьмеричной
  4. Шестнадцатеричной

Десятичная система счисления

Это одна из самых распространённых систем счисления. Именно её мы используем, когда называем цену товара и произносим номер автобуса. В каждом разряде (позиции) может использоваться только одна цифра из диапазона от 0 до 9. Основанием системы является число 10.

Для примера, возьмём число 503. Если бы это число было записано в непозиционной системе, то его значение равнялось 5+0+3 = 8. Но у нас — позиционная система, значит каждую цифру числа необходимо умножить на основание системы, в данном случае число “10”, возведённое в степень, равную номеру разряда. Получается, значение равно 5102 + 0101 + 3*100 = 500+0+3 = 503. Чтобы избежать путаницы при одновременной работе с несколькими системами счисления основание указывается в качестве нижнего индекса. Таким образом, 503 = 50310

Двоичная система счисления

Двоичная позиционная система счисления имеет основание 2 и использует для записи числа 2 символа (цифры): 0 и 1. В каждом разряде допустима только одна цифра — либо 0, либо 1.

Примером может служить число 101. Оно аналогично числу 5 в десятичной системе счисления. Для того, чтобы перевести из 2-й в 10-ю необходимо умножить каждую цифру двоичного числа на основание “2”, возведённое в степень, равную разряду. Таким образом, число 1012 = 122 + 021 + 1*20 = 4+0+1 = 510.

8-битное число может принимать одно из 256 (от 0 до 255) различных значений.


let int8Min = Int8.min // -128
let int8Max = Int8.max // 127
let uint8Min = UInt8.min // 0
let uint8Max = UInt8.max // 255

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


// 0 - 0
// 1 - 1
// 2 - 10
// 3 - 11 = 1*2^1 + 1*2^0 = 2 + 1
// 4 - 100
// 5 - 101
// 6 - 110
// 7 - 111
// 8 - 1000

Восьмеричная система счисления

Имеет основание 8 и использует для записи числа цифры от 0 до 7.

Пример восьмеричного числа: 254. Для перевода в 10-ю систему необходимо каждый разряд исходного числа умножить на 8n, где n — это номер разряда. Получается, что 2548 = 282 + 581 + 4*80 = 128+40+4 = 17210.

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

// 7 - 7
// 8 - 10
// 9 - 11
// 10 - 12
// 11 - 13
// 12 - 14
// 13 - 15
// 14 - 16
// 15 - 17
// 16 - 20
// 17 - 21

Шестнадцатеричная система счисления

Шестнадцатеричная система широко используется в современных компьютерах, например при помощи неё указывается цвет: #FFFFFF — белый цвет. Рассматриваемая система имеет основание 16 и использует для записи числа: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B. C, D, E, F, где буквы равны 10, 11, 12, 13, 14, 15 соответственно.

Пример записи десятичного чисоа в шестнадцатеричной системе:

// 255 = FF = 15*16^1 + 15*16^0
// 26 = 1A = 1*16^1 + 10*16^0

Swift позволяет записывать числовые литералы систем числения с использованием специальных префиксов:


print("\(0b11101)") // префикс 0b для двоичной записи
print("\(0o14)") // префикс 0o для восьмеричной записи
print("\(0xFF)") // префикс 0x для шестнадцатеричной записи

Чтобы перевести целое положительное десятичное число в систему счисления с другим основанием, нужно это число разделить на основание. Полученное частное снова разделить на основание, и дальше до тех пор, пока частное не окажется меньше основания. В результате записать в одну строку последнее частное и все остатки, начиная с последнего.

Пример перевода десятичного числа в двоичную систему:

7 / 2 = 3(1)
3 / 2 = 1(1)
1 (< 2)
7 -> 111

Побитовые операторы

let binaryUint: UInt8 = 0b00001111
let binaryInt: Int8 = 0b00001111

Побитовый оператор NOT


print(binaryUint) 15
print(~binaryUint) 240
print(binaryInt) 15
print(~binaryInt) -16

Побитовый оператор AND


let firstUint: UInt8 =  0b00001111 // 15
let secondUint: UInt8 = 0b00001000 // 8

print(firstUint & secondUint) // 0b00001000

Побитовый оператор OR


print(firstUint | secondUint)
// 0b00001111

Побитовый оператор XOR


print(firstUint ^ secondUint)
// 0b00000111

Типы рекурсивных функций (Recursion):

  • обычная

func recursion(number: Int) {
    if number > 0 {
        recursion(number: number - 1)
        print("Recursion number: \(number)")
    }
}

recursion(number: 2)

\\ "Recursion number: 1"
\\ "Recursion number: 2"

  • хвостовая

func tailRecursion(number: Int) -> Int {
    if number > 0 {
        print("TailRecursion number: \(number)")
        return tailRecursion(number: number - 1)
    } else {
        return 0
    }
}

print(tailRecursion(number: 2))

\\ "TailRecursion number: 2"
\\ "TailRecursion number: 1"
\\ "0"

  • перекрёстная

func recursionOne(number: Int) {
    if number < 0 {
        print("RecursionOne number: \(number)")
        recursionTwo(number: number + 1)
    }
}

func recursionTwo(number: Int) {
    if number < 0 {
        print("RecursionTwo number: \(number)")
        recursionOne(number: number + 1)
    }
}

recursionTwo(number: -2)

\\ "RecursionTwo number: -2"
\\ "RecursionOne number: -1"