JavaRush /Курсы /Swift SELF /Интерполяция и форматирование вывода

Интерполяция и форматирование вывода

Swift SELF
7 уровень , 2 лекция
Открыта

1. Углубляемся в интерполяцию

Когда программа что-то сообщает пользователю, она обычно собирает фразу из кусочков: немного текста, какие-то значения переменных, иногда результаты вычислений. В Swift это удобно делать через интерполяцию — вставку значений внутрь строки.

Важно держать простую модель: у вас есть шаблон сообщения, и вы подставляете в него значения, а не «конструируете строку как конструктор LEGO из сотни деталей».

Базовый синтаксис: "\(…)"

Интерполяция в Swift выглядит так: внутри строкового литерала пишем \(выражение). Выражением может быть переменная, число, результат арифметики, даже тернарный оператор — главное, чтобы получился какой-то выводимый результат.

let user = "Alice"
let points = 42

print("User \(user) has \(points) points.") // User Alice has 42 points.

Обратите внимание: вы не делаете String(points) для перевода типа в строку — Swift сам знает, как превратить многие значения в текст для вывода.

Внутри \(…) можно писать выражения

Это удобно, но есть нюанс: если выражение сложное, строка становится трудно читаемой. Начинайте с простого — так проще отлаживать.

let price = 3
let count = 5

print("Total: \(price * count)") // Total: 15

Если выражение становится «простынёй», лучше вынести расчёт в let, а в строку вставить уже готовый результат. Это не «лишний код», это забота о вашем будущем.

Маленькая полезная внутренняя деталь

Если вам интересно, что происходит «под капотом»: интерполяция в Swift — это не магия, а механизм, который компилятор разворачивает в последовательность операций «добавь кусочек текста» и «добавь значение». В стандартной библиотеке это описывается через специальные методы вроде appendInterpolation, которые компилятор использует при сборке строки.

Вам не нужно это запоминать как API, но полезно понимать идею: интерполяция — это правильный, встроенный способ собрать строку из разных значений.

Конкатенация +: когда можно, но лучше не надо

Конкатенация — это «склейка» строк оператором +. Она существует, и иногда её используют, но в реальном коде очень быстро превращается в кашу: вы начинаете вручную расставлять пробелы, добавлять String(...) для чисел, и через пять минут хочется сделать вид, что этого писали не вы.

Интерполяция почти всегда читаемее, потому что в ней сразу видно шаблон сообщения.

let name = "Alice"
let points = 42

let message1 = "User " + name + " has " + String(points) + " points."
print(message1) // User Alice has 42 points.

let message2 = "User \(name) has \(points) points."
print(message2) // User Alice has 42 points.

Во втором варианте меньше шума, меньше шансов забыть пробел, и нет ручного String(points).

Если вы собираете фразу для человека — берите интерполяцию. Конкатенация остаётся как запасной инструмент: например, когда вы уже работаете со строками как с «кирпичиками», а не как с предложениями.

2. Пробелы и пунктуация в шаблонах

Когда вы начинаете активно использовать интерполяцию, внезапно выясняется, что самая частая ошибка новичка — вовсе не синтаксис, а… пробелы. Программа выполняется, компилируется, всё «правильно», но вывод выглядит как будто текст склеили суперклеем: слова прилипли друг к другу, запятые уехали, а пользователь читает это и грустит.

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

Пробелы — это часть шаблона, а не часть значения

Значение name не обязано знать, что вы хотите пробел перед ним. Пробел — это ваша ответственность в строке-шаблоне.

let name = "Bob"

print("Hello,\(name)!")  // Hello,Bob!
print("Hello, \(name)!") // Hello, Bob!

Вторая строка отличается всего одним пробелом, но выглядит как нормальная человеческая фраза.

Пунктуация должна быть «пришита» к правильному месту

Практическое правило: запятая и точка обычно «прилипают» к слову слева, а пробел — стоит после запятой. И если вы пишете шаблон, то и соблюдайте это в шаблоне.

let city = "Paris"
let year = 2026

print("City: \(city), year: \(year).") // City: Paris, year: 2026.

Переносы строк: лучше управлять ими явно

Если вы выводите несколько строк, иногда проще сделать несколько print, а иногда — один print с "\n". Но даже если вы делаете несколько print, всё равно думайте о «форме» вывода: где заголовок, где пустая строка, где данные.

let title = "Report"
let items = 3

print(title)                 // Report
print("Items: \(items)")     // Items: 3
print("---")                 // ---

3. print как мини‑форматтер

Иногда вам не хочется собирать одну длинную строку. Например, вы выводите несколько значений подряд и хотите контролировать, чем они разделяются и как заканчивается вывод.

В Swift print умеет:

  • печатать несколько аргументов за один вызов;
  • настраивать разделитель через separator:;
  • управлять окончанием вывода через terminator:.

Несколько значений и separator:

По умолчанию print ведёт себя так: между аргументами ставит пробел, а в конце печатает перевод строки. Это можно воспринимать как «нормальный человеческий вывод».

Небольшая табличка, чтобы закрепить:

Что настраиваем Параметр print Значение по умолчанию Что означает
Разделитель между аргументами
separator:
" "
Чем разделять print(a, b, c)
Окончание вывода
terminator:
"\n"
Чем закончить вывод (обычно новая строка)

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

let a = 10
let b = 20
let sum = a + b

print("a=", a, "b=", b, "sum=", sum, separator: " ")
// a= 10 b= 20 sum= 30

Да, тут получаются пробелы после = — потому что "a=" и a печатаются как два отдельных аргумента. Если хотите без пробелов, либо меняйте подход (делайте интерполяцию), либо подбирайте separator:.

let a = 10
let b = 20

print("a=\(a)", "b=\(b)", separator: ", ") // a=10, b=20

Здесь мы соединили «ярлык и значение» через интерполяцию, а разделение пар сделали через separator: ", ".

Когда вы хотите, чтобы данные визуально читались как колонки, вертикальная черта — простой и понятный разделитель:

let name = "Bob"
let role = "Reader"
let id = 7

print(name, role, id, separator: " | ") // Bob | Reader | 7

terminator: и вывод в одну строку

Очень частая ситуация в консольных программах: вы хотите напечатать приглашение к вводу, чтобы курсор остался на той же строке. Или хотите вывести «Loading...done» красивым способом.

По умолчанию print всегда завершает строку символом Enter, но terminator: позволяет это изменить.

Приглашение к вводу на той же строке

print("Enter your name: ", terminator: "")
let name = readLine() ?? "Unknown"

print("Hello, \(name)!") // (например) Hello, Alice!

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

«Два print — одна строка»

print("Loading", terminator: "")
print("...", terminator: "")
print("done") // done (и тут перевод строки)

Это выглядит смешно простым, но такой приём часто используется в маленьких CLI‑утилитах: он позволяет «нарастить» одну строку по частям.

4. String(repeating:count:) для линий и отступов

Когда вы делаете вывод красивым, вам хочется рисовать разделители: линии, отступы, рамки, простейшие «прогресс‑бары». И тут новичок обычно делает страшное: начинает считать пробелы глазами и копировать "--------" вручную.

В Swift для повторяющихся фрагментов есть String(repeating:count:).

Отступ как значение

let indent = String(repeating: " ", count: 4)

print("\(indent)Item 1") //     Item 1
print("\(indent)Item 2") //     Item 2

Отступ — это такие же данные, как имя пользователя. Мы создаём его один раз и используем сколько нужно.

Разделительная линия

let line = String(repeating: "-", count: 20)

print(line) // --------------------
print("Menu")
print(line) // --------------------

Читать вывод сразу легче: глаз цепляется за структуру.

Простейший «бар» прогресса

Пока мы не изучаем ничего сложного, но уже можем сделать «визуальный индикатор» в одну строку.

let done = 3
let total = 10

let filled = String(repeating: "#", count: done)
let empty = String(repeating: ".", count: total - done)

print("[\(filled)\(empty)] \(done)/\(total)") // [###.......] 3/10

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

5. Собираем аккуратный вывод мини‑приложения

Сейчас мы сделаем маленькую консольную заготовку, которая похожа на «микро‑CLI»: показывает заголовок, печатает подсказки, читает ввод и отвечает. Никаких сложных структур данных — только аккуратный вывод.

Это важный момент: пользователь судит программу по тому, что он видит. Даже если внутри у вас гениальный алгоритм, но программа пишет enterNameplz, доверия не будет.

Шаг 1: заголовок и приветствие

let appName = "TinyLibrary"
let version = "0.1"

let line = String(repeating: "=", count: 30)

print(line)                              // ==============================
print("\(appName) v\(version)")          // TinyLibrary v0.1
print("Welcome! Type a command below.")  // Welcome! Type a command below.
print(line)                              // ==============================

Обратите внимание на мелочь: "v\(version)" даёт ровно тот формат, который мы хотим видеть. Если бы мы печатали "v" + version, это было бы не трагедией, но интерполяция читается проще.

Шаг 2: приглашение к команде без переноса строки

print("Command: ", terminator: "")
let command = readLine() ?? ""

print("You typed: \"\(command)\"") // You typed: "help"

Здесь мы сделали две «вежливости» сразу: ввод на той же строке и кавычки вокруг команды, чтобы пользователю было видно, что именно он ввёл (иногда это помогает заметить лишний пробел).

Шаг 3: «псевдо‑помощь» в стиле CLI

Пока мы не разбираем команды по частям (это отдельная тема), но мы можем красиво вывести подсказку.

let indent = String(repeating: " ", count: 2)

print("Available commands:")
print("\(indent)help  - show this message")
print("\(indent)exit  - quit the program")

Такие «ровные» отступы создают ощущение аккуратности.

Шаг 4: один print, много значений, контролируем разделитель

Иногда хочется собрать строку как «лог‑сообщение»: уровень, категория, текст. separator: делает это просто и явно.

let level = "INFO"
let category = "CLI"
let message = "Waiting for command"

print("[\(level)]", "[\(category)]", message, separator: " ")
// [INFO] [CLI] Waiting for command

Если захотите, вы можете заменить разделитель на " | " — и стиль станет более «табличным». Главное, что у вас есть контроль.

6. Типичные ошибки

Ошибка №1: “Где мой пробел?” — слипшийся текст из-за неверного шаблона.
Когда вы пишете "Hello,\(name)!", программа честно делает ровно то, что вы попросили: запятая и имя стоят вплотную. Лечится это не «какой-то особой интерполяцией», а дисциплиной шаблона: пробел — это символ, который вы должны поставить сами в нужном месте ("Hello, \(name)!").

Ошибка №2: попытка запихнуть всю логику внутрь \(…).
Swift позволяет вставлять выражения, и это удобно. Но если в интерполяции появляется три тернарных оператора, четыре сложения и одно «на всякий случай умножение» — строка становится нечитаемой. Обычно лучше вынести расчёт в отдельный let с хорошим именем, а в шаблон подставить результат. Вы удивитесь, насколько меньше ошибок начнёте делать.

Ошибка №3: путаница между “разделитель между аргументами” и “разделитель внутри текста”.
separator: работает только между аргументами print(a, b, c). Он не вставляет пробелы «внутрь» аргумента. Поэтому если вы печатаете "a=" и a как разные аргументы, то пробел появится (если separator: — пробел). Если вам нужно a=10 без пробела, проще собрать аргумент через интерполяцию: "a=\(a)".

Ошибка №4: забыли, что terminator: "" отключает перевод строки.
Это одна из тех ошибок, которые выглядят как «почему всё сломалось», хотя на самом деле всё логично: вы сами отменили \n. Если после приглашения к вводу вы вдруг видите, что следующий вывод «прилип» — проверьте, где последний раз вы ставили terminator: "", и добавьте перевод строки там, где он реально нужен.

Ошибка №5: “Нарисую линию руками” и получу пляску дефисов.
Когда вы пишете "----------------------" вручную, вы почти гарантированно где-то ошибётесь (или вам потом понадобится длина 40, и вы начнёте пересчитывать). String(repeating:count:) решает проблему красиво: длина линии становится числом, а не квестом на внимательность.

1
Задача
Swift SELF, 7 уровень, 2 лекция
Недоступна
Приветствие туриста
Приветствие туриста
1
Задача
Swift SELF, 7 уровень, 2 лекция
Недоступна
Чек на рынке
Чек на рынке
1
Задача
Swift SELF, 7 уровень, 2 лекция
Недоступна
Строка лога
Строка лога
1
Задача
Swift SELF, 7 уровень, 2 лекция
Недоступна
Полоска прогресса
Полоска прогресса
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