Today I Learned

2024 스파르타 내일배움캠프 Sping 트랙 참여 // day9

shinelee26 2024. 10. 14. 23:34

오늘 진행한 학습 요약

1. 알고리즘 특강 1회차

  • 알고리즘이란?
  • 자료구조란?
  • 시간복잡도 (Big-O 표기법)

2. 새싹반 수업

  • 새싹반 1회차 (JVM, 변수)

3. [CH 2 프로그래밍 기초 개인 과제]  Java로 계산기 만들기

  • 클래스를 활용하지 않는 계산기
    • 주요 코드 작성 내용
    • 트러블 슈팅
  • 클래스를 활용하는 계산기
    • 주요코드 작성내용
    • 트러블 슈팅

학습 정리

1. 알고리즘 특강 1회차

  • 알고리즘이란?
    • 알고리즘은 특정문제를 해결하거나 작업을 수행하기 위한 단계적 절차
    • 주어진 입력을 받아 목표한 출력을 생성하는 논리적인 과정을 포함
    • >> 결론적으로 얼마나 효율적으로 얼마나 빠르게 결과를 만들 수 있는지 방법을 찾는 과정
  • 자료구조란?
    • 효율적인 접근 및 수정을 가능하게 하는 자료의 조직, 관리, 저장을 의미
    • 데이터 값의 모임, 또 데이터 간의 관계, 그리고 데이터에 적용할 수 있는 함수나 명령을 의미
    • 자료구조의 필요성
      • 효율적인 데이터 관리
      • 데이터 조직
      • 재사용성
      • 알고리즘 최적화
    • 자료구조의 종류
      • 배열 (Array)
      • 리스트 (ArrayList)
      • 세트 (HashSet)
      • 맵 (HashMap)
      • 스택 (Stack)
      • 큐(Queue)
  • 시간복잡도 (Big-O 표기법)
    • 시간복잡도는 알고리즘이 실행될 때 필요한 입력값과 연산 수행 시간에 따라 효율적인 알고리즘을 나타내는 척도를 의미
    • 입력값이 커질수록 알고리즘의 수행 시간이 어떻게 증가하는지 지표를 의미
    • 시간 복잡도는 빅오 표기법(Big-O notation)를 통해 표현, 수치가 작을수록 효율적인 알고리즘을 의미
    • 빅오(Big-O) 표기법
      • 알고리즘의 입력 크기에 대해 수행 시간이 어떤 방식으로 증가하는지를 표기하는 것으로 최악의 경우의 시간 복잡도를 의미


2. 새싹반 수업

  • 새싹반 1회차 (JVM, 변수)
깨끗한 코드는 단순하고 직접적이다. 깨끗한 코드는 잘 쓴 문장처럼 잘 읽히고 설계자의 의도를 바로 알 수 있다. 오히려 명쾌한 추상화와 단순한 제어문으로 가득하다 코드는 추측이아니라 사실에 기반해야한다. 반드시 필요한 내용만 담아야하며 단호하게 끝내야한다.

 

  • JVM
    • Java 애플리케이션은 JVM을 한번 더 거치고 하드웨어에 맞게 완전히 컴파일된 상태가 아니라 실행시에 해석되기 때문에 속도가 느리다.
    • 하지만 OS에 종속적이지 않다는 장점을 가지고 있다.
  • JVM의 구조 (핵심만!)
    • Class Loader : java 파일을 javac Compiler로 compile 하게 되면 .class 파일의 바이트 코드 생성
                              생성된 클래스 파일들을 RunTime Data Area로 각각 적재
    • Execution Engine : Class Loader에 의해 메모리에 각각 적재된 클래스들을 기계어로 변경해 명렁어 단위로 실행
    • Garbage Collector : heap 메모리 영역에 생성된 객체들 중에 참조되지 않는 객체들을 탐색후 제거
    • Runtime Data Area : JVM의 메모리 영역으로 자바애플리케이션을 실행할때 사용되는 데이터들을 적재
    • Method Area : 필드 정보, 메소드 정보, 변수등이 생성되는 영역
    • Heap Area : new 키워드로 생성된 객체와 배열이 생성되는 영역
    • Stack Area : 지역변수, 파라미터, 리턴값 연산에 사용되는 임시 값 등이 생성되는 영역
    • PC Register : Thread가 생성될때마다 생성되는 영역 Program Counter
    • Native Stack Area: 네이티브 코드를 위한 메모리 영역
  • Java의 실행 규칙

  • 변수란?
    • 값을 정할 수 있는 메모리 공간
    • 변하는 수
  • 변수에 타입이 있는 이유
    • 컴퓨터는 0과 1로만 이루어져 있어 computer가 타입이 없으면 한글을 숫자로 읽어버림
  • 네이밍 컨벤션
    • 패키지 이름
      • 소문자로 구성!
      • 언더스코어나 대문자를 섞지 않음
    • 클래스 이름
      • 명사나 명사절로 지음
      • 대문자 카멜표기법 적용
        • AccessToken
    • 인터페이스 이름
      • 명사나 형용사 사용
      • 대문자 카멜표기법 적용
        • AccessToken
    • 메서드 이름
      • 동사나 전치사로 시작
      • 소문자 카멜표기법 적용
    • 상수
      • 대문자와 언더스코어로 구성
    • 변수 
      • 소문자 카멜표기법 적용
      • 임시 변수 외에는 1글자 사용 금지
    • 조건 / 반복문에 중괄호 필수 사용
    • K&R 스타일로 중괄호 선언
