Kotlin как ввести число с клавиатуры

Обновлено: 02.07.2024

Министский Котин Глава 15. Операции ввода-вывода в файле Kotlin File, регулярные выражения и многопоточность

Нажмите здесь>Купить в торговом центре Jingdong

Нажмите здесь>Покупайте и читайте на Tmall

Мы чувствуем себя очень удобно при использовании файлового ввода-вывода Groovy. Тот же Kotlin также имеет хороший API для операций ввода-вывода файлов. Точно так же некоторые полезные расширения возможностей регулярных выражений Java были сделаны в Kotlin. А многопоточность в Kotlin в основном заключает в себе многопоточность API Java. Поскольку эти Java уже имеют много базовых API, Kotlin не повторил саму реализацию, но сделал практические расширения функций на основе Java.

В этой главе мы представим операции ввода-вывода файла Kotlin, регулярные выражения и многопоточность.

15.1 Введение в Kotlin IO

Все операции ввода-вывода Kotlin выполняются в пакете kotlin.io. Принцип Kotlin заключается в том, что в Java он уже есть. Если его легко использовать, используйте его напрямую. Если он плохой или нет, используйте оригинальный класс для его расширения. Например, Kotlin написал функции расширения для класса File. Это та же идея, что и в расширенном API Groovy.

15.2 Терминал ввода-вывода

Длинный оператор вывода Java System.out.println () продолжается до настоящего времени! Та же самая работа может быть сделана в C ++ с простым cout <<. Конечно, при необходимости мы можем напрямую инкапсулировать System.out.println () в проекте как простой метод печати.

В Kotlin все очень просто. Вам нужно использовать только две глобальные функции println или print. Нам не нужны длинные префиксы. Конечно, если мы очень ностальгируем, мы просто хотим использовать System.out.println (), Kotlin все еще поддерживает это напрямую (бесшовная совместимость с Java).

Функция println Kotlin реализована следующим образом

Конечно, Kotlin только инкапсулирует System.out.println ().

Чтение данных из терминала также очень просто: самый основной метод - глобальная функция readLine, которая читает строку непосредственно из терминала в виде строки. Если вам нужна дополнительная обработка, вы можете использовать различные функции обработки строк, предоставляемые Kotlin, для обработки и преобразования строк.

Класс Kotlin, который инкапсулирует терминальный ввод-вывод, находится в исходном файле stdlib / src / kotlin / io / Console.kt.

15.3 Операции ввода-вывода файла

Kotlin предоставляет множество полезных функций расширения для java.io.File. Эти функции расширения в основном находятся в следующих трех исходных файлах:

kotlin/io/files/FileTreeWalk.kt
kotlin/io/files/Utils.kt
kotlin/io/FileReadWrite.kt

В то же время, Kotlin также сделал простые расширения для InputStream, OutputStream и Reader. В основном они находятся в следующих двух исходных файлах:

kotlin/io/IOStreams.kt
kotlin/io/ReadWrite.kt

Сериализация Колтина напрямую использует псевдоним типа класса сериализации Java:

Давайте кратко представим операции чтения и записи файла Kotlin.

15.3.1 Чтение файлов

Прочитать все содержимое файла

Если мы просто читаем файл, мы можем использовать метод readText (), который напрямую возвращает все содержимое файла. Пример кода выглядит следующим образом

Мы напрямую используем объект File для вызова функции readText, чтобы получить все содержимое файла, которое возвращает строку. Если вы указываете кодировку символов, вы можете указать ее, передав параметр Charset.

Если мы хотим получить содержимое каждой строки файла, мы можем просто передать split("\n") Получить массив содержимого каждой строки.

Получить содержимое каждой строки файла

Мы также можем напрямую вызвать инкапсулированную функцию readLines Kotlin, чтобы получить содержимое каждой строки файла. Функция readLines возвращает список, содержащий содержимое каждой строки.

Управление байтовыми массивами напрямую

Если мы хотим напрямую манипулировать байтовым массивом файла, мы можем использовать readBytes (). Если вы хотите использовать традиционный способ Java, вы можете использовать его так же свободно, как Groovy в Kotlin.

15.3.2 Запись файлов

Подобно чтению файла, запись в файл проста. Мы можем написать строки или байтовые потоки. Вы также можете использовать Java Writer или OutputStream напрямую.

Перезаписать файл

Добавить файл в конце

15.4. Обход файлового дерева

