Перейти к содержимому

Практика 2. Практика к лекции 2

Цель: закрепить работу с переменными (var) и константами (let), освоить базовые типы данных Swift (Int, Double, String, Bool, Character, кортежи), разобраться в механизмах вывода типов (type inference) и явного преобразования типов, а также научиться использовать typealias.

Рекомендации по выполнению:

  • Каждое задание оформляйте в отдельном файле (например, task1.swift).
  • Запускайте через swift имя_файла.swift на Linux.
  • Обращайте внимание на ошибки компилятора — они помогают понять строгую систему типов Swift.
  • Там, где просят «объяснить», пишите ответ в комментариях прямо в коде.

A. Разминка — let vs var

  1. Объявите следующие значения, выбрав let или var в зависимости от того, будет ли значение меняться. Обоснуйте выбор в комментарии:
/* let или var? */ username = "Анна" // имя пользователя (не меняется)
/* let или var? */ score = 0 // текущий счёт в игре (меняется)
/* let или var? */ pi = 3.14159 // число Пи (не меняется)
/* let или var? */ currentDate = "2026-02-14" // текущая дата (меняется)
/* let или var? */ maxAttempts = 3 // максимум попыток (не меняется)

Скомпилируйте программу. Затем попробуйте изменить значение каждой константы — запишите в комментарии, какие строки вызывают ошибку и почему.

  1. Вывод типов. Объявите переменные без явного указания типа и определите, какой тип выведет компилятор. Проверьте себя с помощью type(of:):
let a = 42
let b = 3.14
let c = "Hello"
let d = true
let e = 2 + 3.0
print(type(of: a)) // ?
print(type(of: b)) // ?
print(type(of: c)) // ?
print(type(of: d)) // ?
print(type(of: e)) // ?

В комментариях объясните, почему e получает тип Double, а не Int.


B. Преобразование типов

  1. Объявите a: Int = 17 и b: Double = 3.0. Выполните следующие действия:
    • Вычислите Double(a) / b и выведите результат.
    • Вычислите a / Int(b) и выведите результат.
    • Попробуйте написать a / b без преобразования — закомментируйте строку и запишите ошибку компилятора.

Ожидаемый вывод:

Double-деление: 5.666666666666667
Int-деление: 5

В комментарии объясните, почему Swift не выполняет автоматическое приведение типов (в отличие от Python).

  1. Безопасное преобразование строк. Напишите программу, которая пытается преобразовать строки в числа:
let inputs = ["42", "3.14", "hello", "100", ""]
for input in inputs {
if let number = Int(input) {
print("'\(input)' → Int: \(number)")
} else if let number = Double(input) {
print("'\(input)' → Double: \(number)")
} else {
print("'\(input)' → невозможно преобразовать")
}
}

Ожидаемый вывод:

'42' → Int: 42
'3.14' → Double: 3.14
'hello' → невозможно преобразовать
'100' → Int: 100
'' → невозможно преобразовать

В комментарии объясните, чем Int("hello") в Swift безопаснее, чем int("hello") в Python.


C. Строки и символы

  1. Работа со строками. Создайте строку с вашим полным именем и выполните следующие операции:
let fullName = "Иван Петров"
print("Количество символов: \(fullName.count)")
print("Первый символ: \(fullName.first!)")
print("Последний символ: \(fullName.last!)")
print("Верхний регистр: \(fullName.uppercased())")
print("Содержит 'ван': \(fullName.contains("ван"))")

Дополнительно:

  • Разделите строку на имя и фамилию (через split(separator:)).
  • Выведите строку задом наперёд (через String(fullName.reversed())).
  • Проверьте, начинается ли строка с "Ив" и заканчивается ли на "ов".
  1. Символы и Unicode. Создайте массив символов и исследуйте их:
let emoji = "👨‍👩‍👧‍👦"
let cafe = "café"
let simple = "hello"
print("emoji.count = \(emoji.count)") // ?
print("cafe.count = \(cafe.count)") // ?
print("simple.count = \(simple.count)") // ?
print("cafe.utf8.count = \(cafe.utf8.count)")
print("cafe.utf16.count = \(cafe.utf16.count)")

В комментариях объясните, почему count и utf8.count дают разные значения и чем подход Swift к подсчёту символов отличается от len() в Python.


D. Кортежи

  1. Функция minMax. Напишите функцию minMax(array:), возвращающую именованный кортеж (min: Int, max: Int):
func minMax(array: [Int]) -> (min: Int, max: Int) {
// ваш код
}
let result = minMax(array: [3, 1, 7, -2, 5])
print("Мин: \(result.min), макс: \(result.max)")
// Ожидаемый вывод: Мин: -2, макс: 7

Затем напишите функцию stats(array:), возвращающую кортеж (min: Int, max: Int, sum: Int, avg: Double):

30.0
let s = stats(array: [10, 20, 30, 40, 50])
print("Мин: \(s.min), макс: \(s.max), сумма: \(s.sum), среднее: \(s.avg)")
  1. Деструктуризация кортежей. Создайте кортеж с координатами точки и выполните деструктуризацию:
let point = (x: 3.5, y: 7.2, label: "A")
// деструктуризация
let (x, y, label) = point
print("Точка \(label): (\(x), \(y))")
// игнорирование элемента
let (px, py, _) = point
print("Координаты: (\(px), \(py))")

Создайте массив из 3 точек (кортежей) и выведите их, используя цикл for-in с деструктуризацией.


E. Typealias и составные типы

  1. Создайте typealias и используйте его:
typealias Student = (name: String, age: Int, grade: Double)

Напишите:

  • Массив из 5 студентов.
  • Функцию averageGrade(students:), возвращающую средний балл.
  • Функцию bestStudent(students:), возвращающую студента с максимальным баллом.
  • Функцию printReport(students:), выводящую таблицу:
Имя Возраст Балл
──────────────────────────────
Анна Иванова 20 4.80
Пётр Сидоров 21 3.90
...
──────────────────────────────
Средний балл: 4.35
Лучший студент: Анна Иванова (4.80)

F. Мини-проект — «Конвертер единиц»

  1. Создайте программу converter.swift, которая выполняет конвертацию между различными единицами измерения:
typealias Conversion = (value: Double, fromUnit: String, toUnit: String, result: Double)

Программа должна:

  • Определить константы коэффициентов: let kmToMiles = 0.621371, let celsiusToFahrenheit = ... и т.д.
  • Конвертировать:
    • 100 километров → мили
    • 36.6 °C → °F (формула: °F = °C × 9/5 + 32)
    • 75 килограммов → фунты (1 кг ≈ 2.20462 фунта)
    • 1024 байт → килобайты
  • Сохранить результаты в массив [Conversion].
  • Вывести результаты в отформатированном виде:
100.0 км = 62.14 миль
36.6 °C = 97.88 °F
75.0 кг = 165.35 фунтов
1024 байт = 1.0 КБ
  • Использовать let для всех значений, которые не изменяются.

G. Критерии оценивания

  • Корректность компиляции и запуска всех программ на Linux: 0–4 балла
  • Правильный выбор let/var, корректная работа с типами и преобразованиями: 0–4 балла
  • Полнота выполнения заданий (все 10 пунктов): 0–4 балла
  • Оформление кода: комментарии с пояснениями, именование, читаемость: 0–4 балла

Максимум: 16 баллов. Бонус до +2 за задания из раздела «Дополнительно».


H. Дополнительно (по желанию)

  • Добавьте в конвертер чтение пользовательского ввода через readLine() с безопасным преобразованием типа.
  • Реализуйте функцию describe(_ value: Any) -> String, которая возвращает строку с типом и значением переменной (используйте type(of:)).
  • Исследуйте, как ведут себя Int.max, Int.min, Double.infinity, Double.nan — выведите их значения и попробуйте арифметические операции с ними.