Elvis operator doesn't work in Kotlin while the synthax seems correct - kotlin

I am learning Kotlin from this [video][1] and at 35:45 he is running this code:
[enter image description here][2]
I ve tried to run exactly the same code:
fun main() {
val x = readLine()?:"1"
val y = readLine()?:"1"
val z = x.toInt() + y.toInt()
print(z)
}
But i get this error:
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:662)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at MainKt.main(Main.kt:4)
at MainKt.main(Main.kt)
Can somebody help me please? I am really a noob in kotlin (and sofware programming too) and i didn't found an answer on the web.
Thank you.
[1]: https://www.youtube.com/watch?v=5flXf8nuq60&t=302s
[2]: https://i.stack.imgur.com/nlHqi.jpg
[3]: https://i.stack.imgur.com/o7y2I.jpg

The Elvis operator evaluates to the right operand only when the left operand is null. The empty string "" is not the same as null.
readLine() returns null when it detects the "end of file". When reading from a file, this is obviously when reaching the end. When reading from stdin (the console's standard input), this is usually when you press Ctrl+D.
If you just press Enter, you are effectively inputting an empty line (""), not the "end of file".
If you want to get this kind of default value when you press Enter on the command line, then you should react to the empty string instead of null. As #lukas.j mentioned, one way to do this is to use ifEmpty to provide a default:
val x = readln().ifEmpty { "1" }

Related

readLine() returns with nothing after a while loop with a readLine() as its condition

I'm trying to write a code that prints out whatever the user inputted into the console, but when I insert a while loop that use the readLine() function as its condition before it, the code would always return with nothing even if the user inputted something into the console. The code is here below:
fun main() {
while(readLine()=="A") print("A is inputted")
print(readLine()+" 123")
}
My intention was for when the user inputted (into the first readLine()) anything besides "A", the code would proceed to the next line, then prints out the next string inputted (into the second readLine()) joined with " 123".
For example: "asdfasdfaf 123", but in actuality it would just prints " 123" instead
Can anyone tell me why this is the case? And what would be the code that'll get the expected behavior? Any help will be appreciated since I'm new to this, thanks :)
EDIT:
I've found the solution a while after posting this and it's kind of weird.
fun main(args: Array<String>) {
while(readln()=="A") print("A is inputted")
readLine() // throwaway readLine()
print("${readLine()} 123")
}
I might be wrong but from what I've gathered here, after the while loop is stopped, the code somehow inputted nothing --which I assume is a null-- into the second readLine(). So I just put a throwaway readLine() between those two. I still don't know why this is the case though
By using readLine() twice, you are effectively asking for 2 pieces of input. This is what your code is currently doing:
You are reading the input (using a while loop? Do you mean to use an if statement instead?)
You are reading a second piece of input, and appending " 123" to the second piece of input.
Try this instead:
fun main() {
//Some kind of for or while loop if you want to constantly take input
val input = readLine()
if (input == "A") {
println("A has been input")
println("$input 123")
}
}
The way it's written, you have to type your "other" input twice - once so it's seen as not "A", and again when you try to print it - you hit two readLine() calls when you type something that isn't "A"
At a guess, you're getting " 123" because you type "asdfasdfaf", which exits the while loop, but then you hit the second readLine() and you're probably just hitting Return again, wondering why it hasn't printed. So the print statement reads in the empty line you just typed, and you get " 123"
If you want to have access to the non-"A" input, you need to store it - that way you can check it during your if condition, and use it in your print statement later. Here's a way you can do it
fun main() {
// do-while runs the loop -at least once- and checks the repeat condition at the end
do {
val input = readLine()
if (input == "A") print("A is inputted")
// this prints inside the loop, now we just need to exit it
else print("$input 123")
} while (input == "A") // stops looping the first time you get non-"A" input
}
which is what Cloudate9 was getting at
I am not exactly sure what you are looking to do, but the way I read and understand your post, this is what I came up with:
fun main() {
val input = readLine()
if (input == "A") {
println("A has been inputted")
} else {
println("$input 123")
}
}

Kotlin forEach sometimes not executing until CTL-C when run in the REPL?