Как и Groovy, Kotlin также предоставляет удобные функции для обхода дерева файлов. Обход дерева файлов требует вызова метода расширения walk (). Он вернет объект FileTreeWalk, и у него есть несколько методов для установки направления и глубины обхода, подробности см. В документации по FileTreeWalk API.

В следующем примере выполняется перебор всех файлов в указанной папке.

Запустите приведенный выше тестовый код, он выведет все подкаталоги и их файлы в текущем каталоге.

Мы также можем перебрать все файлы подкаталогов ниже текущего файла и сохранить его в Итераторе <File>

Мы перебираем все файлы подкаталогов в текущем файле, а также можем фильтровать по условиям и сохранять результаты в Sequence <File>

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

15.5 Операции сетевого ввода-вывода

Ниже мы просто напишем несколько примеров функций.

Получить ответ URL в соответствии с HTML-функцией URL

Получить функцию массива битов ответа URL в соответствии с URL

Записать байтовый массив ответа URL в файл

Следующий пример просто возвращает исходный код домашней страницы Baidu.

В следующем примере выполняется получение потока битов изображения на основе URL-адреса, а затем вызывается метод readBytes () для чтения потока байтов и записи его в файл.

Мы можем увидеть скачанный файл «picture.jpg» в соответствующей папке проекта.

15.6 kotlin.io Стандартная библиотека

Библиотека io Kotlin - это, прежде всего, библиотека io, которая расширяет Java. Ниже мы кратко приведем несколько примеров.

appendBytes

Добавить байтовый массив в файл

appendText

Добавить текст в файл

bufferedReader

Получить BufferedReader для файла

bufferedWriter

Получите BufferedWriter для файла

copyRecursively

Скопируйте файл или рекурсивно скопируйте каталог и все его вложенные файлы по указанному пути. Если файл по указанному пути не существует, он будет создан автоматически.

15.7. Выполнение командной строки оболочки

Мы используем файловые операции ввода-вывода Groovy, которые кажутся очень полезными, такие как

Файловый IO и сетевой IO-операции в Kotlin так же просты, как Groovy.

Кроме того, из приведенного выше кода мы видим, что выполнить команды терминала с помощью Groovy очень просто:

В Kotlin такие функции, как класс String и Process, еще не расширены. На самом деле, расширение такой функции очень просто. Мы можем расширить себя.

Во-первых, давайте расширим функцию execute () строки.

Затем давайте расширим текстовую функцию до класса Process.

После выполнения двух простых функций расширения, описанных выше, мы можем выполнить команды терминала, такие как Groovy, в следующем тестовом коде:

Фактически, благодаря изучению многих предыдущих примеров, мы можем видеть, что функции расширения Котлина весьма практичны. Язык API Kotlin сам по себе широко использует расширения.

15.8 Регулярные выражения

В Kotlin, в дополнение к прежнему использованию Java Pattern, Matcher и других классов, Kotlin также предоставляет класс регулярного выражения kotlin / text / regex / Regex.kt. Мы используем конструктор Regex для создания регулярного выражения ,

15.8.1. Построение выражения регулярного выражения

Используйте конструктор Regex

Параметр сопоставления RegexOption является обычным параметром сопоставления в шаблоне класса Java, который используется напрямую.

Функция расширения ToRegex с использованием String

15.8.2 Функция регулярного выражения

Regex предоставляет множество простых и практичных функций, как показано в следующей таблице

Имя функции Описание функции
matches(input: CharSequence): Boolean Все входные строки совпадают
containsMatchIn(input: CharSequence): Boolean У входной строки есть хотя бы одно совпадение
matchEntire(input: CharSequence): MatchResult? Все входные строки совпадают, возвращают соответствующий объект результата
replace(input: CharSequence, replacement: String): String Заменить совпадающую часть входной строки содержимым замены
replace(input: CharSequence, transform: (MatchResult) -> CharSequence): String Замените совпадающее значение во входной строке новым значением после преобразования преобразования функции
find(input: CharSequence, startIndex: Int = 0): MatchResult? Возвращает первое совпадающее значение во входной строке
findAll(input: CharSequence, startIndex: Int = 0): Sequence<MatchResult> Возвращает последовательность всех совпадающих значений во входной строке

Ниже мы приведем простые примеры вышеуказанных функций соответственно.

matches

Все входные строки соответствуют регулярному выражению и возвращают true, в противном случае возвращается false.

