I wanted to build a calculator app for android and for that I needed a parser to convert string expressions to be solved. Now Java and Kotlin doesn't support eval function and importing a javascript engine just for sake of an operation can open me up to various vulnerabilities. So I made my own calculator parser. Now it's working completely fine, all arithmetic operations are working fine except in negative numbers in crash. I do know what the problem is as I am splitting the string using delimiters which are mathematical symbols but I'm not able to do any operation in negative values.
Input : -5 5 Expected : 0 Output : Exception (numberFormatException)
Here's the kotlin class :
class CalculatorParser(private var expression: String) {
init {
if (expression.isEmpty() || expression == "0") {
expression = "0 0"
} else if (expression.split(" ", "-", "*", "/", "^").size == 1) {
expression = "$expression 0"
}
}
private val splitStr = expression.split(" ", "-", "*", "/", "^").toMutableList()
private val a = splitStr[0].toFloat()
private val b = splitStr[1].toFloat()
private val operator = getDelimiter(expression)
private fun getDelimiter(str: String): String {
return if (str.contains(" ")) {
" "
} else if (str.contains("-")) {
"-"
} else if (str.contains("*")) {
"*"
} else if (str.contains("^")) {
"^"
} else {
"/"
}
}
private fun calculate(): Float {
return when (operator) {
" " -> a b
"-" -> a - b
"*" -> a * b
"/" -> a / b
"^" -> pow(a.toInt(), b.toInt()).toFloat()
else -> {
return 0f
}
}
}
fun eval(result: Float = calculate()): String {
var final = ""
if (result.toString().contains(".")) {
val splitResult = result.toString().split(".")
final = if (splitResult[1].toInt() > 0) {
result.toString()
} else {
result.toInt().toString()
}
}
println(splitStr) // This print statement is only for testing the split array in console to be deleted in production code.
return final
}
private fun pow(base: Int, power: Int): Int {
var result = base
var i = 1
while (i < power) {
result *= base
i
}
return result
}
}
CodePudding user response:
private val splitStr = expression.split(" ", "-", "*", "/", "^").toMutableList()
private val a = splitStr[0].toFloat()
the problem because of these lines when you are splitting for "-" and you write -5 5 it is splitting for - and first element is empty ("")and according to this website when you try to parse empty string to float this leads to number format exception.And to solve that maybe you can check if first element is "-" you can convert that expression to "5-5"and that will give you result.
The key is here.You should not use " ""-" ... as first element in your expression.Beacuse you can not convert to empty string ("") to float.I hope my explanation was clear.