Error in inputting array and outputting it | Kotlin - kotlin

I am new at Kotlin (and my English is terrible :).
I want to define the size of the array and elements in it by inputting it from the keyboard.
fun main() {
val array_size = readLine()!!.toInt()
val arr = IntArray(array_size)
for (i in 0..array_size){
arr[i] = readLine()!!.toInt()
}
for(i in 0..array_size){
println(arr[i])
}
}
[I got this message][1]
[1]: https://i.stack.imgur.com/DRk9F.png
This is my first question in StackOverFlow tho, hope it is understandable for those who want to help.

The NullPointerException is probably because the call to readLine() is returning null and then you're forcing that to non-null using readLine()!! which gives you the NPE.
In recent versions of Kotlin a new method was introduced: readln(). It is recommended to use that instead of the old readLine. If and END OF FILE is found, the new readln method will throw a more descriptive exception, whereas readLine will return null which makes it more difficult to see where you went wrong.
You might get an end-of-file condition if the input is redirected from a file or other source. This often happens if you run your program in an IDE or an online compiler service. If you run your program from the command line, it will work, until you get to enter the last line. This is because for(i in 0..array_size) includes the value array_size which is 1 more than the last index, so you get an out-of-bounds exception.
Instead of using 0..(array_size - 1), it is recommended to use arr.indices which gives you the range of valid indices for the array.

readLine() is returning null, and so when you do readLine!!... you're getting a NullPointerException. Perhaps you want to use readln instead.

Related

Kotlin Flow Control - readln()!!.toInt()

I started learning Kotlin a few days ago and I don't really understand why in this case you should use readln()!!.toInt(), from where the number is taken and to which "line" it refers.
fun main(args: Array) {
var number: Int
var sum = 0
for (i in 1..6) {
print("Enter an integer: ")
number = readln()!!.toInt()
It would be extremely helpful if someone could explain that.
Thank you!
readline() (not readln()) returns a line from the standard input stream, or null if the input stream has been redirected to a file and EOF (end of file) is reached. Its return type is String? meaning it could either be a String, or it could be null.
!! is "We are sure this will never be null; force this into a non-nullable type." It means you don't have to deal with the condition where the object you're working with is null.
In this case, the !! is saying "We're sure that system input hasn't been redirected to a file (or if it has, that EOF hasn't been reached); wait for the user to input something."
It looks like someone has mixed up readline() and readln() (which I did when I first answered this question) - #Tenfour04 is right; there's no need to use !! with readln. It does the same thing, except it throws an exception if EOF is encountered.

Kotlin error "Index Out Of Bounds Exception"

I'm newbie to Kotlin, and new to programming also, so pls be gentle :)
Let's say I have a string (it was optimized to NOT have any duplicated character), i want to compare all characters in that string to the alphabet, which declared as a mutable List of character. I want to delete any character from the alphabet which show up in the string. My code is as below
var alphabet=mutableListOf('a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z')
var key="keyword"
println(key)
for (i in key.indices)
{for (j in alphabet.indices)
{if (key[i] == alphabet[j])
alphabet.removeAt(j) // 1. this line have error
//print(alphabet[j]) //2. but this line runs fine
}}}
In above code, I have error at the "alphabet.removeAt(j)" command, so I try another command to print out the characters instead of delete them, and it runs fine. I read some articles and I know this error related to the invalid index, but I used the "indices" key and I think it's pretty safe. Pls help
It is safe to iterate using alphabet.indices, but it is not safe to iterate over a collection while modifying it. Note that indices returned indices for a full alphabet, but then you removed some items from it, making it shorter, so indices are no longer valid.
You don't need to iterate over a collection to find an item to remove. You can just do:
alphabet.remove(key[i])
But honestly, you don't need to do anything of this. Your problem is really a subtracting of two sets and you can solve it much easier:
('a'..'z').toSet() - "keyword".toSet()
You could simplify that whole loop to just:
alphabet.retainAll{ it !in key })
or
alphabet.retainAll { !key.contains(it) }
or if you want the filtered list to be a new list rather than doing it in-place:
val filtered = alphabet.filter { it !in key }
but I used the "indices" key and I think it's pretty safe
Well, the indices collection is only evaluated once when a loop is entered, not at the start of each iteration. Even if you change the size of alphabet in the inner loop, the inner loop will still loop the same number of times, because it doesn't evaluate alphabet.indices again. It would only do that again on the next iteration of the outer loop, but your code would throw an exception before that point.
Other than decreasing j whenever you remove an item, you can also solve this by
key.forEach(alphabet::remove)

Kotlin input first and last name with a twist