containsMatchIn

Возвращает true, если во входной строке есть хотя бы одно совпадение, и false, если совпадения нет.

matchEntire

Все входные строки соответствуют регулярному выражению и возвращают объект MatcherMatchResult, в противном случае он возвращает ноль.

Мы можем получить доступ к значению MatcherMatchResult, чтобы получить соответствующее значение.

Поскольку возвращением функции matchEntire является объект MatchResult? Nullable, здесь мы используем символ безопасного вызова ?. 。

replace(input: CharSequence, replacement: String): String

Замените соответствующую часть входной строки содержимым замены.

Мы можем видеть это в "12345XYZ" 12345 Соответствует регулярному выражению 3+ Содержание было заменено abcd 。

replace(input: CharSequence, transform: (MatchResult) -> CharSequence): String

Замените совпадающее значение во входной строке новым значением после преобразования преобразования.

Мы можем видеть, что 9XYZ8 Числа 9 и 8 соответствуют регулярным выражениям 7+ Содержимое, они соответственно отображаются с помощью функции преобразования (it.value.toInt() * it.value.toInt()).toString() Замените новые значения 81 и 64.

Возвращает первый соответствующий объект MatcherMatchResult во входной строке.

findAll

Возвращает последовательность MatchResults для всех совпадающих значений во входной строке.

Мы можем перебрать все совпадающие значения через цикл forEach

15.8.3 Использование классов регулярных выражений Java

В дополнение к функциям, предоставляемым Kotlin выше, мы все еще можем использовать API регулярных выражений Java в Kotlin.

Приведенный выше код запускает вывод:

15.9 Котлин Многопоточность

В Kotlin нет синхронизированного ключевого слова.
В Kotlin отсутствует ключевое слово volatile.
Любой из Kotlin похож на Java-объект, но без методов wait (), notify () и notifyAll ().

Так как же работает параллелизм в Котлине? Будьте уверены, поскольку Kotlin стоит на плечах Java, конечно, поддержка многопоточного программирования неизбежна - Kotlin упрощает наше кодирование, инкапсулируя классы потоков в Java. В то же время мы также можем использовать некоторые конкретные аннотации и напрямую использовать ключевые слова синхронизации в Java. Давайте кратко представим соответствующий контент многопоточного программирования с Kotlin.

15.9.1 Создание темы

У нас обычно есть два метода в Java для создания потоков в Java:

  • Расширение класса Thread
  • Или создайте его экземпляр и передайте Runnable через конструктор

Поскольку мы легко можем использовать классы Java в Kotlin, можно использовать оба метода.

Создание с использованием выражений объекта

Этот код использует объектное выражение Kotlin для создания анонимного класса и переопределяет метод run ().

Использование лямбда-выражений

Вот как передать Runnable во вновь созданный экземпляр Thread:

Мы не видим здесь Runnable. В Kotlin мы можем легко использовать вышеприведенное лямбда-выражение для его выражения.

Есть ли более простой способ? Посмотрите на объяснение ниже.

Использование Kotlin-обернутых потоковых функций

Например, мы написали следующий код потока

Следующие четыре строки можно назвать стандартным кодом. Инкапсуляция таких операций упрощена в Kotlin.

Этот код выглядит более упорядоченным и аккуратным. Фактически функция thread () является абстрактной инкапсуляцией стандартного кода, часто используемого в нашей практике программирования.

Это просто очень удобная функция обертки, простая и практичная. Из приведенного выше примера мы видим, что Kotlin упростил шаблонный код, расширив API-интерфейс потоков Java.

15.9.2 Методы и блоки синхронизации

синхронизированный - это не ключевое слово в Kotlin, оно заменяется аннотацией @Synchronized. Объявление синхронного метода в Kotlin будет выглядеть так:

Аннотация @Synchronized имеет тот же эффект, что и синхронизация в Java: она помечает методы JVM как синхронизированные. Для синхронизированных блоков мы используем функцию synchronized (), которая принимает блокировку в качестве параметра:

В основном так же, как Java.

15.9.3 Переменное поле

Аналогично, у Kotlin нет ключевого слова volatile, но есть аннотация @Volatile.

@Volatile помечает поля резервного копирования JVM как изменяемые.

Конечно, у нас есть лучшие параллельные библиотеки сопрограмм в Котлине. В практике разработки кода мы можем свободно выбирать в соответствии с реальной ситуацией.