When running the following code as a snippet from https://www.programiz.com/kotlin-programming/examples/convert-list-array :
// printing elements of the array list
vowels_list.forEach { System.out.print(it) }
// vowels array
val vowels_array: Array<String> = arrayOf("a", "e", "i", "o", "u")
// converting array to array list
val vowels_list: List<String> = vowels_array.toList()
// printing elements of the array list
vowels_list.forEach { System.out.print(it) }
The output is supposed to be aeiou
However when I am running it in the kotlin REPL nothing is printed. Why is that?
Update There seems to be something going on for the kotlin repl itself. I just noticed there is a bracket - as if the code were not completed yet:
I have to hit CTL-C and then we see this:
aeiou<interrupted>
What is happening here?
The issue is in the buffering of the terminal. You may add println() to the end of your code to force flushing the symbols to the screen.
Did you try to run only the last three lines of code?
I did it by running on https://play.kotlinlang.org/ and it printed aeiou.

Why won't Kotlin print the string I select from a .txt file unless it's the last line?

I'm using to open a text file, randomly select a line, and format a string that includes the randomly selected line. The string is then printed to the console, but for some reason it won't work unless the last line of the file gets randomly selected.
Text file:
Neversummer
Abelhaven
Phandoril
Tampa
Sanortih
Trell
Zan'tro
Hermi Hermi
Curlthistle Forest
Code:
import java.io.File
fun main() {
var string = File("data/towns.txt")
.readText()
.split("\n")
.shuffled()
.first()
println("$string has printed")
}
Output when last line is selected:
Curlthistle Forest has printed
Output when any other line is selected:
has printed
As suggested by dyukha in the comment section it is indeed a platform specific issue. I prefer the solution (s)he provided using readLines() since you can condense two function calls into one.
However, should you ever need to check for the line delimiter in a platform independent manner you should use the built-in System.lineSeparator() property (Since Java 7).
import java.io.File
fun main() {
var string = File("data/towns.txt")
.readText()
.split(System.lineSeparator())
.shuffled()
.first()
println("$string has printed")
}
...
Still, I do recommend that you use readLines() since it packages the functionality of both .readText() and .split(System.lineSeparator()).

Clean way of reading all input lines in Kotlin

A common pattern when doing coding challenges is to read many lines of input. Assuming you don't know in advance how many lines, you want to read until EOF (readLine returns null).
Also as a preface, I don't want to rely on java.utils.* since I'm coding in KotlinNative, so no Scanner.
I would like to maybe do something like
val lines = arrayListOf<String>()
for (var line = readLine(); line != null; line = readLine()) {
lines.add(line)
}
But that clearly isn't valid Kotlin. The cleanest I can come up with is:
while (true) {
val line = readLine()
if (line == null) break
lines.add(line)
}
This works, but it just doesn't seem very idiomatic. Is there a better way to read all lines into an array, without using a while/break loop?
generateSequence has the nice property that it will complete if the internal generator returns null and accepts only a single iteration, so the following code could be valid:
val input = generateSequence(::readLine)
val lines = input.toList()
Then like s1m0nw1's answer you can use any of the available Sequence<String> methods to refine this as desired for your solution.
I guess you're talking about reading from System.in (stdin) here. You could make that work with sequences:
val lines = generateSequence(readLine()) {
readLine()
}
lines.take(5).forEach { println("read: $it") }
We begin our sequence with a first readLine (the sequence's seed) and then read the next line until null is encountered. The sequence is possibly infinite, therefore we just take the first five inputs in the example. Read about details on Sequence here.

JOptionPane.showInputDialog Changing the ´cancel´ Button

So I'm trying to get a number input from a player in an RPG/survival type game, using showInputDialog to present the options, prompting the user to input a number. My problem is, I get a fatal error if they press cancel.
This is my current code:
String typeReader;
do{
typeReader = JOptionPane.showInputDialog(options);
}while(typeReader.isEmpty());
if (typeReader.isEmpty())
typeReader = "0";
charType = Integer.parseInt(typeReader);
and this is the error I get:
Exception in thread "main" java.lang.NullPointerException
at Game.main(Game.java:66)
Java Result: 1
BUILD SUCCESSFUL (total time: 14 seconds)
Ideally, if a user presses cancel the program would just read it as an empty String:
typeReader = "";
Can anyone help?
OK, you seem to be pretty new to this ;-)
First, you won't need the loop. Just write
String typeReader = JOptionPane.showInputDialog(options);
If the user clicks "Cancel", typeReader will be null afterwards. null is not an object, so you cannot call isEmpty() on it and you get the NullPointerException. Instead, you should check for null:
if (typeReader != null) {
...
}
You should read the Oracle tutorial on dialogs and maybe also the Javadoc.