πŸ“š[Java] 계산기 과제

텁텁·2025λ…„ 4μ›” 16일

μžλ°” 첫 κ³Όμ œκ°€ μ£Όμ–΄μ‘Œλ‹€.
λ‹¨μˆœνžˆ 사칙연산이 λ˜λŠ” 계산기 μ½”λ“œλ₯Ό μž‘μ„±ν•  쀄 μ•Œμ•˜λŠ”λ° 생각보닀 μš”κ΅¬μ‚¬ν•­μ΄ λ§Žμ•„ μž‘μ„±μ— 쑰금 어렀움을 κ²ͺμ—ˆλ‹€.


1λ‹¨κ³„λŠ” 클래슀λ₯Ό λ‚˜λˆ„μ§€ μ•Šκ³  κ΅¬ν˜„ν•˜κ³  2λ‹¨κ³„μ—μ„œλŠ” 클래슀λ₯Ό λ‚˜λˆ„μ–΄ κ΅¬ν˜„ν•˜λŠ” μ‹μœΌλ‘œ κ³Όμ œκ°€ λ‚˜λ‰˜μ–΄ μžˆμ—ˆλ‹€.
개인적으둜 λ‹¨κ³„λ³„λ‘œ λ‚˜λˆ„μ–΄μ Έ μžˆλŠ” μ΄μœ λŠ” λ¦¬νŒ©ν† λ§ 과정을 읡히게 ν•˜λ €λŠ” μ˜λ„λΌκ³  μƒκ°ν–ˆκ³  λ”°λΌμ„œ 2단계 κ³Όμ œλŠ” 1λ‹¨κ³„μ˜ 흐름을 크게 λ°”κΎΈμ§€ μ•ŠλŠ” μ„ μ—μ„œ ꡬ쑰λ₯Ό μ •λ¦¬ν•˜κ³  κΉ”λ”ν•˜κ²Œ λ‚˜λˆ„λŠ” 것에 쀑점을 두고 μž‘μ„±μ„ μ‹œμž‘ν–ˆλ‹€.

κ³Όμ œλŠ” 두 μ •μˆ˜(x β‰₯ 0)와 '+', '-', '*', '/' μ—°μ‚°κΈ°ν˜Έλ₯Ό μž…λ ₯ λ°›μ•„ 사칙연산을 μˆ˜ν–‰ν•˜λŠ” '계산기'λ₯Ό λ§Œλ“œλŠ” κ²ƒμ΄μ—ˆλ‹€.
λ”°λΌμ„œ μ—°μ‚°λ§ˆλ‹€ 각각 λ‹€λ₯Έ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•˜κ³  μž…λ ₯된 κΈ°ν˜Έμ— 따라 ν•΄λ‹Ή μ—°μ‚° λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” λ°©μ‹μœΌλ‘œ ꡬ쑰λ₯Ό μ§°λ‹€.


1단계 과제 μ½”λ“œ

계산기 클래슀인 Calculator ν΄λž˜μŠ€μ—μ„œ λͺ¨λ“  μž‘μ—…μ„ μ²˜λ¦¬ν–ˆλ‹€.

import java.util.InputMismatchException;
import java.util.Scanner;

public class Calculator {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = 0;
        int b = 0;
        double sum = 0;
        String c = "";

