Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading console input in Kotlin

I am attempting to accept input from the console in Kotlin but it is difficult because I am not too sure about the syntax.

I begin with the main

fun main(args: Array<String>) {  } 

WHAT should I enter after this? I am aware that the println() and readline() are involved but I do not know how to structure them.

Objective: prompt user to enter a number, the number entered is multiplied by 6, program returns the result to the console display.

like image 589
siur Avatar asked Dec 22 '16 12:12

siur


People also ask

How do you read a Kotlin console value?

It's possible to take input as a string using readLine() function, and convert it to values of other data type (like Int ) explicitly. If you want input of other data types, you can use Scanner object. Then, you need to create Scanner object from this class. Now, the reader object is used to take input from the user.

What is readLine () in Kotlin?

Kotlin has standard library function readLine() which is used for reads line of string input from standard input stream. It returns the line read or null.

How do you take float input on Kotlin?

Taking the input other than String using Scanner class In this example we are taking the input as an integer and float using the nextInt() and nextFloat() functions respectively. Similarly we can use nextLong() , nextDouble() and nextBoolean() methods to take long, double and boolean inputs respectively.


2 Answers

Note that since Kotlin 1.6 readLine()!! should be replaced with readln().

Here are A+B examples in Kotlin reading from stdin:

fun main() {   val (a, b) = readLine()!!.split(' ')   println(a.toInt() + b.toInt()) } 

or

fun main(vararg args: String) {   val (a, b) = readLine()!!.split(' ').map(String::toInt)   println(a + b) } 

or

fun readInts() = readLine()!!.split(' ').map { it.toInt() }  fun main(vararg args: String) {   val (a, b) = readInts()   println(a + b) } 

or

import java.util.Scanner  fun main() {   val input = Scanner(System.`in`)   val a = input.nextInt()   val b = input.nextInt()   println(a + b) } 

or

with(Scanner(System.`in`)) {     val a = nextInt()     val b = nextInt()     println(a + b) } 

Competitive programming

Must-read intro: https://kotlinlang.org/docs/tutorials/competitive-programming.html

Must-watch Kotlin productivity videos: https://www.jetbrains.com/icpc/

Here is an (inspired by the article) extended bunch of helper functions for reading all possible types, lists, arrays, 2d-arrays, etc:

private fun readln() = readLine()!! private fun readlnByte() = readln().toByte() private fun readlnShort() = readln().toShort() private fun readlnInt() = readln().toInt() private fun readlnLong() = readln().toLong() private fun readlnFloat() = readln().toFloat() private fun readlnDouble() = readln().toDouble() private fun readlnBigInt(radix: Int = 10) = readln().toBigInteger(radix) private fun readlnBigDecimal() = readln().toBigDecimal()  private fun lineSequence(limit: Int = Int.MAX_VALUE) = generateSequence { readLine() }.constrainOnce().take(limit) private fun readlnStrings() = readln().split(' ') private fun readlnBytes() = readlnStrings().map { it.toByte() } private fun readlnShorts() = readlnStrings().map { it.toShort() } private fun readlnInts() = readlnStrings().map { it.toInt() } private fun readlnLongs() = readlnStrings().map { it.toLong() } private fun readlnFloats() = readlnStrings().map { it.toFloat() } private fun readlnDoubles() = readlnStrings().map { it.toDouble() }  private fun readByteArray() = readlnStrings().run { ByteArray(size) { get(it).toByte() } } private fun readShortArray() = readlnStrings().run { ShortArray(size) { get(it).toShort() } } private fun readIntArray() = readlnStrings().run { IntArray(size) { get(it).toInt() } } private fun readLongArray() = readlnStrings().run { LongArray(size) { get(it).toLong() } } private fun readFloatArray() = readlnStrings().run { FloatArray(size) { get(it).toFloat() } } private fun readDoubleArray() = readlnStrings().run { DoubleArray(size) { get(it).toDouble() } }  private fun readlnByteArray(n: Int) = ByteArray(n) { readlnByte() } private fun readlnShortArray(n: Int) = ShortArray(n) { readlnShort() } private fun readlnIntArray(n: Int) = IntArray(n) { readlnInt() } private fun readlnLongArray(n: Int) = LongArray(n) { readlnLong() } private fun readlnFloatArray(n: Int) = FloatArray(n) { readlnFloat() } private fun readlnDoubleArray(n: Int) = DoubleArray(n) { readlnDouble() }  private fun readByteArray2d(rows: Int, cols: Int) = Array(rows) { readByteArray().also { require(it.size == cols) } } private fun readShortArray2d(rows: Int, cols: Int) = Array(rows) { readShortArray().also { require(it.size == cols) } } private fun readLongArray2d(rows: Int, cols: Int) = Array(rows) { readLongArray().also { require(it.size == cols) } } private fun readIntArray2d(rows: Int, cols: Int) = Array(rows) { readIntArray().also { require(it.size == cols) } } private fun readFloatArray2d(rows: Int, cols: Int) = Array(rows) { readFloatArray().also { require(it.size == cols) } } private fun readDoubleArray2d(rows: Int, cols: Int) = Array(rows) { readDoubleArray().also { require(it.size == cols) } }  private fun isWhiteSpace(c: Char) = c in " \r\n\t"  // JVM-only targeting code follows next  // readString() via sequence is still slightly faster than Scanner private fun readString() = generateSequence { System.`in`.read().toChar() }         .dropWhile { isWhiteSpace(it) }.takeWhile { !isWhiteSpace(it) }.joinToString("") private fun readByte() = readString().toByte() private fun readShort() = readString().toShort() private fun readInt() = readString().toInt() private fun readLong() = readString().toLong() private fun readFloat() = readString().toFloat() private fun readDouble() = readString().toDouble() private fun readBigInt(radix: Int = 10) = readString().toBigInteger(radix) private fun readBigDecimal() = readString().toBigDecimal()  private fun readBytes(n: Int) = generateSequence { readByte() }.take(n) private fun readShorts(n: Int) = generateSequence { readShort() }.take(n) private fun readInts(n: Int) = generateSequence { readInt() }.take(n) private fun readLongs(n: Int) = generateSequence { readLong() }.take(n) private fun readFloats(n: Int) = generateSequence { readFloat() }.take(n) private fun readDoubles(n: Int) = generateSequence { readDouble() }.take(n) 

Beware that Scanner is somewhat slow. This may be important in some cases like competitive programming where program's execution on large inputs could be made up to two times faster just by replacing Scanner with plain readLine. Even my suboptimal readString() implementation tokenizing via sequence is slightly faster. It allows to read input tokens until any next whitespace unlike Kotlin's built-in readLine().

I hope someday a concise, crossplatform, performant, universal for both console and files input parsing support would be introduced in Kotlin stdlib. Like readInt, readLong, etc global and Reader extension functions. This would be very userful not only for competitive programming but also for learning Kotlin as first language. A concept of reading a number shouldn't require first explaining collections, lambdas and monads.


Bonus

Sometimes you start with console input/output but then need to switch to files. It becomes too tedious to prepend every read or write call with file stream variable.

Here is a peace of Kotlin magic that allows to just wrap unchanged console code with a couple of lines to force it read and write to files also ensuring they are closed properly:

fun <T : Closeable, R> T.useWith(block: T.() -> R): R = use { with(it, block) }  File("a.in").bufferedReader().useWith {     File("a.out").printWriter().useWith {         val (a, b) = readLine()!!.split(' ').map(String::toInt)         println(a + b)     } }  Scanner(File("b.in")).useWith {     PrintWriter("b.out").useWith {         val a = nextInt()         val b = nextInt()         println(a + b)     } } 

Wrapping lines can be quickly commented out when happens a need to switch back to console.

like image 143
Vadzim Avatar answered Sep 30 '22 11:09

Vadzim


Use readLine() to take input from user, ATQ:

fun main(args:Array<String>){     print("Enter a number")     var variableName:Int = readLine()!!.toInt()  // readLine() is used to accept the String value and ".toInt()" will convert the string to  Int.      var result:Int= variableName*6     print("The output is:$result")  } 
like image 33
sohel yadav Avatar answered Sep 30 '22 12:09

sohel yadav