Краткое содержание этой главы

Kotlin - очень практичный инженерный язык: из файлового ввода-вывода, регулярных выражений и многопоточности, представленных в этой главе, мы можем понять основные принципы Kotlin: в полной мере использовать существующую экологическую библиотеку Java и опираться на На нем есть более простые и практичные расширения, которые значительно повышают производительность труда программистов. Из этого мы также поняли минималистскую концепцию программирования Kotlin - постоянно абстрагируя, инкапсулируя и расширяя, делая ее более простой и практичной

В следующей главе и в нашей последней главе давайте оторвемся от JVM и напрямую будем использовать Kotlin Native для разработки приложения Kotlin, которое компилируется непосредственно в машинный код и запускается.

Чтобы быстро начать программировать на языке, достаточно знать несколько основных конструкций и общих правил написания кода. Со временем вы освоите все нюансы, а на старте можно использовать что-то попроще.

Если вы не знаете, зачем нужен Kotlin и что на нём программируют, почитайте нашу статью про Kotlin. А если знаете — вот вам краткий справочник по основам языка.

👉 В Kotlin будет много конструкций, похожих на Java. Это нормально, потому что Kotlin работает тоже поверх виртуальной машины JVM, как и Java.

Точка с запятой в Котлине не нужна.

Комментарии

Всё как обычно — есть однострочные и многострочные комментарии:

// Это однострочный комментарий
// Для каждой строки нужно добавлять его отдельно
/* А это — многострочный
его можно сделать любой длины,
если в начале и в конце поставить нужные символы */

Многие программисты ругают Kotlin за то, что ключевые слова для переменной и константы отличаются всего на одну букву:

val — объявляет константу

var — объявляет переменную

Из-за этого легко ошибиться и сделать константу вместо переменной и наоборот.

Ввод и вывод

Чтобы ввести что-то с клавиатуры, нам нужна переменная, где будет храниться результат ввода и команда readLine(). Эта команда ждёт, когда пользователь введёт любые данные и нажмёт Enter. После этого всё, что ввёл пользователь, отправляется в ту переменную.

Для вывода используются команды print() и println() — первая оставляет курсор на той же строке, а вторая после вывода переводит курсор на новую строку.

Чтобы вывести значение переменной в команде вывода, перед переменной ставят знак доллара:

Присваивание и сравнение

Всё так же, как в Java, но без точек с запятой:

// это присваивание
x = 10
// а это — сравнение x и 10
// результат сравнения отправляется в переменную b
var bol: Boolean
b = (x == 10)

Условный оператор if

Работает как обычно: сначала проверяется условие, и если оно истинно — выполняется код, который идёт после условия. Если результат проверки ложный — выполняется код, написанный после else, или не выполняется ничего, если такого блока в условии нет. Условие пишется в скобках, фигурные скобки можно не писать, если нужно выполнить только одну команду.

Оператор множественного выбора when

Аналог классического Case или Switch из других языков программирования. Команда смотрит на значение переменной, которое к ней поступило, и сравнивает это значение со своим списком вариантов. Если есть совпадение — выполняется нужная команда.

Циклы

Проще всего работать с циклом for: достаточно указать имя переменной цикла и диапазон, в котором она будет меняться:

При желании можно указать шаг цикла внутри диапазона (по умолчанию он равен единице):

for (i in 1..6 step 2) print("$i ") // на экране появятся числа 1, 3 и 5
>

Циклы с предусловием и с постусловием выглядят и работают как в обычном Java:

Функции

У функций в Kotlin полная свобода:

  • можно возвращать значение, а можно и не возвращать;
  • функции могут иметь свой тип, а могут и не иметь;
  • функции могут работать как переменные;
  • функции можно перегружать почти как операторы в C++.

👉 А ещё в Kotlin, как и в Java, каждая программа состоит из функций и каждая команда должна быть внутри какой-то функции. Основная функция программы называется main.

Самое простое объявление и использование функций в Kotlin выглядит так:

Классы

Классы в Котлине поддерживают полноценные конструкторы и инициализации, но для старта достаточно объявить имя класса и его содержимое:

Объекты

Как и в большинстве ООП-языков, для создания нового объекта достаточно указать класс, от которого произойдёт объект. После этого с объектом можно работать по всем правилам объектно ориентированного программирования:

В этой статье вы научитесь отображать вывод на экран и принимать ввод от пользователя в Kotlin.