        while (true) {
            //μ˜ˆμ™Έμ²˜λ¦¬
            try {
                System.out.println("---------------------");
                System.out.println("계산할 두 μ •μˆ˜λ₯Ό μž…λ ₯ν•˜μ„Έμš” (μž…λ ₯κ°’>=0)");

                System.out.print("첫 번째 μ •μˆ˜: ");
                a = sc.nextInt();
                System.out.print("두 번째 μ •μˆ˜: ");
                b = sc.nextInt();

                //음수 체크 둜직
                if(a < 0 || b < 0){
                    System.out.println("0보닀 μž‘μ€ 값을 μž…λ ₯ν–ˆμŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”!");
                    continue;
                }

                System.out.println("계산을 μ§„ν–‰ν•  μ—°μ‚° 기호λ₯Ό μž…λ ₯ν•˜μ„Έμš”.(+, -, *, /)");
                c = sc.next();

                if(c.equals("+")){
                    sum = plusInt(a, b);
                } else if(c.equals("-")){
                    sum = minusInt(a, b);
                } else if(c.equals("*")){
                    sum = timesInt(a, b);
                } else if(c.equals("/")){
                    try {
                        sum = dividedInt(a, b);
                    } catch (IllegalArgumentException e){
                        System.out.println(e.getMessage());
                        continue;
                    }
                } else {
                    System.out.println("μ§€μ›ν•˜μ§€ μ•ŠλŠ” ν˜•μ‹μž…λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.");
                    continue;
                }

                System.out.println("계산 결과값은: " + sum + " μž…λ‹ˆλ‹€.");
                sc.nextLine(); //남은 κ°œν–‰λ¬Έμž(\n) μ§€μš°κΈ°
                System.out.println("μ—”ν„°λ₯Ό λˆ„λ₯΄λ©΄ λ‹€μŒ 계산을 μ§„ν–‰ν•©λ‹ˆλ‹€. ('exit'λ₯Ό μž…λ ₯μ‹œ μ’…λ£Œλ©λ‹ˆλ‹€.)");
                c = sc.nextLine();

                if(c.equals("exit")) {
                    System.out.println("ν”„λ‘œκ·Έλž¨μ„ μ’…λ£Œν•©λ‹ˆλ‹€.");
                    break;
                }

            } catch (InputMismatchException e){
                //InputMismatchException λ°œμƒ μ‹œ μ²˜μŒλΆ€ν„° 계산을 λ‹€μ‹œ μ‹€ν–‰
                System.out.println("잘λͺ»λœ μž…λ ₯μž…λ‹ˆλ‹€. 쑰건에 맞게 μž…λ ₯ν•΄μ£Όμ„Έμš”.");
                sc.nextLine(); //버퍼 λΉ„μš°κΈ°
                continue; //흐름 λͺ…μ‹œν•΄μ£ΌκΈ° 없어도 무방
            }

        }

    }

    //사칙연산 λ©”μ„œλ“œ
    public static int plusInt(int a, int b){
        return a + b;
    }

    public static int minusInt(int a, int b){
        return a - b;
    }

    public static int timesInt(int a, int b){
        return a * b;
    }

    public static double dividedInt(int a, int b) throws IllegalArgumentException{
        if(b == 0){
            throw new IllegalArgumentException("λ‚˜λˆ„κΈ° μ§„ν–‰ μ‹œ 두 번째 값이 0이 될수 μ—†μŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.");
        }
        return (double)a / b;
    }
}

2단계 과제 μ½”λ“œ

1단계 과제λ₯Ό 사칙연산을 μˆ˜ν–‰ν•˜λŠ” Calculator ν΄λž˜μŠ€μ™€ 메인싀행을 λ‹΄λ‹Ήν•˜λŠ” App 클래슀둜 λ‚˜λˆ„μ–΄ λ¦¬νŒ©ν† λ§ν•˜μ˜€λ‹€.

1μ°¨ μˆ˜μ • : μ»¬λ ‰μ…˜μ— κ²°κ³Ό 값을 μ €μž₯ν•˜κ³  κ²Œν„°, μ„Έν„° ν™œμš© λˆ„λ½μœΌλ‘œ μΈν•œ μˆ˜μ •
2μ°¨ μˆ˜μ • : μ»¬λ ‰μ…˜ μ €μž₯κ°’ 제거 κΈ°λŠ₯ κ΅¬ν˜„ λˆ„λ½μœΌλ‘œ μΈν•œ μˆ˜μ •

import java.util.ArrayList;
import java.util.List;

public class Calculator {
    //μ—°μ‚°κ²°κ³Ό μ €μž₯ ν•„λ“œ
    private final List<Double> operationResults = new ArrayList<>();

