实战:构建一个Kotlin版本的四则运算计算器
计算器 1.0
val help = """
--------------------------------------
使用说明:
1. 输入 1 + 1,按回车,即可使用计算器;
2. 注意:数字与符号之间要有空格;
3. 想要退出程序,请输入:exit
--------------------------------------""".trimIndent()
fun main() {
while (true) {
println(help)
val input = readLine() ?: continue
if (input == "exit") exitProcess(0)
val inputList = input.split(" ")
val result = calculate(inputList)
if (result == null) {
println("输入格式不对")
continue
} else {
println("$input = $result")
}
}
}
private fun calculate(inputList: List<String>): Int? {
if (inputList.size != 3) return null
val left = inputList[0].toInt()
val operation = Operation.valueOf(inputList[1])
val right = inputList[2].toInt()
return when (operation) {
Operation.ADD -> left + right
Operation.MINUS -> left - right
Operation.MULTI -> left * right
Operation.DIVI -> left / right
}
}
计算器 2.0
class CalculatorV2 {
val exit = "exit"
val help = """
--------------------------------------
使用说明:
1. 输入 1 + 1,按回车,即可使用计算器;
2. 注意:数字与符号之间要有空格;
3. 想要退出程序,请输入:exit
--------------------------------------""".trimIndent()
fun start() {
while (true) {
println(help)
val input = readLine() ?: continue
val result = calculate(input)
if (result == null) {
println("输入格式不对")
continue
} else {
println("$input = $result")
}
}
}
private fun calculate(input: String): String? {
if (shouldExit(input)) exitProcess(0)
val exp = parseExpression(input) ?: return null
val left = exp.left
val operator = exp.operator
val right = exp.right
return when (operator) {
Operation.ADD -> addString(left, right)
Operation.MINUS -> minusString(left, right)
Operation.MULTI -> multiString(left, right)
Operation.DIVI -> diviString(left, right)
}
}
private fun addString(left: String, right: String): String {
val result = left.toInt() + right.toInt()
return result.toString()
}
private fun minusString(left: String, right: String): String {
val result = left.toInt() - right.toInt()
return result.toString()
}
private fun multiString(left: String, right: String): String {
val result = left.toInt() * right.toInt()
return result.toString()
}
private fun diviString(left: String, right: String): String {
val result = left.toInt() / right.toInt()
return result.toString()
}
private fun shouldExit(input: String): Boolean {
return input == exit
}
private fun parseExpression(input: String): Expression? {
val operation = parseOperator(input) ?: return null
val list = input.split(operation.value)
if (list.size != 2) return null
return Expression(
left = list[0].trim(),
operator = operation,
right = list[1].trim()
)
}
private fun parseOperator(input: String): Operation? {
Operation.values().forEach {
if (input.contains(it.value)) {
return it
}
}
return null
}
private fun parseOperator1(input: String): Operation? {
return when {
input.contains(Operation.ADD.value) -> Operation.ADD
input.contains(Operation.MINUS.value) -> Operation.MINUS
input.contains(Operation.MULTI.value) -> Operation.MULTI
input.contains(Operation.DIVI.value) -> Operation.DIVI
else -> null
}
}
}
enum class Operation(val value: String) {
ADD("+"),
MINUS("-"),
MULTI("*"),
DIVI("/")
}
data class Expression(
val left: String,
val operator: Operation,
val right: String
)
fun main() {
val calculator = CalculatorV2()
calculator.start()
}
计算器 3.0
单元测试的代码,我们一般会放在工程的 test 目录下: 可以从这个图中看出很多信息: ·第一,test 目录、main 目录,它们是平级的目录,内部拥有着相同的结构。main 目录下放的是功能代码,test 目录下放的则是测试代码。 ·第二,由于我们要开发 3.0 版本,所以我们在 main 目录下创建了 CalculatorV3 这个类;另外,由于我们需要在 3.0 版本加入单元测试,所以对应的,我们在 test 目录下相同的地方,创建了 TestCalculatorV3。这两个类的关系是一一对应的,CalculatorV3 是为了实现 3.0 版本的功能,TestCalculatorV3 是为了测试 3.0 版本的功能,确保功能正常。
class CalculatorV3 {
private val exit = "exit"
private val help = """
--------------------------------------
使用说明:
1. 输入 1 + 1,按回车,即可使用计算器;
2. 注意:数字与符号之间要有空格;
3. 想要退出程序,请输入:exit
--------------------------------------""".trimIndent()
fun start() {
while (true) {
println(help)
val input = readLine() ?: continue
val result = calculate(input)
if (result == null) {
println("输入格式不对")
continue
} else {
println("$input = $result")
}
}
}
fun calculate(input: String): String? {
if (shouldExit(input)) exitProcess(0)
val exp = parseExpression(input) ?: return null
val left = exp.left
val operator = exp.operator
val right = exp.right
return when (operator) {
Operation.ADD -> addString(left, right)
Operation.MINUS -> minusString(left, right)
Operation.MULTI -> multiString(left, right)
Operation.DIVI -> diviString(left, right)
}
}
private fun addString(leftNum: String, rightNum: String): String {
val result = StringBuilder()
var leftIndex = leftNum.length - 1
var rightIndex = rightNum.length - 1
var carry = 0
while (leftIndex >= 0 || rightIndex >= 0) {
val leftVal = if (leftIndex >= 0) leftNum.get(leftIndex).digitToInt() else 0
val rightVal = if (rightIndex >= 0) rightNum.get(rightIndex).digitToInt() else 0
val sum = leftVal + rightVal + carry
carry = sum / 10
result.append(sum % 10)
leftIndex--
rightIndex--
}
if (carry != 0) {
result.append(carry)
}
return result.reverse().toString()
}
private fun minusString(left: String, right: String): String {
val result = left.toInt() - right.toInt()
return result.toString()
}
private fun multiString(left: String, right: String): String {
val result = left.toInt() * right.toInt()
return result.toString()
}
private fun diviString(left: String, right: String): String {
val result = left.toInt() / right.toInt()
return result.toString()
}
private fun shouldExit(input: String): Boolean {
return input == exit
}
private fun parseExpression(input: String): Expression? {
val operation = parseOperator(input) ?: return null
val list = input.split(operation.value)
if (list.size != 2) return null
return Expression(
left = list[0].trim(),
operator = operation,
right = list[1].trim()
)
}
private fun parseOperator(input: String): Operation? {
Operation.values().forEach {
if (input.contains(it.value)) {
return it
}
}
return null
}
}
fun main() {
val calculator = CalculatorV3()
calculator.start()
}
编写测试代码:
class TestCalculatorV3 {
@Test
fun testCalculate() {
val calculator = CalculatorV3()
val res1 = calculator.calculate("1+2")
assertEquals("3", res1)
}
}
|