Колтин Выход

Вы можете использовать println() и print() функцию для отправки вывода на стандартный вывод (экран). Возьмем пример:

Когда вы запустите программу, вывод будет:

Здесь println() выводится строка (в кавычках).

Разница между println () и print ()

  • print() - выводит строку внутри кавычек.
  • println() - выводит строку внутри кавычек аналогично print() функции. Затем курсор переместится в начало следующей строки.

Когда вы используете println() функцию, она вызывает System.out.println() функцию внутри себя. ( System.out.println() используется для вывода вывода на экран в Java).

Если вы используете IntelliJ IDEA, поместите курсор мыши рядом println и перейдите к Navigate > Declaration (ярлык: Ctrl + B. Для Mac: Cmd + B ), это откроется Console.kt (файл декларации). Вы можете видеть, что println() функция вызывает внутренний вызов System.out.println() .

Точно так же, когда вы используете print() функцию, она вызывает System.out.print() функцию.

Пример 1: print () и println ()

Когда вы запустите программу, вывод будет:

Пример 2: печать переменных и литералов

Когда вы запустите программу, вывод будет:

В этом разделе вы научитесь принимать данные от пользователя…

Чтобы прочитать строку в Kotlin, вы можете использовать readline() функцию.

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

Когда вы запустите программу, вывод будет:

Можно принимать ввод в виде строки с помощью readLine() функции и Int явно преобразовывать ее в значения другого типа данных (например, ).

Если вы хотите ввести другие типы данных, вы можете использовать Scanner объект.

Для этого вам нужно импортировать Scanner класс из стандартной библиотеки Java, используя:

Затем вам нужно создать Scanner объект из этого класса.

Теперь объект чтения используется для ввода данных от пользователя.

Пример 4: Получение целочисленного ввода от пользователя

Когда вы запустите программу, вывод будет:

Здесь создается reader объект Scanner класса. Затем nextInt() вызывается метод, который принимает целочисленный ввод от пользователя, который сохраняется в переменной integer.

Для того, чтобы получить Long , Float , double и Boolean ввод от пользователя, вы можете использовать nextLong() , nextFloat() , nextDouble() и nextBoolean() методы соответственно.

  • Open with Desktop
  • View raw
  • Copy raw contents Copy raw contents Loading

Copy raw contents

Copy raw contents

5. Основы текстового ввода-вывода

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

Рассмотрим обе эти задачи подробнее.

Простая задача на разбор строки может выглядеть так. Некоторая строка содержит текущее время в формате "11:34:45", то есть часы, минуты и секунды, разделённые двоеточием. Написать функцию, которая разберёт эту строку и рассчитает количество секунд, прошедшее с начала дня. В нашем случае ответ должен быть 11 * 3600 + 34 * 60 + 45 = 41685. Решение на Котлине может выглядеть так:

Данная функция начинается с разбиения строки на части. Для этой цели мы используем функцию str.split(":") , у которой разбиваемая строка является получателем, а аргумент задаёт последовательность символов, по которой происходит разбиение. Результатом функции split является СПИСОК строк, содержащий части исходной строки. В нашем случае строка содержит два двоеточия, поэтому частей будет три, например, "11", "34" и "45".

Получив части нашей строки — часы, минуты и секунды — нам необходимо каждую из них превратить из строки в целое число. Это преобразование осуществляется оператором val number = part.toInt() . Похожие функции нам уже встречались в уроке 2 — они использовались для преобразования целых чисел в вещественные n.toDouble() или вещественных в целые x.toInt() . Оказывается, функции toInt() и toDouble() определены и для получателя типа String.

Мутирующая переменная result используется для формирования результата. В процессе выполнения цикла for часы будут умножены на 60 дважды, минуты — один раз, а секунды оставлены как есть (проверьте этот факт). В результате мы получим количество секунд, прошедшее с начала дня.

Произошло так называемое исключение. Исключение — это особый тип переменных, который в языках Котлин и Java имеет название Exception . У исключений есть множество разновидностей, или подтипов, конкретно в данном случае произошло исключение, тип которого называется NumberFormatException , или "исключение формата числа". Математически мы имеем здесь переменную e , причём e ∈ ENF (NumberFormatException), а ENF ⊂ E (Exception).

Переменные с типом "исключение" используются для описания произошедших в ходе программы ошибочных ситуаций. У таких переменных есть возможность, которой нет у других переменных — их можно бросать (throw). В Котлине это делается так:

или просто, без создания промежуточной переменной:

Вызов функции NumberFormatException("Description") создаёт исключение. При этом вначале указывается название типа, а в скобках перечисляются необходимые для создания исключения аргументы. В данном случае аргумент один — это строка с описанием произошедшего; в примере выше таким описанием было For input string: "AA" . Обратите внимание на необычность такой функции — её имя начинается с большой буквы и полностью совпадает с именем некоторого типа. Такие функции называются конструкторами, поскольку используются для создания новых элементов определённого типа. Позже мы ещё не раз с ними столкнёмся.

После описания исключения на консоль выводится порядок, в котором происходил вызов функций, программисты называют его стек вызовов функций:

Читается стек вызовов обычно снизу вверх следующим образом:

Функция timeStrToSeconds из пакета lesson5.task1 и класса Tests в строке 11 файла Tests.kt вызвала…​

Функцию timeStrToSeconds из пакета lesson5.task1 и класса ParseKt , которая в строке 14 файла Parse.kt , в свою очередь, вызвала…​

Функцию parseInt из пакета java.lang и класса Integer , которая в строке 615 файла Integer.java , в свою очередь, вызвала…​

и так далее. Читая стек вызовов, надо иметь в виду, что часть функций — например, toInt — в Котлине являются встраиваемыми (inline) — такие функции не попадают в стек. Другая часть функций может находится в библиотеках, в том числе и библиотеках Java — в частности, parseInt . Обычно, чтобы разобраться в ситуации, достаточно изучения собственных функций.

Обратите внимание, что строчки вроде Parse.kt:14 IDE подсвечивает синим цветом. Щелчком на них можно перейти к соответствующей строке. Видно, что там происходит вызов part.toInt() . Из описания исключения можно сделать вывод, что оно произошло для исходной строки "AA" , и понятно, о какой ошибке идёт речь — эта строка не соответствует никакому десятичному числу.

Поставим себя на минутку на место функции toInt() . Ей передана некоторая строка, из которой следует сделать число. Если строка действительно соответствует числу, его следует сконструировать и вернуть как результат. Но что делать, если из строки нельзя сконструировать число? Мы могли бы вернуть некоторую специальную константу (во многих упражнения предлагалось делать так), но какую? Любое целое число может быть результатом преобразования какой-либо строки. Пусть, например, мы выбрали число -1, и пусть при вызове toInt() мы получили такой результат. Как нам узнать — это произошла ошибка, или же наша строка действительно была равна "-1" ? Из-за возможности подобных неоднозначностей программисты придумали исключения.

Итак, если ранее функция обязана была всегда сформировать какой-нибудь результат, то с появлением исключений у неё появилась вторая альтернатива — бросить исключение. Такое поведение характерно для многих функций. Например, при обращении к элементу списка по индексу необходимо, чтобы индекс находился в пределах от 0 до list.size - 1 . В противном случае произойдёт исключение подтипа IndexOutOfBoundsException .

Как предусмотреть возможность появления исключения в программе? Вернёмся к задаче о преобразовании времени в формате "ЧЧ:ММ:СС" в число секунд, прошедшее с начала дня. В этой задаче нам известно, что число часов, минут и секунд неотрицательно, поэтому мы могли бы возвращать результат -1 в случае, когда исходная строка некорректна. В отличие от функции toInt() , в нашем случае -1 секунда не может получиться из любой корректной строки. Но как вернуть результат -1, если произошло исключение? Для этого исключение необходимо поймать (catch).

Ловится исключение так. Часть функции, где может произойти исключение, оборачивается блоком try < >— сравните текст функции с её первоначальным вариантом. try с английского переводится как "попытаться" (выполнить участок программы, в котором может произойти исключение). После блока try записывается один (или несколько) блоков catch (e: ExceptionType) < >— в котором написано, что следует делать, если произошло определённое исключение. Как только в результате одного из вызовов функций внутри блока try происходит исключение типа NumberFormatException , выполнение блока try прерывается и начинает выполняться блок catch. e: ExceptionType — это параметр блока catch, ExceptionType указывает его тип — в нашем случае это NumberFormatException .

Рассмотрим порядок ловли исключения чуть более точно. Пусть в некоторой функции foo произошло определённое исключение типа SomeException . Будем считать, что функция способна обработать исключение типа SomeException , если в данный момент она находится внутри блока try, и за ним имеется блок catch для ловли исключения типа SomeException или более общего (например, Exception ). Тогда программа последовательно выполнит следующие действия:

Проверим, может ли функция foo обработать исключение. Если да — управление передаётся её блоку catch.

В противном случае, перейдём к функции bar , которая до этого вызвала функцию foo . Проверим, может ли она обработать исключение. Если да — управление передаётся её блоку catch.

В противном случае, перейдём у функции baz , которая до этого вызвала функцию bar . Проверим то же самое для неё.

Выполнение блока catch после передачи управления ему происходит обычным образом. В нашем случае он содержит один оператор return -1 , который формирует результат функции, и выполнение её на этом заканчивается. В общем случае содержимое блока catch может быть любым. После окончания его выполнения, начинает выполняться следующий оператор после try..catch, если такой оператор есть.

Ловля и обработка исключений — очень важный элемент программирования. Пользуясь чужими программами, вам, скорее всего, не раз приходилось говорить, что программа "упала". В современном программировании такое "падение" программы чаще всего вызывается именно исключением, которое возникло, но никем не было поймано и обработано. Такое исключение приводит к аварийной остановке работы программы, что в промышленном программировании недопустимо. Принято, что программа должна КОРРЕКТНО реагировать на любые, в том числе некорректные, действия пользователя, поэтому промышленные программы обычно включают в себя механизмы обработки исключений.

Не менее важной задачей является представление определённой информации пользователю. Здесь мы касаемся лишь маленького кусочка этой задачи — правильного форматирования строк. Вспомним ещё раз нашу задачу о преобразовании времени в число секунд и рассмотрим обратную ей. Пусть дано время в секундах, прошедшее с начала дня, и необходимо сформировать строку в формате "ЧЧ:ММ:СС", соответствующую данному времени.

Представим себе, что мы дали на эту задачу ответ вроде "13:8:1" вместо ожидаемого "13:08:01" . С одной стороны, человек должен быть в состоянии понять и наш ответ, но с другой стороны, привычным для человека является всё-таки формат "13:08:01" и, увидев наш ответ без нулей, он на мгновение придёт в ступор и задумается, а что же это вообще такое — время или же просто последовательность чисел. Именно поэтому важно всё-таки соблюдать ожидаемый формат.

Для решения задачи мы могли бы воспользоваться функцией вроде этой:

которая для однозначных чисел формирует строку с нулём впереди, а для остальных всё оставляет как есть. Решение с помощью функции twoDigitStr выглядело бы так:

В первых трёх операторах мы рассчитываем текущий час, минуту и секунду путём деления на 60. В последнем мы формируем требуемую строку, и данная функция работает верно. Есть только два "но": выглядит последний оператор довольно уродливо, а кроме того, при форматировании строк может возникать много похожих задач и, казалось бы, для них должно существовать общее решение.

Таким решением является готовая функция String.format() . В данном случае она может использоваться так:

Первым аргументом функции является форматная строка. Это обычный строковый литерал (константа), в которой, однако, особый смысл несёт символ процента %. Этот символ вместе с несколькими последующими образует модификатор формата, который функцией String.format будет заменён на её следующий аргумент ( hour для первого процента, minute для второго и second для третьего). В этом смысле модификаторы формата напоминают строковые шаблоны "$name" , но они имеют большую мощность, так как позволяют выбрать ещё и формат подстановки аргумента в строку.

Конкретно %02d означает "подставить в строку целое число, заняв НЕ МЕНЬШЕ двух (2) символов и заполнив НЕДОСТАЮЩИЕ символы (если число однозначное) нулём (0). Перечислим другие распространённые модификаторы формата:

%d — подставить число типа Int ;

%3d — подставить число типа Int , заняв не меньше трёх позиций (пустые заполняются по умолчанию пробелами);

%c — подставить символ;

%s — подставить строку;

%20s — подставить строку, заняв не меньше 20 позиций;

%lf — подставить число типа Double в обычном формате;

%le — подставить число типа Double в экспоненциальном формате вида 1.3e+4;

%6.2lf — подставить число типа Double в обычном формате, заняв не меньше шести позиций и используя ровно два знака после запятой.

Разбор и форматирование строк может применяться, в том числе, для взаимодействия с пользователем в консольном приложении. Вам уже известна функция println , предназначенная для вывода информации на консоль. Комбинируя её с функцией String.format или со строковыми шаблонами, программа может обеспечить вывод на консоль в нужном пользователю формате.

