본문 바로가기
개발노트/Kotlin

내일배움캠프 2주차 4일 코틀린기초 과제 수정 및 ++

by 시계속세상은아직돌아가는중 2023. 7. 20.

1. 과제 수정점

package com.example.myapplication

class Calculator{
    fun cal(){
        var isEnd:Boolean = false //종료 여부 판단하는 변수
        var addOperation = AddOperation()
        var subOperation = SubtractOperation()
        var mulOperation = MultiplyOperation()
        var divOperation = DivideOperation()
        var num1 : Double
        var num2 : Double
        var operator : String


        while (!isEnd) { // isEnd가 False이면 무한반복

            while(true){
                try{
                    println("숫자를 입력해주세요")
                    num1 = readLine()!!.toDouble()
                    num2 = readLine()!!.toDouble()
                    break
                } catch (e: NumberFormatException){
                    println("잘못입력하였습니다")
                }

            }
            var result: Double = 0.0

            while (true) {
                println("연산자를 입력해주세요 (+, -, /, *, %). 종료를 원하시면 '종료'를 입력하세요")
                operator = readLine()!!.toString()

                if (operator in listOf("+", "-", "*", "/", "%", "종료")) {
                    break
                } else {
                    println("잘못 입력하였습니다. 다시 입력해 주세요.")
                }
            }


            when (operator) {
                "+" -> result = addOperation.operate(num1 = num1, num2 = num2)
                "-" -> result = subOperation.operate(num1 = num1, num2 = num2)
                "*" -> result = mulOperation.operate(num1 = num1, num2 = num2)
                "/" -> result = divOperation.operate(num1 = num1, num2 = num2)
                "%" -> result = num1 % num2
                "종료" ->  isEnd = true // isEnd를 True로 만들어서 루프종료


            }
            if (operator == "종료"){
                println("종료되었습니다.")
            } else{
                println("결과값은 ${result}입니다")

            }
        }

    }
}

기존에 calculator에서 잘못된 동작을 확인하여서 수정하였다.

operator가 해당 문자열 외에 다른 것이 입력받는다면 예외처리를 when문 안에서 했는데, 그렇게 된다면 결과값또한 출력되고 다시 루프가 돌기에 새로운 방식을 도입하였다.

 

 while (true) {
                println("연산자를 입력해주세요 (+, -, /, *, %). 종료를 원하시면 '종료'를 입력하세요")
                operator = readLine()!!.toString()

                if (operator in listOf("+", "-", "*", "/", "%", "종료")) {
                    break
                } else {
                    println("잘못 입력하였습니다. 다시 입력해 주세요.")
                }
            }

바로 이 부분이다.

while(true)를 이용해 조건식이 참일 때만 반환할 수 있도록 설계하였는데, string에 숫자가 들어가는 것은 오류가 아니므로 예외처리를 사용하지 못해본 것이 아쉽다.

 

해당 식

operator in listOf("+", "-", "*", "/", "%", "종료")

을 사용하여 operator가 옳바른 식이 들어가있으면  break가 가능한 반복문이 탄생하였다.

 

또한 오늘 배우게된 예외 처리를 적극 반영하여

 

            while(true){
                try{
                    println("숫자를 입력해주세요")
                    num1 = readLine()!!.toDouble()
                    num2 = readLine()!!.toDouble()
                    break
                } catch (e: NumberFormatException){
                    println("잘못입력하였습니다")
                }

            }

부분을 추가하였다.

int형으로 들어가여 하는 num1과 num2에 문자형태가 들어오면 예외처리하여 '잘못입력하였습니다'를 출력하고 '숫자를 입력해주세요'부분으로 돌아가게 된다.

 

2. for문에 관하여

 

코틀린의 for문은 기존 내가 알고있던 c/c++와 차이점이 존재하였다.

 

이는 내가 이전 c언어에서 '변수를 초기화 해야하는데 어째서 초기화 해야하지?'라는 의문에서 시작되어 초기화 할 곳이 없자 함수 내에서 초기화 함으로써 발생한 문제이다.

 

import java.util.Scanner

fun main() {
    val scanner = Scanner(System.`in`)
    var star = scanner.nextInt()

    for (i in 1..star) {
        for (j in 1..i) {
            print("*")
        }
        println()
    }
}

해당 부분은 이 코드(백준 2438번)을 풀면서 발생하였는데,

import java.util.Scanner

fun main() {
    val scanner = Scanner(System.`in`)
    var star = scanner.nextInt()
    var i:int = 0


    for (i in 1..star) {
        for (j in 1..i) {
            print("*")
        }
        println()
    }
}

의 형태로 i를 지정해주어서 발생하였다.

 

코틀린에서 for문의 i는 반복문에서 사용하는 변수를 직접 선언함과 동시에, 조건식을 수행하려면 당연히 변수가 초기화되어야 하므로 코틀린 자체적으로 초기화되는 것 이다.

 

var i:int = 0

부분은 필요없으며 for문 안에 있는 i와는 별개의 i가 된다.