Seems a pretty simple program, but I can't figure out what I'm doing wrong. Any help is greatly appreciated!
TASK Write a program that reads the first name and the last name of a person, each on a separate line. Then, print the first letter of the first name with a dot and then the last name (with a single space in between): for example, Arthur Dent would be A. Dent
I've tried the following code:
fun main() {
val s1 = readLine()
val s2 = readLine()
println(s1.first() +"." + " " + s2)
}
Which returns an error: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
This is pretty straightforward in Python, but been struggling to solve it in Kotlin.
Thanks in advance!
Looking at the readLine docs it states that:
Return the line read or null if the input stream is redirected to a file and the end of file has been reached. (also if you fake an end file indication)
This means that both s1 and s2 are nullable. You would have seen this if you would have explicitly declared the type of the vals (something that beginners in kotlin should probably always do), as they would have been String?.
So, if we want to get the first letter (or do more or less anything), we need to use the ? safe call to avoid a NPE. The reason you don't get any error with s2 is because the default invocation of .toString will just return a String with the value of null.
Now even if you do add the safe call you will still get an error, that being that you can't concatenate null to a String. And you can simply solve it by using template instead of concatenation (which is actually the prefered way in kotlin). So we will have this:
println("${s1?.first()}. $s2")
Some changes due to the single input requirement. If you only have one input of type John Doe then the above code won't work, because you are reading 2 separate lines, one of which does not exist, making the lastName null. Doing is for a single input needs a bit more work:
val line = readLine()?.split(" ")
val firstNameInitial = line?.getOrNull(0)?.first()
val lastName = line?.getOrNull(1)
println("$firstNameInitial. $lastName")
This assumes that there are no people with a space in their names (not sure if true or not),that nobody will enter a middle name, and that the first and last name are separated by a " " space.
As per Joffrey's comment, we can also use the elvis operator to ensure that the readLine is not null, by throwing our own exception stating that the input is not readable.
val line = (readLine() ?: error("Unexpected end of input, expected first and last name in format \"John Doe\"")).split(" ")
val firstNameInitial = line.getOrNull(0)?.first() // in case we receive an empty string
val lastName = line.getOrNull(1) //in case we only receive one name
println("$firstNameInitial. $lastName")

Creating 4 digit number with no repeating elements in Kotlin

Thanks to #RedBassett for this Ressource (Kotlin problem solving): https://kotlinlang.org/docs/tutorials/koans.html
I'm aware this question exists here:
Creating a 4 digit Random Number using java with no repetition in digits
but I'm new to Kotlin and would like to explore the direct Kotlin features.
So as the title suggests, I'm trying to find a Kotlin specific way to nicely solve generate a 4 digit number (after that it's easy to make it adaptable for length x) without repeating digits.
This is my current working solution and would like to make it more Kotlin. Would be very grateful for some input.
fun createFourDigitNumber(): Int {
var fourDigitNumber = ""
val rangeList = {(0..9).random()}
while(fourDigitNumber.length < 4)
{
val num = rangeList().toString()
if (!fourDigitNumber.contains(num)) fourDigitNumber +=num
}
return fourDigitNumber.toInt()
}
So the range you define (0..9) is actually already a sequence of numbers. Instead of iterating and repeatedly generating a new random, you can just use a subset of that sequence. In fact, this is the accepted answer's solution to the question you linked. Here are some pointers if you want to implement it yourself to get the practice:
The first for loop in that solution is unnecessary in Kotlin because of the range. 0..9 does the same thing, you're on the right track there.
In Kotlin you can call .shuffled() directly on the range without needing to call Collections.shuffle() with an argument like they do.
You can avoid another loop if you create a string from the whole range and then return a substring.
If you want to look at my solution (with input from others in the comments), it is in a spoiler here:
fun getUniqueNumber(length: Int) = (0..9).shuffled().take(length).joinToString('')
(Note that this doesn't gracefully handle a length above 10, but that's up to you to figure out how to implement. It is up to you to use subList() and then toString(), or toString() and then substring(), the output should be the same.)

Is there any good defacto standard 'everything went smoothly' message in a method that returns string errors?

So my class takes data and does it's thing, returning an error message if anything went wrong. What should I make the string if everything went fine? null? "1"? "OK!"? "success"?
Please support your answer.
Unix standard return codes use '0' as OK - by analogy, it's often recommended to use empty string (length 0), at least in languages where you can treat the "" value as "false".
E.g., in Perl: if ( $error = my_method_call() ) { print "Failed: $error\n" }
In a language where there's no such implication (use "" as false), any string can be chosen as "OK", as long as it's obvious and readable ("OK" fits the bill).
Methods should never return string errors. They are way too error prone and are more costly than the obvious alternative, returning integer codes, which you can translate to descriptive constants and have a single method which translates those codes to strings.
If you will use error codes to print them out (or log them), then it might be fine to use strings, but then again, there is nothing preventing you from printing or logging the error in the erroring method itself and returning a failing status code to the caller.
If you will use string error codes to check internally in code for different conditions, strings are a pain:
rv = some_function();
if (rv == "The file could not be read") {
take_corrective_action();
}
About including details in error code, the caller (usually) has the details and can compose the complete error message:
rv = read_data(FILE);
if (rv == READ_PERMISSION_ERROR) {
log("The file " + FILE + " could not be read. You don't have permissions");
}