    public double getOperationResults(){
        return operationResults.get(0);
    }

    public void clearSumList(){
        operationResults.clear();
    }

    public void setOperationResults(double sum){
        operationResults.add(sum);
    }

    //사칙연산 λ©”μ„œλ“œ
    public double plusInt(int a, int b){
        return a + b;
    }

    public double minusInt(int a, int b){
        return a - b;
    }

    public double timesInt(int a, int b){
        return a * b;
    }

    public double dividedInt(int a, int b) throws IllegalArgumentException{
        if(b == 0){
            throw new IllegalArgumentException("λ‚˜λˆ„κΈ° μ§„ν–‰ μ‹œ 두 번째 값이 0이 될수 μ—†μŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.");
        }
        return (double)a / b;
    }

    public void checkNegative(int a, int b) throws IllegalArgumentException{
        if(a < 0 || b < 0){
            throw new IllegalArgumentException("μž…λ ₯값은 μŒμˆ˜κ°€ 될 수 μ—†μŠ΅λ‹ˆλ‹€. (μž…λ ₯κ°’>=0)");
        }
    }
}
import java.util.InputMismatchException;
import java.util.Scanner;

public class App {
    public static void main(String[] args) {
        Calculator cal = new Calculator();
        Scanner sc = new Scanner(System.in);
        int a = 0;
        int b = 0;
        String c = "";

        while (true) {
            //μ˜ˆμ™Έμ²˜λ¦¬
            try {
                System.out.println("---------------------");
                System.out.println("계산할 두 μ •μˆ˜λ₯Ό μž…λ ₯ν•˜μ„Έμš” (μž…λ ₯κ°’>=0)");

                System.out.print("첫 번째 μ •μˆ˜: ");
                a = sc.nextInt();
                System.out.print("두 번째 μ •μˆ˜: ");
                b = sc.nextInt();

                //음수 체크 λ©”μ„œλ“œ
                cal.checkNegative(a, b);

                System.out.println("계산을 μ§„ν–‰ν•  μ—°μ‚° 기호λ₯Ό μž…λ ₯ν•˜μ„Έμš”.(+, -, *, /)");
                c = sc.next();

                if(c.equals("+")){
                    cal.setOperationResults(cal.plusInt(a, b));
                } else if(c.equals("-")){
                    cal.setOperationResults(cal.minusInt(a, b));
                } else if(c.equals("*")){
                    cal.setOperationResults(cal.timesInt(a, b));
                } else if(c.equals("/")){
                    try {
                        cal.setOperationResults(cal.dividedInt(a, b));
                    } catch (IllegalArgumentException e){
                        System.out.println(e.getMessage());
                        continue;
                    }
                } else {
                    System.out.println("μ§€μ›ν•˜μ§€ μ•ŠλŠ” ν˜•μ‹μž…λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.");
                    continue;
                }

                System.out.println("계산 결과값은: " + cal.getOperationResults() + " μž…λ‹ˆλ‹€.");
                sc.nextLine(); //남은 κ°œν–‰λ¬Έμž(\n) μ§€μš°κΈ°

                //계산기 μ €μž₯κ°’ λΉ„μš°κΈ°
                cal.clearSumList();

                System.out.println("μ—”ν„°λ₯Ό λˆ„λ₯΄λ©΄ λ‹€μŒ 계산을 μ§„ν–‰ν•©λ‹ˆλ‹€. ('exit'λ₯Ό μž…λ ₯μ‹œ μ’…λ£Œλ©λ‹ˆλ‹€.)");
                c = sc.nextLine();

                if(c.equals("exit")) {
                    System.out.println("ν”„λ‘œκ·Έλž¨μ„ μ’…λ£Œν•©λ‹ˆλ‹€.");
                    break;
                }

            } catch (InputMismatchException e){
                //InputMismatchException λ°œμƒ μ‹œ μ²˜μŒλΆ€ν„° 계산을 λ‹€μ‹œ μ‹€ν–‰
                System.out.println("잘λͺ»λœ μž…λ ₯μž…λ‹ˆλ‹€. 쑰건에 맞게 μž…λ ₯ν•΄μ£Όμ„Έμš”.");
                sc.nextLine(); //버퍼 λΉ„μš°κΈ°
                continue; //흐름 λͺ…μ‹œν•΄μ£ΌκΈ° 없어도 무방
            } catch (IllegalArgumentException e){
                System.out.println(e.getMessage());
                continue; //흐름 λͺ…μ‹œν•΄μ£ΌκΈ° 없어도 무방
            }

        }
    }
}

μ²˜μŒμ—λŠ” μž…λ ₯κ°’ a, b κ°€ μ •μˆ˜μ΄κΈ° λ•Œλ¬Έμ— 결과값을 μ €μž₯ν•˜λŠ” sum λ³€μˆ˜λ„ int둜 μ„ μ–Έν–ˆλŠ”λ° λ‚˜λˆ—μ…ˆμ„ κ΅¬ν˜„ν•˜λ©΄μ„œ int / int 연산은 μ†Œμˆ˜μ  μ΄ν•˜λ₯Ό 버렀 μ •ν™•ν•œ κ²°κ³Όλ₯Ό μ–»κΈ° μ–΄λ ΅λ‹€λŠ” κ±Έ κΉ¨λ‹¬μ•˜λ‹€.

κ·Έλž˜μ„œ sum λ³€μˆ˜λ₯Ό double ν˜•μœΌλ‘œ λ°”κΎΈκ²Œ λ˜μ—ˆκ³  ν•΄λ‹Ή κ³Όμ •μ—μ„œ double 은 int 보닀 큰 μžλ£Œν˜•μœΌλ‘œ μžλ™ ν˜•λ³€ν™˜μ΄ λ˜μ–΄ λ©”μ„œλ“œλ“€μ„ μˆ˜μ •ν•˜μ§€ μ•Šμ•˜μ§€λ§Œ λ‚˜λˆ—μ…ˆμ—μ„œλŠ” μ‹€μˆ˜ κ²°κ³Όλ₯Ό μ–»κΈ° μœ„ν•΄ (double)a / b 둜 ν˜•λ³€ν™˜μ„ 해쀬닀.

μ΄ˆκΈ°μ—λŠ” μž…λ ₯된 νƒ€μž…μ΄ λ§žμ§€ μ•ŠμœΌλ©΄ λ°œμƒν•˜λŠ” InputMismatchException 을 μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄ 반볡문 전체λ₯Ό 감싸고 μžˆλŠ” ν˜•νƒœλ‘œ try-catch 문을 μž‘μ„±ν–ˆλ‹€.
ν•˜μ§€λ§Œ int ν˜•μœΌλ‘œ κ΅¬ν˜„ν•œ λ‚˜λˆ„κΈ° λ©”μ„œλ“œμ—μ„  λ³€μˆ˜ b 의 값이 0일 경우 ArithmeticException μ˜ˆμ™Έκ°€ λ°œμƒν–ˆκ³  ν•΄λ‹Ή μ˜ˆμ™Έμ— λŒ€ν•΄μ„œλ„ μ²˜λ¦¬ν•΄μ•Ό ν–ˆλ‹€.

전체 try-catch 문에 ν•΄λ‹Ή μ˜ˆμ™Έμ— λŒ€ν•œ catch 문을 μΆ”κ°€ν•˜λŠ”κ²Œ κΉ”λ”ν•˜λ‹€λŠ” 생각이 λ“€μ—ˆμ§€λ§Œ λ‚˜λˆ„κΈ° λ©”μ„œλ“œμ—μ„œλ§Œ ν•΄λ‹Ή μ˜ˆμ™Έκ°€ λ°œμƒν•˜κΈ°μ— 이λ₯Ό λͺ…μ‹œν•˜κΈ° μœ„ν•΄ ν•΄λ‹Ή κ΅¬λ¬Έμ—λ§Œ λ”°λ‘œ try-catch 문을 μΆ”κ°€ν•˜μ˜€λ‹€.

그런데 μ‹€μˆ˜ν˜• λ‚˜λˆ—μ…ˆμœΌλ‘œ λ°”κΎΈκ³  λ‚˜λ‹ˆ λ³€μˆ˜ b 의 값에 0을 넣어도 μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ§€ μ•Šμ•˜κ³ 
였히렀 Infinity λΌλŠ” 값이 좜λ ₯됐닀. 이건 μ‹€μˆ˜ν˜• 자료λ₯Ό 0으둜 λ‚˜λˆŒλ•Œ λ°œμƒν•˜λŠ” κ°’μœΌλ‘œ μžλ°”μ—μ„œ 였λ₯˜λ‘œ μΈμ‹ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μ΄μ „μ²˜λŸΌ μ˜ˆμ™Έ 처리둜 κ±ΈλŸ¬λ‚Ό 수 μ—†μ—ˆλ‹€.

κ·Έλž˜μ„œ μ²˜μŒμ—” Exception 클래슀λ₯Ό μ΄μš©ν•΄ κ°•μ œλ‘œ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λ„λ‘ ν–ˆλŠ”λ° Exception 은 λ„ˆλ¬΄ 포괄적인 μ˜ˆμ™ΈλΌ 상황에 μ–΄μšΈλ¦¬λŠ” μ˜ˆμ™Έ νƒ€μž…μ΄ μ•„λ‹ˆλΌκ³  λŠκΌˆλ‹€.
ν•΄λ‹Ή 상황은 '잘λͺ»λœ 값’을 λ„˜κΈ΄ κ²½μš°λ‹ˆκΉŒ IllegalArgumentException 이 더 μ μ ˆν•˜λ‹€κ³  νŒλ‹¨ν–ˆκ³  μˆ˜μ •μ„ μ§„ν–‰ν–ˆλ‹€.

μ΅œμ’…μ μœΌλ‘œ λ³€μˆ˜ b 의 값이 0일 λ•Œ "λ‚˜λˆ„κΈ° μ§„ν–‰ μ‹œ 두 번째 값이 0이 될수 μ—†μŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”." λΌλŠ” λ©”μ„Έμ§€κ°€ λ‹΄κΈ΄ IllegalArgumentException 을 λͺ…μ‹œμ μœΌλ‘œ λ°œμƒμ‹œμΌ°κ³  catch 문에 e.getMessage() λ©”μ„œλ“œλ₯Ό 톡해 μ˜ˆμ™Έ λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•˜κ²Œ λ§Œλ“€μ—ˆλ‹€. μ΄λ ‡κ²Œ ꡬ쑰λ₯Ό λ°”κΎΈλ©΄μ„œ 0으둜 λ‚˜λˆ„λŠ” 상황을 μ’€ 더 λͺ…ν™•ν•˜κ²Œ μ²˜λ¦¬ν•  수 μžˆμ—ˆκ³  ν”„λ‘œκ·Έλž¨ 흐름도 μžμ—°μŠ€λŸ½κ²Œ μ΄μ–΄κ°ˆ 수 μžˆμ—ˆλ‹€.

1μ°¨ μˆ˜μ •

2단계 과제의 μš”κ΅¬μ‚¬ν•­μΈ μ»¬λ ‰μ…˜ ν™œμš©μ„ λˆ„λ½ν•΄μ„œ μΆ”κ°€ μž‘μ—…μ„ μ§„ν–‰ν–ˆλ‹€.
λ¦¬μŠ€νŠΈμ— κ°„μ ‘μ μœΌλ‘œ μ ‘κ·Όν•΄ 결과값을 κ°€μ Έμ˜€κ³  μˆ˜μ •ν•  수 μžˆλ„λ‘ κ²Œν„°, μ„Έν„° λ©”μ„œλ“œλ„ μΆ”κ°€λ‘œ κ΅¬ν˜„ν•˜μ˜€λ‹€.
λ‚΄κ°€ κ΅¬ν˜„ν•œ μ„Έν„°λŠ” κΈ°λŠ₯적인 μ˜λ―Έμ—μ„  λΉ„μŠ·ν•œλ° 일반적인 μ„Έν„°μ™€λŠ” ꡬ쑰적으둜 차이가 μžˆμ–΄ 이 뢀뢄에 λŒ€ν•΄μ„œ νŠœν„°λ‹˜κ»˜ μ§ˆλ¬Έμ„ λ“œλ Έλ‹€.
νŠœν„°λ‹˜λ„ "값을 μ„€μ •ν•˜λŠ” 세터보단 μ €μž₯에 κ°€κΉŒμš΄ λŠλ‚Œμ΄μ§€λ§Œ ν˜„ 상황에선 μš”κ΅¬μ‚¬ν•­μ— λΆ€ν•©ν•˜λŠ” κ΅¬ν˜„μ΄λΌκ³  μƒκ°ν•œλ‹€." 라고 λ‹΅λ³€ν•΄ 주셨기에 λ‹€λ₯Έ μˆ˜μ • 사항은 κ±°μΉ˜μ§€ μ•Šκ³  λ§ˆλ¬΄λ¦¬ν•˜μ˜€λ‹€.
μΆ”κ°€μ μœΌλ‘œ λ¦¬νŒ©ν† λ§μ΄λž€ 기쑴의 μ½”λ“œλ₯Ό κ·ΈλŒ€λ‘œ κ°€μ Έκ°€λŠ” 것이 μ•„λ‹ˆλΌκ³  μ•Œλ €μ£Όμ…¨μ§€λ§Œ μ΅œλŒ€ν•œ ꡬ쑰λ₯Ό λ³€κ²½ν•˜μ§€ μ•Šκ³  μž‘μ„±ν•˜κΈΈ μ›ν–ˆλ˜ 초기의 μž‘μ„± μ˜λ„λ₯Ό λ“€μœΌμ‹œκ³ λŠ” 이해해주셨닀.

2μ°¨ μˆ˜μ •

μš”κ΅¬μ‚¬ν•­ 쀑 μ»¬λ ‰μ…˜ μ €μž₯κ°’ 제거 κΈ°λŠ₯이 μžˆμ—ˆλŠ”λ° λˆ„λ½ν•΄μ„œ μˆ˜μ •ν•˜μ˜€λ‹€.
ν•œ 번의 반볡이 μ’…λ£Œλ˜κΈ° 전에 μ €μž₯값을 λΉ„μš°λŠ” λ©”μ„œλ“œκ°€ μ‹€ν–‰λ˜λŠ” ꡬ쑰둜 변경됨에 따라 Getter() λŠ” operationResults.(operationResults.size()-1) : λ§ˆμ§€λ§‰ μ €μž₯κ°’ 좜λ ₯이 μ•„λ‹Œ operationResults.get(0) : 0번째 인덱슀의 μ €μž₯κ°’μœΌλ‘œ λ³€κ²½ν•˜μ˜€λ‹€.

3단계 λ„μ „κ³Όμ œλŠ” enum, μ œλ„€λ¦­, λžŒλ‹€, μŠ€νŠΈλ¦Όμ„ λͺ¨λ‘ μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” κ³Όμ œμ΄λ‹€.
슀슀둜 λŠλΌκΈ°μ— ν•™μŠ΅μ΄ λΆ€μ‘±ν•˜λ‹€λŠ” νŒλ‹¨μ΄ λ“€μ–΄ 쑰금 더 ν•™μŠ΅μ„ μ§„ν–‰ν•œ 후에 μ‹œμž‘ν•  μ˜ˆμ •μ΄λ‹€.


profile
μ°¨κ·Όμ°¨κ·Ό

0개의 λŒ“κΈ€