public class SearchConditionParser {
    public boolean isValidExpression(String exp) {

        if (exp == null) {
            return false;
        }

        for (char ch : exp.toCharArray()) {
            ....
        }

        return true;
    }
}

3. [CH 2 프로그래밍 기초 개인 과제]  Java로 계산기 만들기

  • 클래스를 활용하지 않는 계산기
    • 클래스를 활용하지 않는 계산기로 Java의 기본 문법으로 작성하였다.
      • 나눗셈 연산에서 분모가 0일 경우 계산 실패 알림이 뜨도록 수정하였다.
      • if문사용이 많이져 if문이 아닌 Case문을 활용해서 가독성이 높게 작성해볼 예정이다.
더보기
더보기
package NoClassCalculrator;

import java.util.Scanner;

public class App {
    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        System.out.println("==========noClass 사칙연산 계산기==========");

        System.out.print("원하는 조건문을 선택하세요(if, while, case) : ");
        String option = scanner.nextLine();

        switch (option) {
            // 1. IF문으로 조건을 만족할 경우 계산하도록 작성
            case "if":
                // 첫번째 계산할 숫자 입력
                System.out.print("첫번째 숫자를 입력하세요 : ");
                int firstNum0 = scanner.nextInt();
                // 두번째 계산할 숫자 입력
                System.out.print("두번째 숫자를 입력하세요 : ");
                int secondNum0 = scanner.nextInt();
                // 계산에 사용할 사칙연산 기호 입력
                System.out.print("원하는 사칙연산 기호를 입력하세요(+, -, *, /) : ");
                char operator0 = scanner.next().charAt(0);

                if (firstNum0 >= 0 && secondNum0 >= 0) {
                    if (operator0 == '+') {
                        System.out.println("결과 : " + (firstNum0 + secondNum0));
                    } else if (operator0 == '-') {
                        System.out.println("결과 : " + (firstNum0 - secondNum0));
                    } else if (operator0 == '*') {
                        System.out.println("결과 : " + (firstNum0 * secondNum0));
                    } else if (operator0 == '/') {
                        if (secondNum0 == 0) {
                            System.out.println("나눗셈 연산에서 분모(두번째 정수)에 0이 입력될 수 없습니다.");
                        } else {
                            System.out.println("결과 : " + (firstNum0 / secondNum0));}
                    } else {
                        System.out.println("사칙연산 값을 잘못 입력하셨습니다.");
                    }
                } else { // 양의 정수를 입력하지 않을 경우 알림
                    if (firstNum0 < 0 && secondNum0 < 0) {
                        System.out.println("양의 정수를 입력하세요.");
                    } else if (firstNum0 < 0) {
                        System.out.println("첫번째 자리에 양의 정수를 입력하세요.");
                    } else {
                        System.out.println("두번째 자리에 양의 정수를 입력하세요.");
                    }
                }
                System.out.println("=========================================");
                break;


            // 2. while문으로 특정 조건을 만족하기 전까지 연산을 반복하도록 작성
            case "while":
                while (true) {
                    System.out.print("첫번째 숫자를 입력하세요 : ");
                    int firstNum1 = scanner.nextInt();
                    // 두번째 계산할 숫자 입력
                    System.out.print("두번째 숫자를 입력하세요 : ");
                    int secondNum1 = scanner.nextInt();
                    // 계산에 사용할 사칙연산 기호 입력
                    System.out.print("원하는 사칙연산 기호를 입력하세요(+, -, *, /) : ");
                    char operator1 = scanner.next().charAt(0);
                    scanner.nextLine();

                    if (firstNum1 >= 0 && secondNum1 >= 0) {
                        if (operator1 == '+') {
                            System.out.println("결과 : " + (firstNum1 + secondNum1));
                        } else if (operator1 == '-') {
                            System.out.println("결과 : " + (firstNum1 - secondNum1));
                        } else if (operator1 == '*') {
                            System.out.println("결과 : " + (firstNum1 * secondNum1));
                        } else if (operator1 == '/') {
                            if (secondNum1 == 0) {
                                System.out.println("나눗셈 연산에서 분모(두번째 정수)에 0이 입력될 수 없습니다.");
                            } else {
                            System.out.println("결과 : " + (firstNum1 / secondNum1));}
                        } else {
                            System.out.println("사칙연산 값을 잘못 입력하셨습니다.");
                        }
                    } else { // 양의 정수를 입력하지 않을 경우 알림
                        if (firstNum1 < 0 && secondNum1 < 0) {
                            System.out.println("양의 정수를 입력하세요.");
                        } else if (firstNum1 < 0) {
                            System.out.println("첫번째 자리에 양의 정수를 입력하세요.");
                        } else {
                            System.out.println("두번째 자리에 양의 정수를 입력하세요.");
                        }
                    }
                    System.out.println("더 계산을 원하시면 아무키나 눌러주세요 (exit 입력 시 종료)");
                    String answer = scanner.nextLine();

                    if (answer.equals("exit")) {
                        break;
                    } else {
                        System.out.println("=========================================");
                    }
                }

//            // 3. Case문으로 계산기 작성
//            case "case":
//                while (true) {
//                    System.out.print("첫번째 숫자를 입력하세요 : ");
//                    int firstNum2 = scanner.nextInt();
//                    // 두번째 계산할 숫자 입력
//                    System.out.print("두번째 숫자를 입력하세요 : ");
//                    int secondNum2 = scanner.nextInt();
//                    // 계산에 사용할 사칙연산 기호 입력
//                    System.out.print("원하는 사칙연산 기호를 입력하세요(+, -, *, /) : ");
//                    char operator2 = scanner.next().charAt(0);
//                    scanner.nextLine();



                }
        }
    }

  • 클래스를 활용하는 계산기
    • 클래스를 활용하는 계산기로 기존 작성한 클래스를 활용하지 않는 계산기에서 작성한 문법을 바탕으로 작성하였다.
      • App.java클래스(메인메서드)와 Calculator클래스를 생성하여 작업하였다.
      • input은 클래스에서 계산 및 배열은 Calculator클래스에서 구현하였다.
      • 계산의 결과값을 변수 result로 주고 result는 ArrayList resultlist로 삽입되게 하였다.
      • 인덱스를 삭제할 수 있도록 삭제를 묻고 input값을 받는 부분을 구현하였다.
      • 정상적으로 계산 및 인덱스 삭제가 되는 것을 확인한 후 Calculator 필드에 private로 캡슐화를 하였다.
      • 배열값에 접근할 수 있도록 Getter와 Setter를 구현하였다.
    •  트러블 슈팅 내용
      • private주자 메인메서드가 실행이 되지 않는 것을 알게되었다.
      • 이를 실행하기 위해서 resultlist 배열을 가져오는 public메서드와 입력된 값으로 배열값을 삭제하는 public 메서드를 구현해야 했다. (앞에서부터 삭제하라는 요구사항이 있어 내일 코드를 재수정해야겠다.)
      • 하지만 코드 작성중에 계속 오류가 떴고 알고보니 중괄호를 제대로 삭제하지 않아 발생하였다.
      • 코드 작성 과정중 Arraylist의 사용코드가 헷갈려 구글링을 진행하였다.
      • Getter로 Arraylist의 전체 배열을 가지고 올 수 없다는 구글 검색결과에 헤매였다.
      • return값으로 resultlist를 주니 전체 배열이 출력되었다.
      • 배열에서 원하는 순서를 삭제하기 위해서 index값을 줘야한다는 사실을 알게 되었다.
더보기
더보기
package ClassCalculrator;

import java.util.ArrayList;

public class Calculator {

    // 필드 선언, private으로 클래스 내부에서만 읽을 수 있게
    private ArrayList<Integer> resultlist = new ArrayList<>();
    private int result = 0; // 결과값에 대한 기본값을 0으로 줌
    // firstNum : input 첫번째 대입 숫자
    // secondNum : input 두번째 대입 숫자
    // operator : input 사칙연산 대입자

    // 계산 및 오류검증
    public int cal(int firstNum, int secondNum, char operator) {
        if (firstNum >= 0 && secondNum >= 0) {
            if (operator == '+') {
                System.out.println("결과 : " + (firstNum + secondNum));
                result = firstNum + secondNum;
            } else if (operator == '-') {
                System.out.println("결과 : " + (firstNum - secondNum));
                result = firstNum - secondNum;
            } else if (operator == '*') {
                System.out.println("결과 : " + (firstNum * secondNum));
                result = firstNum * secondNum;
            } else if (operator == '/') {
                if (secondNum == 0) {
                    System.out.println("나눗셈 연산에서 분모(두번째 정수)에 0이 입력될 수 없습니다.");
                    return 0;
                } else {
                    System.out.println("결과 : " + (firstNum / secondNum));
                    result = firstNum / secondNum;
                }
            } else {
                System.out.println("사칙연산 값을 잘못 입력하셨습니다.");
                return 0;
            }
        } else { // 양의 정수를 입력하지 않을 경우 알림
            if (firstNum < 0 && secondNum < 0) {
                System.out.println("양의 정수를 입력하세요.");
                return 0;
            } else if (firstNum < 0) {
                System.out.println("첫번째 자리에 양의 정수를 입력하세요.");
                return 0;
            } else {
                System.out.println("두번째 자리에 양의 정수를 입력하세요.");
                return 0;
            }
        }

        // 결과값인 result를 resultlist에 저장
        resultlist.add(result);
        return result;
    }

    // 결과 리스트 반환 (getter)
    public ArrayList<Integer> getResultlist() {
        return resultlist;
    }

    // 결과 리스트에서 특정 인덱스 값 삭제 (setter)
    public void setRemoveResult(int index) {
        if (index < resultlist.size()) { // index사이즈가 index사이즈보다 작으면 실행되도록
            resultlist.remove(index);
            System.out.println("결과가 성공적으로 삭제되었습니다.");
        } else {
            System.out.println("잘못된 인덱스입니다. 삭제할 수 없습니다.");
        }
    }
}

더보기
더보기
package ClassCalculrator;

import java.util.Scanner;

public class App {
    public static void main(String[] args) {
        // Calculator 메서드
        Calculator calculator = new Calculator();
        // 입력 생성
        Scanner scanner = new Scanner(System.in);

        System.out.println("==========Class 사칙연산 계산기==========");

        while (true) {
            System.out.print("첫번째 숫자를 입력하세요 : ");
            int firstNum = scanner.nextInt();
            // 두번째 계산할 숫자 입력
            System.out.print("두번째 숫자를 입력하세요 : ");
            int secondNum = scanner.nextInt();
            // 계산에 사용할 사칙연산 기호 입력
            System.out.print("원하는 사칙연산 기호를 입력하세요(+, -, *, /) : ");
            char operator = scanner.next().charAt(0);
            scanner.nextLine();

            // 결과 값 반환
            int result = calculator.cal(firstNum, secondNum, operator);
            System.out.println("");

            // resultlist에 저장된 값 출력
            System.out.println("저장된 결과값 :" + calculator.getResultlist());
            // resultlist에 저장된 결과값 삭제
            System.out.println("결과값을 삭제하고 싶으시면 y 아니면 n을 입력해주세요");
            String removeAnswer = scanner.nextLine();
            if (removeAnswer.equals("n")) {
                continue;
            } else if (removeAnswer.equals("y")) {
                System.out.println("삭제하고 싶은 인덱스 번호를 입력하세요");
                int indexRemove = scanner.nextInt(); // 삭제하고싶은 인덱스값 입력
                calculator.setRemoveResult(indexRemove); // set으로 입력된 인덱스 수정
                System.out.println("수정 후 결과값 : " + calculator.getResultlist());
                System.out.println("");

                // 재 계산 여부 물어보기
                System.out.println("더 계산을 원하시면 아무키나 눌러주세요 (exit 입력 시 종료)");
                String answer = scanner.nextLine();
                scanner.nextLine();

                if (answer.equals("exit")) {
                    break;
                } else {
                    System.out.println("=========================================");
                }
            }

        }
    }
}