CODING/스파르타 내일배움캠프 TIL

16_코트카타 문자열을 정수로 바꾸기_개인 과제 진행_25.1.3(금)

codingTrip 2025. 1. 3. 21:46

코트카타

18) 문자열을 정수로 바꾸기

나의 풀이

class Solution {
    public int solution(String s) {
        int answer = 0;
        answer = Integer.parseInt(s);
        return answer;
    }
}

복잡하게 생각하려다 함수를 써버렸다...

 

다른 분들의 풀이

public class StrToInt {
    public int getStrToInt(String str) {
            boolean Sign = true;
            int result = 0;

      for (int i = 0; i < str.length(); i++) {
                char ch = str.charAt(i);
                if (ch == '-')
                    Sign = false;
                else if(ch !='+')
                    result = result * 10 + (ch - '0');
            }
            return Sign?1:-1 * result;
    }
    
    //아래는 테스트로 출력해 보기 위한 코드입니다.
    public static void main(String args[]) {
        StrToInt strToInt = new StrToInt();
        System.out.println(strToInt.getStrToInt("-1234"));
    }
}

출처:https://school.programmers.co.kr/learn/courses/30/lessons/12925/solution_groups?language=java

'0' = 48

result = result * 10 + (ch - '0'); 이 부분이 가장 참신하다고 생각했다.

Sign이 플러스면 1을 곱하고 마이너스면 -1을 곱했다.

객체지향 개념도 사용하신 것으로 보인다.

 

함수를 썼던 것 자체를 잘못했다기보다는

알고리즘 문제를 풀고자 하는 목적이 있는데 이를 잊은 채

빠르게 풀기 급급했던 나 자신에 대해 반성한다.

 


개인 과제 진행

 

Lv1  트러블슈팅

java.util.InputMismatchException at java.base/java.util.Scanner.throwFor(Scanner.java:939) at java.base/java.util.Scanner.next(Scanner.java:1594) at java.base/java.util.Scanner.nextInt(Scanner.java:2258) at java.base/java.util.Scanner.nextInt(Scanner.java:2212) at com.example.calculator2.App.main(App.java:19)

숫자가 아닌 다른 값을 입력했을 때 발생했다.

사실 어제 마지막으로 팀원들과 회고할 때, 다른 팀원분이 말씀해주신 사항이어서 이에 대한 예외처리를 해야 한다.

4주차 try- catch문을 사용한  예외처리를 하라고 조언을 해주셨다.

 

튜터님께서 예외처리는 4주차 강의 내용이므로 필수 과제에서는 구현 안해도 된다고 하셨다.

도전 과제까지 진행하게 될 경우, 하게 될 것으로 보인다.


Lv2  트러블슈팅

트러블슈팅 작성 방

  • 배경 : 어떤 현상을 발견해서
  • 발단 : 이런 장애가 생길 수 있다는 것을 인지했고,
  • 전개 : 장애를 대응, 해결하던 와중에
  • 위기 : 또 다른 장애 발견 또는 간단하게 해결할 수 없다는 것을 알게되어서,
  • 절정 : 근본적인 해결을 위해 이런 방법으로 접근하였다.
  • 결말 : 따라서, 이런이런 방법을 통해 근본적으로 해결 및 앞으로 유지, 보수에 용이하게 개선하게 되었다.

컬렉션 선정

  • 배경 : 사칙연산 계산의 결과값을 컬렉션에 저장해야 한다. -> 어떤 컬렉션에 저장할지 생각해야 한다. 
               Calculator 클래스에 저장된 연산 결과들 중 가장 먼저 저장된 데이터를 삭제하는 기능을 가진 메서드를 구현해야 한다.
               처음에는 FIFO가 생각나서 Queue를 선택하려고 했다.
               그러나 Queue는 인덱스를 통해 값을 불러오지 못한다.
  • 발단 : Calculator 클래스의 연산 결과를 저장하고 있는 컬렉션 필드의 값을 가져오지 못한다.
  • 전개 : 이에 다른 컬렉션을 찾아보게 되었다.
  • 위기 : 가장 먼저 저장된 데이터를 삭제해야 하기 때문에 순서가 있는 컬렉션을 선택해야 한다.
  • 절정 : 순서가 있는 컬렉션List가 있다.
  • 결말 : 결국 List 중 ArrayList을 선택했다.

 

가변길이의 매개변수를 어떻게 받아올 것인가?

위의 사진은 내가 고민했던 부분을 간단하게 도식화한 것이다.

Calculator 클래스의 calculte 메서드에 가변길이의 매개변수를 받고자 하니

나로서는 복잡한 생각이 들었다.

 

Q1) 매개변수 value의 타입을 String타입 배열로 받아야 하나?

Q2) App 클래스에서 num1(첫 번째 정수 입력값), num2(두 번째 정수 입력값), operator(연산자)를

       각각 int, int, char타입으로 지정했는데,

       String으로 변환해서 보내줘야 하나?

Q3) String 배열로 받아서 다시 int, int, char 타입으로 변환해야 하나?

Q4) Output은 result로? 아니면 list 형식으로 반환해야 하나?

 

비효율적으로 보이지만 나는 위의 질문사항들을 토대로 구현하기 시작했다.

 

Q1) 매개변수 value의 타입을 String타입 배열로 받기

public int calculate(String... value) {}

 

Q2) App 클래스에서 num1(첫 번째 정수 입력값), num2(두 번째 정수 입력값), operator(연산자)를

       String으로 변환해서 보내주기

String stringNum1= Integer.toString(num1);
String stringNum2= Integer.toString(num2);
String stringOperator = Character.toString(operator);

 

Q3) String 배열로 받아서 다시 int, int, char 타입으로 변환하기

int num1 = Integer.parseInt(value[0]);
int num2 = Integer.parseInt(value[1]);
char operator = value[2].charAt(0);

 

Q4) Output은 result로 반환하기, 결과값은 list 추가하기

list.add(result);
return result;

 

 

ArrayIndexOutOfBoundsException 발생

  • 배경 : ArrayIndexOutOfBoundsException이 발생했다.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
  • 발단 : 예외의 내용을 보니, 배열의 크기와 관련된 것으로 추정했다.
  • 전개 : ArrayIndexOutOfBoundsException 관련 원인을 검색해서 찾기 시작했다.
  • 위기 : 정해진 배열의 크기보다 크거나 음수 index에 대한 요청이 있으면 ArrayIndexOutOfBoundsException이 발생한다.
  • 절정 : 배열 길이가 3이고 index가 0, 1, 2에 값이 있는데 배열의 3번 값을 달라고 했으니 오류가 났다...
  • 결말 : value[3] 항상 0부터 시작하는데 잠깐 잊고 있었나보다.
char operator = value[3].charAt(0);
-> char operator = value[2].charAt(0);

 

튜터님 피드백

가변길이 매개변수 수정하기

가변길이 매개변수는 좋은 방법이 아니므로, 다른 방법으로 구현하는 것이 좋다고 하셔서 수정했다.

그 이유는 [이펙티브 자바] 책 '가변인수는 신중히 사용하라' 부분을 참고하라고 하셨다.

 

이유 : 가변인수 메서드 호출될 때마다 배열을 새로 하나 할당하고 초기화한다.

성능에 민감한 상황이라면 가변인수가 걸림돌이 될 수도 있다고 한다.

그래서 일반적으로 많이 쓰이는 개수까지 다중정의를 하고, 그 이후가변인수를 사용하기도 한다고 한다.

 

+) 추가적으로 아래와 같이 두 오버로딩된 메서드가 구분되지 않아서 컴파일에러가 발생하기도 한다.

따라서 가능하면 가변인수를 사용한 메서드는 오버로딩하지 않는 것이 좋다.

static String concatenate(String delim, String... args){} //1번
static String concatenate(String... args){} //2번

출처:자바의 정석 3판 p289

// 수정 전
public int calculate(String... value) {
		// String타입의 value 배열에 값을 받아서 각각 변수에 저장
        int num1 = Integer.parseInt(value[0]);
        int num2 = Integer.parseInt(value[1]);
        char operator = value[2].charAt(0);
        }
        
// 수정 후
 public int calculate(int num1, int num2, char operator) {/*중략*/}

 

 

삭제하시겠습니까? 기능 추가

기존에는 exit 즉 종료를 하면, 가장 먼저 저장된 데이터를 바로 삭제하고 종료하게 구현했었다.

그러나 튜터님께서 삭제하시겠습니까?라고 사용자에게 물어보는 기능을 추가하라고 하셔서 아래와 같이 구현했다.

if(exits.equals("exit")){
        System.out.println("가장 먼저 저장된 데이터를 삭제하시겠습니까? y/n");
        removeOk = sc.next();
        if(removeOk.equals("y")){
           cal.removeResult();
        }else if(removeOk.equals("n")){
           System.out.println("삭제하지 않고 종료합니다.");
        }else{
           System.out.println("삭제하지 않고 종료합니다.");
        }
        break;
}

 

0으로 나누거나 사칙연산자 외 다른 값을 입력할 경우 대처방안

switch (operator) {
            case '+':
                result = num1 + num2;
                break;
            case '-':
                result = num1 - num2;
                break;
            case '*':
                result = num1 * num2;
                break;
            case '/':
                if (num2 == 0) {
                    System.out.println("나눗셈 연산에서 분모(두번째 정수)에 0이 입력될 수 없습니다.");
                    break;
                }
                result = num1 / num2;
                break;
            default:
                System.out.println("잘못된 연산자입니다. 다시 입력해주세요.");
                break;
        }

위와 같이 작성했을 때, App 단독 클래스에서 작동할 때는 잘 되었지만

이 계산 기능을 Calculator 클래스의 계산 메소드에서 처리하게 될 경우에는

println은 잘 나오지만 리스트에 해당 값을 0으로 저장하게 되는 문제가 발생했다.

 

switch (operator) {
    case '+':
        result = num1 + num2;
        System.out.println("결과: "+num1+operator+num2+"=" + result);
        resultList.add(result);
        break;
    case '-':
        result = num1 - num2;
        System.out.println("결과: "+num1+operator+num2+"=" + result);
        resultList.add(result);
        break;
    case '*':
        result = num1 * num2;
        System.out.println("결과: "+num1+operator+num2+"=" + result);
        resultList.add(result);
        break;
    case '/':
        if (num2 == 0) {
            System.out.println("나눗셈 연산에서 분모(두번째 정수)에 0이 입력될 수 없습니다.");
            break;
        }
        result = num1 / num2;
        System.out.println("결과: "+num1+operator+num2+"=" + result);
        resultList.add(result);
        break;
    default:
        System.out.println("사칙연산자가 아닙니다. 다시 입력해주세요.");
        break;
}

따라서 위와 같이 작성을 했다.

문제 상황이 아닌 부분에는 일일이 list에 결과값을 추가했다.

코드의 가독성이 좀 안 좋아보이지만

일단 문제는 해결했으니 리팩토링에 관한 부분은 다음의 과제로 만들겠다.

 

레벨 2는 다음주까지 시간이 소요될 것이라고 생각했었다.

그런데 생각보다 구현을 하고, 어느 정도 기능의 문제는 없어서

왜 이러지? 뭔가 빠뜨린 것 이 있나?하고 의아해하는 날이었다.

그래서 계속 튜터님께 확인받기도 했다.

생각보다 일이 잘 풀려도 불안하다. :)