Для ввода информации с консоли в Котлине применяется функция readLine() , считывающая одну строку с консоли. Строка заканчивается, когда пользователь нажимает клавишу Enter. Функция не имеет параметров, а результат её имеет тип String? . Знак вопроса после названия типа означает, что, помимо строки, результатом функции может быть также специальная константа null. Смысл этой константы в большинстве случаев — "некорректный результат", фактически это ещё один (в дополнении к исключениям) способ поведения в ошибочных ситуациях. Более точный смысл null — некорректная ссылка, не ссылающаяся никуда.

readLine() использует результат null, когда ввод строки по какой-либо причине завершился неудачно. Это может произойти при достижении особого символа конец файла, который в нормальной ситуации не встречается при вводе в консоли. Операционная система, однако, имеет возможность перенаправления консольного входа программы таким образом, чтобы вместо ввода информации пользователем с клавиатуры программа читала информацию из файла. В случае использования такого перенаправления действительно возможно достижение конца файла.

Я пытаюсь принять вход с консоли в Kotlin, но это сложно, потому что я не слишком уверен в синтаксисе.

Начну с основного

ЧТО я должен ввести после этого? Я знаю, что задействованы println() и readline() , но я не знаю, как их структурировать.

Цель: пригласить пользователя ввести номер, число введенное умножается на 6, программа возвращает результат на консольный дисплей.

Вот примеры A + B в котлинском чтении со стандартного ввода:

Конкурентное программирование

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

Остерегайтесь, что Сканер работает несколько медленно. Это может быть важно в некоторых случаях, например, в конкурентном программировании, где выполнение программы на больших входах можно ускорить в два раза, просто заменив Scanner на обычную readLine. Даже моя неоптимальная реализация readString() использованием последовательности выполняется несколько быстрее. Он позволяет читать входные токены до следующего пробела, в отличие от встроенного в Kotlin readLine() .

Я надеюсь, что когда-нибудь в Kotlin stdlib появится краткая, кроссплатформенная, производительная, универсальная поддержка парсинга и ввода файлов. Как readInt , readLong и т.д. Глобальные и функции расширения Reader . Это было бы очень полезно не только для конкурентного программирования, но и для изучения Kotlin в качестве первого языка. Концепция чтения числа не должна требовать предварительного объяснения коллекций, лямбд и монад.

бонус

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

Вот мир волшебства Kotlin, который позволяет просто обернуть неизмененный консольный код парой строк, чтобы заставить его читать и записывать в файлы, также гарантируя, что они закрыты должным образом:

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

Используйте readLine() для ввода ввода от пользователя, ATQ:

По умолчанию readLine принимает входные данные, так как строка toInt может использоваться для преобразования ее в целое число.

Существует несколько альтернатив для обработки ввода/вывода с помощью Kotlin.

1. Использование стандартной библиотеки Kotlin. Стандартная библиотека Kotlin предоставляет нам расширения для обработки ввода-вывода на основе классов JDK.

Для печати в консоли мы можем использовать функцию print . Если мы запустим следующий фрагмент:

Для чтения из консоли мы можем использовать функцию readLine :

2. Использование стандартной библиотеки Java: Kotlin обладает отличной совместимостью с Java. Таким образом, мы можем использовать стандартные классы ввода-вывода из JDK в наших программах на случай, если они нам понадобятся.

2.1. Использование класса сканера. Использование класса Scanner очень просто; нам нужно только создать экземпляр и использовать метод nextLine :

Обратите внимание, что мы экранируем свойство in с помощью обратных кавычек, потому что это ключевое слово в Kotlin.

2.2. Использование класса BufferedReader: чтобы использовать класс BufferedReader для чтения из стандартного входного потока, нам сначала нужно создать экземпляр с помощью System.in :

И тогда мы можем использовать его методы - например, readLine() :

2,3. Использование класса консоли: в отличие от двух предыдущих классов, класс Console имеет дополнительные методы для обработки ввода-вывода консоли, такие как readPassword и printf .

Чтобы использовать класс Console нам нужно получить экземпляр из класса System :

Кроме того, благодаря совместимости Kotlins с Java, мы можем использовать дополнительные библиотеки Java для обработки ввода/вывода.

В вашем случае после чтения ввода вы можете преобразовать значение String в Int используя toInt() .

Читайте также: