Вывод в Rust
Ты уже не раз пользовался println!. На этой странице — другие макросы для вывода, которые тебе встретятся, и когда какой из них выбирать.
println! и print!
Заголовок раздела «println! и print!»println! печатает текст и добавляет в конце перевод строки. print! делает то же самое, но перевод строки не добавляет:
fn main() { print!("Привет, "); print!("мир"); println!("!");}Вывод:
Привет, мир!Заметь: все три вызова напечатали текст в одной строке — на новую переходит только println!. На практике почти всегда используют println!, а print! полезен в основном тогда, когда строка собирается по кусочкам.
Заполнители: {} и имена переменных
Заголовок раздела «Заполнители: {} и имена переменных»Ты уже видел {} в роли заполнителя. Заполнить его можно двумя способами: передать значение после строки или написать имя переменной прямо внутри скобок:
fn main() { let name = "Феррис"; let age = 10;
println!("{} уже {} лет", name, age); // по позиции println!("{name} уже {age} лет"); // прямо в строке (тот же результат)}Вывод:
Феррис уже 10 летФеррис уже 10 летОбе строки печатают одно и то же. Стиль с именем внутри ({name}) появился чуть позже и обычно читается легче, так что по возможности выбирай его.
format! — собрать строку вместо вывода
Заголовок раздела «format! — собрать строку вместо вывода»Иногда отформатированный текст нужен как String, а не сразу на экране — например, чтобы сохранить его или передать в другую функцию. Для этого есть format!. Он работает в точности как println!, только не печатает, а возвращает String:
fn main() { let name = "Феррис"; let message = format!("Привет, {name}!"); println!("{message}");}Вывод:
Привет, Феррис!Отладочный вывод с {:?}
Заголовок раздела «Отладочный вывод с {:?}»Обычный {} работает только со значениями, которые умеют показывать себя как текст: числа, строки, логические значения. Для более сложных значений, вроде кортежей или структур, {} не скомпилируется. Используй вместо него {:?} (отладочный формат, debug):
fn main() { let point = (3, 7); println!("{:?}", point);}Вывод:
(3, 7)Для больших значений есть более красивый многострочный вариант — {:#?} (pretty-print):
fn main() { let point = (3, 7); println!("{:#?}", point);}Вывод:
( 3, 7,)Форматирование чисел
Заголовок раздела «Форматирование чисел»Несколько приёмов форматирования, которые нужны часто:
fn main() { let pi = 3.14159; println!("{:.2}", pi); // 2 знака после точки -> 3.14 println!("{:5}", 42); // дополнить до ширины 5 -> " 42" println!("{:08.2}", pi); // дополнить нулями -> 00003.14}Вывод:
3.14 4200003.14Заучивать это не нужно — просто знай, что такие возможности есть, когда понадобится выровнять числа или округлить дроби.
Выравнивание текста и вывод фигурных скобок
Заголовок раздела «Выравнивание текста и вывод фигурных скобок»Ширина работает и для текста, причём можно выбрать, к какой стороне прижимать значение. После : поставь < (влево), > (вправо) или ^ (по центру), а затем ширину. Перед ними можно указать символ-заполнитель, например -:
fn main() { let coffee = 3.5; let bagel = 2.25;
println!("{:-^20}", " МЕНЮ "); println!("{:<12}{:>8}", "Товар", "Цена"); println!("{:<12}{:>8.2}", "Кофе", coffee); println!("{:<12}{:>8.2}", "Бублик", bagel); println!("{:<12}{:>8.2}", "Итого", coffee + bagel);}Вывод:
------- МЕНЮ -------Товар ЦенаКофе 3.50Бублик 2.25Итого 5.75Разберём {:>8.2} по частям: > — выровнять вправо, 8 — ширина, .2 — два знака после точки. Если выровнять числа вправо, десятичные точки встанут друг под другом — поэтому так делают в чеках и таблицах. Хорошая новость для русского текста: ширина считается в символах, а не в байтах, так что кириллица выравнивается так же ровно, как латиница.
А если нужна настоящая { в выводе? Раз скобки означают «заполнитель», их нужно удвоить: {{ печатает {, а }} печатает }.
fn main() { println!("Множество: {{{}, {}}}", 1, 2);}Вывод:
Множество: {1, 2}Практика
Заголовок раздела «Практика»1. Ценник
Заголовок раздела «1. Ценник»Сохрани товар "Блокнот" и цену 2.5, а затем выведи Блокнот стоит 2.50 ₽. Подсказка: {:.2} округляет до двух знаков после точки и работает прямо в строке: {price:.2}.
Показать решение
fn main() { let item = "Блокнот"; let price = 2.5; println!("{item} стоит {price:.2} ₽");}Вывод:
Блокнот стоит 2.50 ₽2. Собери метку и выведи её двумя способами
Заголовок раздела «2. Собери метку и выведи её двумя способами»С помощью format! собери метку ferris-7 из имени "ferris" и числа 7. Выведи её один раз через {} и один раз через {:?} и найди разницу. Подсказка: format! принимает в точности те же заполнители, что и println!.
Показать решение
fn main() { let name = "ferris"; let id = 7; let label = format!("{name}-{id}");
println!("{label}"); println!("{label:?}");}Вывод:
ferris-7"ferris-7"Отладочный вывод показывает текст в кавычках, так что видно, где он начинается и заканчивается. Это удобно, когда в значении затесались лишние пробелы.
println!печатает с переводом строки,print!— без.{}и{name}— заполнители для значений, которые умеют показывать себя черезDisplay.format!работает какprintln!, но не печатает, а возвращаетString.{:?}(и{:#?}) выводит значения для отладки, включая те, с которыми{}не справляется.{:.2}округляет дроби;<,>и^вместе с шириной выравнивают текст;{{и}}печатают сами скобки.
Проверь себя
Заголовок раздела «Проверь себя»Проверь себя
1. Чем println! отличается от print!?
2. Зачем выводить кортеж через {:?}, а не через {}?
Результат: 0 / 2
Что почитать
Заголовок раздела «Что почитать»std::fmt— документация стандартной библиотеки (на английском): полный список параметров форматирования, включая ширину, заполнитель, выравнивание и точность.- Форматированный вывод — Rust на примерах: примеры позиционных и именованных аргументов, дополнения и выравнивания, которые можно запустить (перевод на русский).
- Debug — Rust на примерах: как работают
{:?}и{:#?}и как их получают твои собственные типы (перевод на русский). println!— документация стандартной библиотеки (на английском): официальный справочник поprintln!со ссылками наprint!иeprintln!.format!— документация стандартной библиотеки (на английском): как собратьStringпо тем же правилам форматирования.