이렇게 된다면 두 개의 문제점이 존재한다.

 

1. for문 밖의 i는 사용되지 않은 i라는점

2. for문 밖의 i와 for문 조건식 안의 i라는 두 개의 'i'라는 변수가 존재하게 된다.

 

즉 별개의 변수이지만 같은 이름을 가진 i가 존재하게 되므로 이는 지양해야되는 프로그래밍 방식이다.

 

3. 추가과제

package com.example.freeassignment

import java.time.LocalDate
import java.time.format.DateTimeFormatter


class HotelReservation {
    fun reservation(): Array<*> { //*는 어떤 타입이 나와도 된다는 뜻.
        var name: String =""
        var roomNumber: Int = 0
        var checkInDate: String = ""
        var checkOutDate: String = ""

        val nowDay: LocalDate = LocalDate.now()
        val dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd")

        while (true) {
            println("예약자분의 성함을 입력해주세요: ")
            name = readLine().toString()

            if (name != null && !name.any { it.isDigit() }) {
                break
            }

            println("이름에 숫자가 포함되어 있습니다. 다시 입력해주세요.")
        }

        println("예악자분의 방번호를 입력해주세요(방 번호는 100~999이내 입니다.")

            while (true){
            try {
                roomNumber = readLine()!!.toInt()
                if (roomNumber in 100 .. 999){
                    break
                } else{
                    println("잘못된 방번호입니다. 방번호는 100~999 이내입니다.")
                }
            } catch (e: NumberFormatException){
                println("잘못 입력하셨습니다. 숫자를 입력해주세요")
            }
        }

        println("체크인 날짜를 입력해주세요 표기형식. 20230720")
        while (true){

            checkInDate = readLine().toString()
            val changeDateForm = LocalDate.parse(checkInDate, dateFormatter)

            if (checkInDate != null && checkInDate < nowDay.toString()) {
                println("체크인은 지난 날짜를 입력할 수 없습니다. ")
            } else if(checkInDate != null && checkInDate >= nowDay.toString())
            {
                break
            }
        }

        println("체크아웃 날짜를 입력해주세요")
        while (true) {
            val checkOutDate = readLine().toString()
            if (checkInDate != checkOutDate && checkInDate < checkOutDate){
                break
            }else{
                println("체크아웃 날짜는 체크인 날짜와 동일하거나 이전 날짜로 지정할 수 없습니다.\n다시 입력해주세요.")
            }
        }
        val reservationMemberInfo = arrayOf(name, roomNumber, checkInDate, checkOutDate)

        return reservationMemberInfo

    }

}

해당 클래스를 작성하면서 

return reservationMemberInfo

부분이 작동하지 않아 

fun reservation(): Array<*> { //*는 어떤 타입이 나와도 된다는 뜻.

를 수정하였다. 본래 작성은 arry<any>였으나 *로 바꿔 모든 입력값을 받게 하였다.

다만, 왜 범위 내를 벗어난 입력값이 있는지는 아직 모르며, 최종적으로 작동 오류를 발생한다면 처음부터 다시 작성할 것 이다.

 

해당 코드를 작성하면서 처음 접하게 된 것

val nowDay: LocalDate = LocalDate.now()
val dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd")

부분이다. 이는 자바의 문법으로

import java.time.LocalDate
import java.time.format.DateTimeFormatter

를 통해 사용되었다.

 

LocalDate로 현재 시간을 받으며

DateTimeFormatter를 이용하여 입력된 값을 localDate와 같은 형식으로 변환하여 둘을 비교할 수 있도록 하였다.

 

package com.example.freeassignment

fun main(){
    var isEnd : Boolean = false
    var menuNum : Int = 0
    val hotelResrvation = HotelReservation()


    while(!isEnd){
        println("[메뉴]")
            println("1. 방 예약, 2. 예약목록 출력, 3. 예약목록 (정령) 출력 4. 시스템 종료, 5. 금액 입금-출금 내역 목록 출력 6. 예약 변경/취소")
        while (true){
            try {
                menuNum = readLine()!!.toInt()
                break
            } catch (e: NumberFormatException){
                println("잘못 입력하셨습니다. 숫자를 입력해주세요")
            }
        }
        when(menuNum){
            1 ->{
                hotelResrvation.reservation()
            }
            2 -> isEnd = true
            3 -> isEnd = true
            4 -> isEnd = true
            5 -> isEnd = true
            6 -> isEnd = true
        }
    }

}

아직 구현되지 않은 부분은 프로그램이 종료되도록 작성하였다.

 

현재 구현해야되는 목표는

 

반환받은

return reservationMemberInfo

값으로 예약한 인원을 늘려나가는 것이다.

이를 위해 reservationMemberInfo를 받는 배열을 만들어

배열[0]에 reservationMemberInfo를 받은 뒤 초기화하고 그 다음에 입력된 값을
배열[1]에 reservationMemberInfo를 새로 받고 초기화하는 식으로 채울 것 이다.

 

혹은 리스트 형태도 고민하고있다.