Kotlin when expression issue for calculating (calculator) new to kotlin - kotlin

//Error due to receive type mismatch but it the logic seems ok to me
fun main(args : Array<String>){
println("Enter a number")
var a = readLine()
println("Choose your operator")
val operator = readLine()
println("Enter a second number")
var b = readLine()
var result = when (operator) {
"+" -> a + b
"-" -> a - b
"*" -> a * b
"/" -> a / b
else -> "invalid operator or number"
}
println("Results = $result")
}

In this case, a and b are type String. This means they don't have the -, /, or * operators. I'm going to guess you probably want them to be Ints so you can perform mathematical operations with them.
To do that, we can convert them to Int after we read them:
println("Enter a number")
var a: Int = readLine()?.toInt() ?: throw IllegalArgumentException("Must be an Int")
println("Enter a second number")
var b: Int = readLine().toInt() ?: throw IllegalArgumentException("Must be an Int")
I've explicitly typed a and b as Ints in this example, so we can see how it works. What this new code says is "read a line of input and try to turn it into an Int, if that doesn't work, throw an IllegalArgumentException. You could rewrite this to keep trying, but we're going to leave that bit up to you.
One more thing I would fix is that result is type Any because it can be either an Int (if we know about the operator) or a String (if we don't). I would change it so the invalid operator also throws an exception.
And again, I've typed this explicitly as Int:
var result: Int = when (operator) {
"+" -> a + b
"-" -> a - b
"*" -> a * b
"/" -> a / b
else -> throw IllegalArgumentException("Invalid operator")
}

The problem is that you have input value as string, you have to convert them to int.
Here my code:
fun main(){
println("Enter a number")
val a = readLine()?.toInt()
println("Choose your operator")
val operator = readLine()
println("Enter a second number")
val b = readLine()?.toInt()
if( a != null && b != null) {
val result = when (operator) {
"+" -> a + b
"-" -> a - b
"*" -> a * b
"/" -> a / b
else -> "invalid operator or number"
}
println("Results = $result")
}
}

Related

Kotlin (if else)

I'm new to kotlin. I need to make a calculator using enam. At the end of the code, there is a function that reads the action and returns the enam. The function works but, "if else" doesn't. Need console calculator, not in android studio.Please help!
All code from file
import java.lang.Exception
fun main() {
print("first number: ")
val first : Int = readNumber()
print("second number: ")
val second : Int = readNumber()
println("Enter action: +, -, *, /")
val sum : Int = first + second
println("Answer: $sum ")
}
fun readNumber() :Int{
return try {
readLine()!!.toInt()
}
catch (e:Exception){
0
}
}
enum class Action(val symbol : String){
PLUS("+"),
MINUS("-"),
MULTIPLY("*"),
DIVIDE("/");
}
fun defineAct(){
val pls = Action.PLUS
val mns = Action.MINUS
val mlt = Action.MULTIPLY
val dvd = Action.DIVIDE
if (val = pls){
sum = pls + mns
println("Ответ: ${sum}")
else if (val - mns){
sum = pls - mns
}
}
Your are using val keyword inside if-else. You could change it accordingly your requirements. Hope it will solve your problem.

Error in building simple calculator logic using when expression in Kotlin

This is my code:
fun main() {
// write your code here
val firstNumber:Long = readLine()!!.toLong()
val secondNumber:Long = readLine()!!.toLong()
val operator = readLine()!!
when (operator) {
"+" -> println(firstNumber + secondNumber)
"-" -> println(firstNumber - secondNumber)
"/" -> if (secondNumber == 0.toLong()) println("Division by 0!") else println(firstNumber / secondNumber)
"*" -> println(firstNumber * secondNumber)
else -> println("Unknown operator")
}
}
I think I am doing everything right but still having an error as shown in image.
Please help me to find where I am wrong.

What is the function of the [0] in the reader.next()[0] line of the below code

import java.util.*
fun main(args: Array<String>) {
val reader = Scanner(System.`in`)
print("Enter two numbers: ")
// nextDouble() reads the next double from the keyboard
val first = reader.nextDouble()
val second = reader.nextDouble()
print("Enter an operator (+, -, *, /): ")
val operator = reader.next()[0]
val result: Double
when (operator) {
'+' -> result = first + second
'-' -> result = first - second
'*' -> result = first * second
'/' -> result = first / second
// operator doesn't match any case constant (+, -, *, /)
else -> {
System.out.printf("Error! operator is not correct")
return
}
}
System.out.printf("%.1f %c %.1f = %.1f", first, operator, second, result)
}
next() returns a String, so the [] operator is translated to the get method on String. With a 0 index, this call returns the first character of the String.
If reader.next() returns an array then operator will have the value of the first element of the returned array.

Kotlin: Variable 'result' must be initialized

The compiler is showing error Kotlin: Variable result must be initialized.
Here is the code.
fun main(args: Array<String>) {
print("Enter two numbers: ")
// nextDouble() reads the next double from the keyboard
var first= readLine()!!.toDouble()
var second = readLine()!!.toInt()
print("Enter an choice(1-4)): ")
val operator = readLine()!!.toInt()
var result: Double
when (operator) {
1 -> result = first + second
2 -> result = first - second
3 -> result = first * second
4 -> result = first / second
else -> {
println("Error.")
}
}
println("The result is :- " +result)
}
The problem is that when you read the value of result here:
println("The result is :- " +result)
result might not be initialized, because here:
var result: Double
when (operator) {
1 -> result = first + second
2 -> result = first - second
3 -> result = first * second
4 -> result = first / second
else -> {
println("Error.")
}
You are NOT assigning a value to result in the else branch. You have several options, one could be to make result nullable. For instance:
var result = when (operator) {
1 -> first + second
2 -> first - second
3 -> first * second
4 -> first / second
else -> null
}
if (result != null) {
println("The result is :- " + result)
} else {
println("Error.")
}
Notice that if the operator is not (1-4) the value of result will be null. Also, in your code you're printing "Error" and then again you're attempting to print the result.
To add something more, you could make the thing a bit nicer if you defined your operator with the when statement as a method reference:
print("Enter an choice(1-4)): ")
val operatorCode = readLine()!!.toInt()
val operator: ((Int) -> Double)? = when (operatorCode) {
1 -> first::plus
2 -> first::minus
3 -> first::times
4 -> first::div
else -> null
}
if (operator != null) {
val result = operator.invoke(second)
println("The result is :- " + result)
} else {
println("Error.")
}
As jrtapsell points out the main issue is that you declare result to be a Double but you since you don't cover every possible value in the when statement, you are accessing an un-initialized variable.
Another option, if you really operators other than 1-4 want it to be an error condition and don't want result to end up with a valid Double is to use Optionals.
fun main(args: Array<String>) {
print("Enter two numbers: ")
// nextDouble() reads the next double from the keyboard
var first= readLine()!!.toDouble()
var second = readLine()!!.toInt()
print("Enter an choice(1-4)): ")
val operator = readLine()!!.toInt()
var result: Double? = null
when (operator) {
1 -> result = first + second
2 -> result = first - second
3 -> result = first * second
4 -> result = first / second
else -> {
println("Error.")
}
}
// only print the result if not null
result?.let {
println("The result is :- " +result)
}
}
In this case result will be null if the operator is not one of 1-4.
What is the error message trying to tell you
Variable 'result' must be initialized.
This means there are paths through your code where you access result before you have given it a value.
This is a problem because it means you have probably missed off handling a condition.
How do you get through your code without setting result
If the user inputs 5 result is not set
How to fix
Either set result in the else branch, or give it a default value in the declaration

Kotlin: Passing operator as a function parameter

I've the following function in Kotlin
fun evaluate(first:Int?, second:Int?) {
var result = 0
if (v.equals('*')) {
result = (first ?: 0) * (second ?: 0)
} else if (v.equals('+')) {
result = (first ?: 0) + (second ?: 0)
} else if (v.equals('-')) {
result = (first ?: 0) - (second ?: 0)
} else if (v.equals('/')) {
result = (first ?: 0) / (second ?: 0)
}
return result
}
I want to change it in a way so that I can pass as a third parameter needed operator and evalute the expression. Something like
fun evaluate(first:Int?, second:Int?, op: () -> Unit):Int {
return (first ?: 0).op(second ?: 0)
}
How can I pass the operator as a function in this case? I checked the same kind of a question, but it is not clear how you can do that with operator.
Writing a higher order function using a function type as a parameter allows using both built-in operators and lambda expressions for the operation, so this would look like:
fun evaluate(first: Int?, second: Int?, op: (Int, Int) -> Int): Int {
return op(first ?: 0, second ?: 0)
}
Which can be called with built-in operators such as:
val r1 = evaluate(value1, value2, Int::times)
val r2 = evaluate(value1, value2, Int::plus)
val r3 = evaluate(value1, value2, Int::minus)
val r4 = evaluate(value1, value2, Int::div)
And with custom functions:
val r5 = evaluate(value1, value2) { a, b -> (a * a) + b }
Now you can also assign the operators to variables, such as you v:
val v: (Int, Int)->Int = Int::times // typing needed on left to avoid ambiguous alternatives
// and then later...
val r6 = evaluate(value1, value2, v)
Note that a function written for signature Int.(Int)->Int can be passed into a parameter expecting (Int, Int)->Int because the receiver this will be passed in as the first parameter.
Change () -> Unit into Int.(Int) -> Int. Then all the other code should work as you've written it there.
On the calling side it this is the first int, and the first parameter is the second int: { other -> this * other }
you can try do that:
fun evaluate(first: Int?, second: Int? , v:String ): Int = v.op(first ?: 0, second ?: 0)
fun String.op(first:Int,second:Int):Int = when (this) {
"*" -> first * second
"+" -> first + second
//....
else -> throw Exception()
}
fun main(args: Array<String>) {
println(evaluate(2,3,"*"))
println(evaluate(2,3,"+"))
}