서브쿼리?

하나의 SQL 문 안에 포함된 또 다른 SQL , 메인쿼리 실행 전 1번 실행된다

SELECT / FROM / WHERE / HAVING 등에 사용되며

비교 연산 시 반드시 오른쪽에 쓰고 , 괄호 안에 쓰며 개수와 자료형을 일치시킨다

유형

1. 단일행 : 서브쿼리 결과값이 1개이며 앞에 비교연산자 가능( > < = ...)

2. 다중행 : 서브쿼리 조회 결과값이 여러행으로 나오며 비교연산자를 쓸 수 없다

                                    

  --그러므로 다음을 사용한다.

  • IN / NOT IN :  한개라도 일치하는 것이 존재
  • >ANY , <ANY : 여러 결과보다 하나라도 크다, 작다
    • 가장 작은것보다 크다 / 가장 큰값보다 작다 를 의미한다
  • >ALL, <ALL : 모든 값보다 크다 ,작다 의미
  • (NOT) EXISTS : 값이 존재 하는지 아닌지 여부

3. 다중열 : 서브쿼리 컬럼수가 여러개이다.

 

    비교 컬럼을 동일하게 서브쿼리를 작성해야 한다

     ->( 1 ,  2 )  IN ( SELECT  1  ,  2  FROM ~~~) 

4. 다중행 다중열 : 서브쿼리 개수, 행이 여러개다

5. 상관쿼리 :

  메인 쿼리의 값이 바뀌면 서브쿼리에도 영향을 줘 바뀌는 상호 연관 쿼리이다.

6. 스칼라쿼리 : 상관쿼리 중 결과 값이 1개인 서브쿼리

7. 인라인 뷰 : FROM 절에 사용하는 경우로 서브쿼리 결과를 테이블로 사용

   TOP-N분석에 사용할 수 있다 (ROWNUM OR RANK() OVER / DENSE_RANK() )

  * WITH 로 서브쿼리에 별칭을 주고 따로 사용할 수 있다

   - WITH (별칭 ) AS (서브쿼리) 

     SELECT ~ FROM (별칭) ;

 

 

여러 테이블을 합쳐서 합집합 교집합을 만들 수 있고 하나의 결과값으로도 만들 수 있다

 

-집합 연산자

  • UNION : 합집합
  • UNION ALL : 중복을 포함한 합집합
  • INTERSECT : 교집합
  • MINUS : 차집합

-JOIN = 하나 이상의 테이블에서 데이터를 조회 시 사용

 

1. INNER JOIN : 연결되는 컬럼의 값이 일치하는 행들만 조회 (없으면 제외됨)

(EX) SELECT A.컬럼 , B.컬럼

        FROM A 

        JOIN B ON A.컬럼 = B.컬럼 ; 

(두 컬럼명이 같으면

JOIN B USING (같은 컬럼명)

NATURAL JOIN B 로 가능 )

 

2. OUTER JOIN

 LEFT/ RIGHT / FULL JOIN : 해당 테이블을 기준으로해서 일치하지 않아도 포함됨

3. CROSS JOIN : 교차 해서 조인 결과가 나옴

 --주로 조인이 잘못된 경우 나온다

4. NATURAL JOIN : 컬럼명이 같은 경우 사용

5. 다중 JOIN : 여러번 JOIN 가능하며 순서가 영향을 미친다.

 

함수 : 컬럼의 값을 읽어서 계산 결과 반환

  1. 단일행 -> N개를 읽어서 N개를 반환
  2. 그룹 -> N개를 읽어서 1개 반환

<단일행 함수>

1. 문자열 관련 함수

  • LENGTH() : 글자수 반환
  • INSTR('문자열', '찾는 문자' , 시작점, N번째 문자) : 해당 문자 찾아 인덱스 반환, 시작점이 -1이면 거꾸로
  • TRIM() : 양쪽 공백제거
  • LTRIM / RTRIM : 왼쪽 오른쪽 공백제거
  • LPAD /RPAD : 왼쪽 오른쪽에 문자 덧붙히기
  • LOWER : 소문자로
  • UPPER : 대문자로
  • INITCAP : 카멜표기법으로

2. 숫자함수

  • ABS() 절대값
  • MOD() 나머지 구하기
  • ROUND() 반올림, 자릿수 지정가능
  • CEIL() 올림
  • FLOOR() 내림
  • TRUNC() 버림

3. 날짜함수

  • SYSDATE :현재 DATE
  • SYSTIMESTAMP : 밀리세컨드까지 반환
  • MONTHS_BETWEEN (1, 2) : 1 과 2의 개월수 차이
  • ADD_MONTHS() : N개월 후
  • TO_CHAR : 숫자 ,날짜 -> 문자 타입으로 바꿈
  • TO_DATE : 날짜 형태 문자,숫자 -> 날짜 타입으로 바꿈

4. 형변환 함수

  • TO_NUMBER : 문자 -> 숫자
    • TO_NUMBER('1,000,000' , '9,999,999') => 1000000 으로 형식있는 문자를 숫자로 가능
    • 반대로
    • TO_CHAR(1000000,'L9,999,999' => \1,000,000 으로 형식있는 문자로도 변환 

5. NULL 처리함수

  • NVL(컬럼 , NULL일 경우의 값) = NULL인 경우의 결과값을 지정할 수 있다
  • NVL2(컬럼, NULL아닌경우, NULL인 경우 값) = NULL이 아닌경우 까지도 설정할 수 있다
  • NULLIF(A,B) : A=B 이면 NULL을 A<> B 이면 A를 나타낸다

6. 선택함수 : 여러 경우(조건) 에 따라 원하는 값을 선택할 수 있도록 한다

 -DECODE(계산식/컬럼 , 조건1, 값1 ,조건2, 값2 ... 조건N, 값 N , DEFAULT값 )

 

 -CASE

    WHEN ~ THEN ~

    ... 반복 ...(여러개 가능)

   END  


<그룹 함수>

  1. SUM, AVG , MAX, MIN
    1. AVG 는 계산시 NULL을 제외시킨다
    2. MAX 와 MIN 는 숫자 뿐만 아니라 문자와 날짜에도 적용된다
  2. COUNT()
    1. COUNT(*) + GROUP BY = 갯수가 0인 경우 출력이 되지 않는다
    2. COUNT(~~) 로만 사용해야 0도 포함해 출력된다.

* GROUP BY : 같은 값들을 하위 그룹으로 묶음 

                  -SELECT 문에는 묶은 컬럼 OR 그룹함수만 올 수 있게 제한된다.

(집계함수 ROLLUP / CUBE) ->GROUP BY 뒤에 사용해서 엑셀처럼 중간 집계 , 최종 집계를 볼 때 사용한다

 

 

 

Data = 값 (----Data 기반 의미부여---->) = Information

 

*DATABASE : 한 조직에 필요한 정보여러 시스템에서 공용할 수 있도록 논리적으로 연관된 데이터를 모으고

                 중복 제거로 최소화하여 구조적으로 통합 저장한 것

[특징]

  1. 실시간 접근성
  2. 계속적인 변화
  3. 동시 공유
  4. 내용에 따른 참조

-DBMS 

  1. 데이터 추출
  2. 데이터 조작
  3. 데이터 정의
  4. 데이터 제어

할 수 있게하는 데이터베이스 관리 시스템

-DBMS 사용이점

  1. 데이터 통합화
  2. 데이터 중복 최소화/데이터 무결성
  3. 데이터 보안향상
  4. 관리 편의성 향상

-관계형 DBMS? 

 : 모든 데이터를 2차원 테이블 형태로 표현

  ->객체관계형 DBMS로 넘어감

 

*디벨로퍼에서 접속환경 만들기

CREATE USER ~ IDENTIFIED BY~

GRANT 권한(EX : CONNECT, RESOURCE) TO ~

 

[SQL] : RDBMS에서 데이터를 조회하거나 조작하기 위해 사용하는 언어

        데이터 조작, 조회 시 절차가 아닌 조건을 기술하여 작성하는 구조적 질의언어

  • DQL = 검색 : SELECT
  • DML = 조작 : INSERT, UPDATE, DELETE
  • DDL = 정의 : CREATE, DROP , ALTER
  • DCL = 제어 : GRAND, REVOKE
  • TCL = 트랜잭션 제어 : COMMIT, ROLLBACK

*오라클 주요 데이터 타입

  1. NUMBER
  2. CHAR :고정길이 , 빈칸 그대로
  3. VARCHAR2 : 가변길이, 빈칸 사라짐( 좋지만 속도면에서 느린 경우도 존재)
  4. LONG
  5. DATE :날짜 , 날짜 타입끼리 연산도 가능함
  6. CLOB : 가변길이 문자
  7. BLOB 2진수

<별칭 붙히기> 컬럼명 + 별칭 OR  + AS + "별칭"  (띄어쓰기 포함시)

<중복 표시 제거> DISTINCT + 컬럼명

<문자 포함 여부 와일드카드> WHERE ~ LIKE '_%'

  • _ 는 1개의 임의 문자가 반드시 있어야 한다 의미
  • %는 몇개든 임의 문자가 공백을 포함해 있는 경우 의미
  • _ 과 %를 단지 특수문자로 쓰려면 ESCAPE 필요
  • EX) ~ LIKE '@__' ESCAPE '@'

- IN 연산자 :  비교하려는 값이 IN 목록에 있는 것과 일치하는 것이 있는지 확인

   -OR 을 연속사용하는 것과 같은 효과

-병합 : || -> 70000 || '원' => 70000원 으로 합쳐지도록 함

-IS NULL / IS NOT NULL : NULL 인지 확인하는 조건문에 많이 사용

 

1. Java의 특징들

  • OS에 독립적이다
  • 객체지향 프로그래밍 언어이다 (OOP)
  • 포인터 메모리를 자동 관리해준다
  • 동적로딩이 가능하다
  • 멀티 쓰레드를 지원한다

2. 변수란?

  • 메모리에 값을 기록하기 위한 공간이다
  • 기록 후 지속적 사용이 가능하다

3. 데이터의 저장 단위

  • 컴퓨터는 기본적으로 2진수를 사용하고 이것이 1bit
  • 사용단위로 1byte = 8bit 가 된다

4. 변수를 선언한다?

  • 메모리 공간에 데이터를 저장할 수 있는 공간을 할당한다는 것과 동일하다

5. Java의 기본 자료형 8가지

  1.  정수형 : byte short int long ( 1  ,  2  ,  4  ,  8  byte)
  2.  실수형 : float  long ( 4 ,  8  byte)
  3.  문자형 : char (2 byte)
  4.  boolean (1 byte)
  5. (String은 기본형이 아닌 참조형이다)

6. 변수 선언시 고려할 것

  1. 변수 명은 대소문자를 구분한다
  2. 예약어는 불가하다
  3. 숫자로 시작할 수 없다
  4. 특수문자는 _ , $ 만 허용되고 되도록 안쓰는게 좋다
  5. 관례적 표기법에 따라 쓰고 카멜표기를 따르면 첫문자는 소문자, 다음 단어 첫문자마다 대문자를 쓴다.

7. 상수와 리터럴은 비슷한 개념이지만 리터럴은 대입되는 값 그 자체를 의미한다.

8. 기본형 변수의 형변환이 가능하다

  1. 자동 형변환 : 작은 자료형 -> 큰 자료형은 컴파일러가 자동으로 바꿔준다.
  2. 강제 형변환 : 큰 자료형 -> 작은 자료형은 강제로 (자료형) 를 붙혀 바꾸며 이떄 값 손실이 생길 수 있다.

ex) double a = 5+ 5.9 ; -> 5는 컴파일러에 의해 자동으로 큰 자료형 실수로 바뀌게 된다

ex) int a = 5 + 5.9; -> 작은 자료형으로 바뀌어야 하므로 강제 형변환으로 소수 자리의 손실이 필요하다.

 

9. 오버플로우란?

  • 표현 가능 범위를 초과하게 될때 최대 표현-> 최소 표현 값으로 나오게 되는것

10. 메모리의 구조

  • Static -> 객체마다 공용으로 써질 것들을 만들어 놓으면 시작 시 Static 메모리에 올라가서 공용으로 사용된다
  • Heap -> new 연산자에 의해 동적으로 할당되고 저장되며 객체 배열 등 사용자 정의로 사용될 수 있다.
  • Stack -> 메서드를 호출하면 자동으로 생성되고 끝나면 자동 소멸된다

*Heap 영역은 객체, 배열 등 사용가자 크기를 정해 만들수 있어 동적 영역이고 가비지 컬렉터 등의 관리 영역도 된다

*Stack은 지역변수, 매개변수, 메소드호출 등 으로 사용된다.

 

11. 배열이란?

  • 같은 자료형의 변수를 하나의 묶음으로 다루는 것.
  • 선언하면 Stack에 주소를 저장하게 되고 new 연산자로 Heap 영역에 올리면 참조해 묶음을 만들어 낸다

12. 배열 복사

  • 복사의 방법으로 2가지가 있다
  • 1.  얕은 복사 : 객체의 주소값만 참조형 변수에 저장함
    • 단순 주소 복사이므로 그냥 변수가 가진 주소값만 대입해 주면 끝난다.
    • 하지만 하나의 배열을 두개의 변수가 참조하는 것이므로 서로가 영향을 준다는 문제가 있다.
  • 2.  깊은 복사 : 새로운 배열 객체 생성 후 기본 배열 데이터를 복사한다.
    • arrays클래스 등의 방법으로 깊은 복사를 지원한다
    • System.arraycopy(arr1 , 0 , arr2 , 0 , arr1.length)
    • arr2 = Arrays.copyOf(arr1, arr1.length)
    • clone() 

13. 2차원 배열

  • 자료형이 같은 1차원 배열을 또 다시 배열로 묶은 것
  • new int[3][] 등으로 표현한 것 처럼 뒷자리를 가변 배열로 서로 다르게 참조할 수 있다.

14. static 과 final

  1. static : 같은 타입의 여러 객체가 공유할 필드에 사용한다 => 정적 메모리 영역에 자동 할당됨
  2. final : 하나의 값만 계속 사용할 시 사용하며 상수는 모두 대문자로 표기한다.

15. final + a 의 효과

  1.  final + 멤버변수 : 상수
  2.  final + 필드 : 상수
  3.  final + 메서드 : 오버로딩이 불가능해 진다
  4.  final + 클래스 : 상속이 불가능해진다 (마지막 클래스)

16. 객체 지향의 특징

  1. 상속 + 추상화
  2. 캡슐화
  3. 다형성

17. 객체란 무엇인가?

  • 자신의 속성과 기능( 값 + 함수) 이 다른것과 구분되어 식별 가능한 것 ( 이 틀을 클래스라 할 수 있다)
  • -> 이것들이 new 연산자로 메모리에 생성된 결과물이 객체라 볼 수 있다.
  • 즉 클래스의 정의대로 메모리에 할당된 결과물이다.

18. 클래스?

  • 객체의 특성에 대해 정의한것( = 설계도의 개념)
  • 추상화와 캡슐화가 필요하다

19. 추상화?

  • 클래스의 속성과 기능중에서 필요한 공통점들을 추출하고 불필요한 부분을 제거하는 것
  • '인간' 이라는 추상화로 공통점으로 뽑아내고 각각의 개성을 가진 1명은 객체가 된다는 것과 비슷

20. 캡슐화

  •  추상화로 정리된 데이터들과 기능을 하나로 묶어서 관리한다.
  •  데이터에 직접 접근을 제한하는 것을 원칙으로 간접 접근 메서드를 내부에 작성해 데이터에 접근한다.
  •  이것으로 정보 은닉 효과를 만들어 낼 수 있다.
  •  멤버 변수(인스턴스 변수)를 private 제한을 하고
  •  이에 대한 접근 메서드는 public 으로 하여 간접 접근을 허용한다.

21. class 접근제한자

  • 기본 default : 같은 패키지 내에서만 가능
  • public : 전부 사용 가능

22. 필드 접근 제한자

  • public : 전부 
  • protected : 같은 패키지 + 후손 패키지 까지 접근 가능
  • default : 같은 패키지
  • private : 클래스 내에서만 가능

23. 생성자란?

  • 객체가 new 연산자로 Heap 메모리 영역에 할당될 때 
  • 객체 안에서 만들어지는 필드 초기화 + 생성 시 필요한 기능 수행
  • 생성자명은 클래스명과 반드시 같아야한다.
  • 작성하지 않으면 컴파일러가 자동으로 기본생성자를 만들어내고
  • 매개변수가 있는 생성자를 만들면 기본생성자를 만들지 않으므로 별도로 기본 생성자를 만들어야 한다.

24. 오버로딩이란?

  • 한 클래스 내에 동일한 이름의 메서드를 여러 개 작성해서 다른 기능을 구현하는 기법이다.
  • 1. 메서드별로 이름은 같아야하고
  • 2. 매개변수는 달라야 한다.
  • * 다르단 것은 [매개변수 갯수] , [매개변수 타입], [갯수와 타입은 같지만 순서가 다름] 을 의미
  • * 오버라이딩과 구분해야 된다

25. this 와 this()

  • this 란 모든 인스턴스의 메서드에 숨겨진채 존재하는 레퍼런스로
  •  할당된 객체 자신을 가르킴( 객체 자신의 주소)
  • 생성자 매개변수 이름 = 필드명 과 같이 생성자 선언시 객체 필드를 매개면수와 구별시 많이 사용
  • this() 란 같은 클래스의 서로 다른 생성자를 호출할 때 사용하며
  • 생성자 () { this() } 처럼 다른 생성자를 호출 시 반드시 첫 출에 사용해야 한다.

26. 상속이란?

  • 다른 클래스가 가지고 있는 멤버들을 새 클래스에서 작성하지 않고도 상속받아
  • 자신의 멤버처럼 사용 가능해 지는것을 말함
  • * 재사용 , 공동 규약의 정의를 할수 있게 된다.
  • 이를 통해 중복을 제거하고 공통 관리로 추가 변경이 용이해지고 코드 양도 결론적으로 줄어들게 되는 장점이 있다
    • <주의점>
    • Java에서는 단일 상속만 허용하므로 주의한다.
    • 모든 클래스는 Object 클래스의 후손이며 컴파일러가 자동으로 추가한다.
    • 부모 클래스의 생성자, 초기화 블록은 상속되지 않는다.
    • 부모의  private 멤버는 상속은 되지만 직접 접근할 수는 없다.
    • * private 멤버는 super() 나 setter getter 로 접근해야 한다(간접)

27. super 와 super()

  • super : 상속을 통한 자식 클래스 정의시 해당 자식클래스 내에서 부모 객체를 가르키는 참조변수
  • super() : 부모 객체의 생성자를 호출한다. 컴파일러는 상속시 super()를 생성자 안에 자동으로 첫줄에 추가한다.

28. 오버라이딩

  • 오버로딩은 한 클래스 내에서 같은 이름의 다른 메서드를 작성하는 것이고
  • 오버라이딩은 상속 관계에서 자식 클래스가 부모에게 물려받은 메서드를 같은 이름으로
  • 재작성해서 사용하는 것을 의미한다.
  • <작성법>
  • @Override 애너테이션을 쓰고
  • 접근제어자는 부모와 같거나 더 넓게 
  • 예외 처리는 부모보다 좁게 
  • 1. 메서드 이름 동일
  • 2. 매개변수 개수, 타입, 순서 동일
  • 3. 리턴 타입 동일
  • 4. private 메서드는 오버라이딩 불가함

29. 다형성

  • 상속을 이용해 부모클래스 타입 참조 변수로 여러 자식 객체를 참조할 수 있는 것.
  • 업캐스팅 : 부모타입 참조 변수로 자식 타입 객체를 참조
  • Car -> Tesla 처럼 Car의 참조변수(주소)에 Tesla 객체를 만들어 그 주소를 참조 저장하게 하는것이다.
  • Car는 Tesla 고유의 것은 사용 할 수 없지만 Tesla가 Car로 물려받은 (Tesla안의 (Car)것들은 사용 할 수 있게 된다.
  • * = 부모 타입의 참조변수로는 자식 멤버를 쓸 수 없다.
  • 다운캐스팅 : 자식의 객체를 참조하고 있는 부모 타입의 참조변수를 다시 자식 타입의 참조 변수로 바꿔서 자식 멤버를 사용할 수 있도록 하는 것
  • 이 때 동적바인딩이 되게 된다.
  • =참조는 부모타입을 하고있음에도 자식이 가진  자식의 오버라이딩 메서드에서 부모 것이 아닌 자식의 오버라이딩 메서드가 실행되게 되는 것.

30. 추상화

  • 미완성된 것으로 자체 객체 생성이 불가하다. => 상속으로 사용
  • abstract 메서드가 포함된 경우 반드시 abstract 클래스여야 한다
  • 일반 변수와 메서드가 포함 가능하다
  • 객체 생성은 안되지만 참조형 변수 타입으로는 사용 가능하다
  • *추상 클래스 = 추상 메서드를 포함해 미완성 된 클래스 or 미완성이 아니더라도 객체생성이 되면 안되는 클래스
  • 장점 : 상속받은 자식에게 공통된 멤버를 제공하고 일부 기능 구현을 강제화 할 수 있다.

31. 인터페이스

  • 상수형 필드와 추상 메서드만을 작성 할 수 있다.
  • 목적 :
  • 일관된 인터페이스(작업환경) 제공
  • 상속받은 모든 클래스가 동일한 메서드 강제 오버라이딩 하도록 일관성 유지
  • 클래스 간의 접점을 강제로 만들어 줄 수 있다. (다중 상속 가능)
  • 모든 메서드 : public abstract
  • 모든 변수 : public static final
  • (없어도 컴파일러에 의해 강제로 써진다)
  • 객체 생성을 할 수 없고 참조 변수로는 사용할 수 있다 ( 다형성)

32. 오류 / 예외

  • 비정상 종료 -> 
    • 컴파일에러 : 코드 오류
    • 런타임 오류 : 논리 오류 -> if처리도 가능 할 수있다.
    • 시스템에러 : 오작동
  • 예외 : 소스코드 수정만으로 해결  가능한 오류를 말한다.
    • try- catch문(+finally : 무엇이 되든 마지막에 수행되는 구문)
      • 예외가 발생할 가능성이 있는 코드를 내부에 작성 시도해 발생하며
      • catch가 잡아내 오류시의 코드를 설정한다.
    • throws
    • throw

33. Wrapper 클래스

  • 기본 자료형을 객체화 시켜주는 클래스
  • 기본 자료형과 관련된 특정 값 기능을 제공하고 기본 자료형을 다룰 수 없는 경우에 사용한다.
  • 첫 문자가 대문자로 바뀌며 int -> Integer , char -> Character 로 예외적으로 바뀐다.
  • 모두 static으로 객체생성 없이 사용 가능하다.
  • 기본형과 객체타입 값 대입시 서로 자동으로 호환되도록 해주는 것을 박싱 / 언박싱이라고 한다.

 

Stack 과 Queue를 배운뒤 괄호가 이것들로 처리된다는 걸 보고

 

문득 이제 계산기를 만들 수 있겠다 싶었다.

 

찾아보니 많은 자료들이 Swing이란 것을 이용한 것 같은데 나는 초보라 알지도 못하고

 

보니 실무에서 많이 안쓰는지 책에도 내용이 개정되어 빠졌다 ㅠㅠ

 

그래서 그냥 처음 내가 생각한대로 구현해보자 마음먹었다.

 

하지만 막상 해보니 1+2 나 숫자 2개를 입력받아 처리는 매우 쉬웠지만 내가 원하는대로 구현은 상당히 어려웠다.

(이상한 집념이 생겨서 이틀이나 날려먹었다....)

게다가 이틀이나 고생했는데 아직도 고쳐야 할 부분이 있다.

(어쩌면 내가 못찾은 문제가 더 있을지도....)

 

기본적으로 구상한것은 이랫다

1. 괄호의 처리

  • Stack을 활용하여 ((((를 push하고 ) 이 처음 pop 되는 순간에 (와 )의 중간 수식을 Middle로 뽑아낸다
  • Middle 수식을 사칙연산에 넣어서 처리 후
  • 새로운 Middle 값을 (Middle)에 전부 대체해 괄호와 이전 수식 제거
  • 또 다시 수행하며 )이 pop 될떄 Middle 다시 처리 반복

2. 뽑아낸 Middle의 처리(이게 난관일줄이야... 갈 길이 멀다)

  • 제일 중요한 것이 문자열을 숫자와 부호로 구분하는 것이였다
  • 한참 고민하고 구글링을 하며 split + 정규표현식 이라는 것을 사용하면 가능하다고 해서 적용했다
String[] numtmp = Middle.split("(?<=[*/+-])|(?=[*/+-])");//정규연산자
  • 위 코드를 적용하면 아마 */+- 인것과 아닌것으로 구분되고 ?는 앞에 전체를 구분해서 잘라내는것 같다
  • 처음에는 정규표현식을 \w(알파벳+숫자) \W(그 반대) 로 써서 뽑아냈는데
  • 구현하고 보니 치명적인 단점이 나눗셈을 위해 반환을 Double로 해놓아서 100.0 같은 ( . ) 이 구분되어 고통받았다
  • 이렇게 구분한 것들을 LinkedList 에 넣고 숫자와 부호로 나누고
  • 부호의 갯수를 count 해서 이때 곱하기+나누기의 횟수 를 저장 후 count만큼 곱하기 나누기를 먼저 수행하도록 함

코드를 작성한 후 돌려보니 먼가 흐뭇하게 돌아가서 잠시 기뻣다 ㅎㅎ

하지만 돌리다보니 오류가 나는 점이 발견되고 스스로도 에러라 생각되는 점도 생각하게 됐다.

  1. '(' 과 ')' 의 갯수가 서로 일치하지 않을때의 Exception 필요
  2. -5*2 와 같은 음수로 시작하는 Middle
  3. 2*-5 와 같이 음수로 끝나는 수식이 포함된 Middle (아직 수정못했다... ㅠㅠ)

1 의 에러는 Exception 만 적절히 해주면 해결되서 다행이였지만

2 와 3의 에러는 골치가 아팠다.

기본적으로 음수도 적용되는 계산기라면 저것들은 오류라기보단 뭔가 코드를 수정해야하는 결함에 가까운것 같다.

그래서 고민끝 해결책으로 

2의 경우는 0-5*2 와 동일한 수식이라는 점을 해결책으로 찾았다

 

3의 경우도 뭔가 해결책을 찾아야하는데... 이틀 고민했더니 다른 공부가 너무 밀려버려서 

이제 그만하고 생산적인 일을 해야하지 않을까 하는 생각(=변명 ㅎㅎ) 이 들어서 

나중에 초보를 벗어나면 다시 더 간결한 코드로 새로짜야겠다 생각했다.

 

간단한 계산기 구현이였는데도 내가 짠 코드를 내가 헷갈릴 정도로 어지러워졌고 코드가 너무 조잡한거같다.

 

그래도 덕분에 객체 지향이라는게 얼마나 편리한지 

그리고 String 이나 배열 보다 StringBuffuer, LinkedList가 사용면에서 얼마나 더 편리한지 몸소 느끼게 됐다.

 

아직 초보도 진입을 못했구나 하는 나의 현실을 여실히 느끼며 다시 공부에 전념해야겠다.

 

<아직 미해결 문제점  : 곱하기와 나누기 뒤에 음수면 에러>

import java.util.EmptyStackException;
import java.util.LinkedList;
import java.util.Stack;

//고쳐야 할 점 : 음수를 뒤에서 곱하거나 나누면 에러!!!!!
public class make_calcul_2st {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyCaluCulLator SWver1 = new MyCaluCulLator();
		StringBuffer input = new StringBuffer("(-2*3+2-2*3-3+7-6*7)*4/(3+2)+3/2-5");
			try {
				System.out.println("노력의 결실이 나옵니다!!!! 답은?"+SWver1.RG(input));
			} catch (EmptyStackException | MyCaluCulLator.OverStackException e) {
				System.out.println("괄호가 맞지 않습니다");
			} 
	}
}
/*
 * 필요사항
 * 1. 괄호 계산이 1순위
 * 2. *와 / 우선순위
 * 3. -A & B 계산시 동시처리
 * => 숫자를 쌓기엔 어레이리스트
 * => 부호를 찾기엔 스택? 문제는 찾으면 날라감
 * =>
 */
class MyCaluCulLator{
	String input;
	MyCaluCulLator(){}
	MyCaluCulLator(String input){
		this.input = input ;
	}
//-----------------------------------생성자 초기화-----------------------------------
//-------------------------------------괄호 없는 경우 String 수식의 계산------------------------
	public String RealCalCul(String Middle) {
		System.out.println("-----------------수식"+Middle+"--------------------");
		String result="";
		String[] numtmp = Middle.split("(?<=[*/+-])|(?=[*/+-])");//정규연산자
		boolean nobuho =true;
		for (int i = 0; i < numtmp.length; i++) {
			if(isbuho(numtmp[i])) {
				System.out.println("부호가 있네요");
				nobuho = false;
				break;
			}
		}
		if(nobuho){ return Middle; }
		
		LinkedList<String> num = new LinkedList<>();
		LinkedList<String> buho = new LinkedList<>();
		int multidivi_count=0;
		int minus = 0;
		for(String a: numtmp) {
			if(isbuho(a)) {
				buho.add(a);
				if(a.equals("*")||a.equals("/")) multidivi_count++;
				else if(a.equals("-")) minus++;
			}
			else {
				num.add(a);
			}
		}
		int plmicount = buho.size() - multidivi_count - minus;
		System.out.println(multidivi_count+"번 곱셈나눗셈 수행할게요");
		//부호와 숫자 분리 완료
		//곱하기 나누기 횟수 저장 후 양수면 먼저수행
		if(multidivi_count>0||plmicount>0) {
			while(multidivi_count!=0) {
				int index = buho.indexOf("*");
				System.out.println(index);
				if(index>=0) {
					System.out.println("곱하기 수행");
					String a = ""+TheCal(num.get(index),"*",num.get(index+1));
					num.remove(index);
					num.remove(index);
					num.add(index, a);
					buho.remove(index);
					System.out.println(num.get(index));
					multidivi_count--;
				}
				int index2 = buho.indexOf("/");
				System.out.println(index2+"=index2값");
				if(index2>=0) {
					System.out.println(num.get(index2));
					System.out.println("나누기 수행");
					String ac = ""+TheCal(num.get(index2),"/",num.get(index2+1));
					num.remove(index2);
					num.remove(index2);
					num.add(index2, ac);
					buho.remove(index2);
					System.out.println(num.get(index2));
					multidivi_count--;
					}
				}//곱하기 while끝
			//곱하기 나누기 완료
		
		//더하기 수행
			System.out.println("현재값");
			for(String a: num) {
				System.out.println(a);
			}
			for(String a: buho) {
				System.out.println(a);
			}
			
		while(minus!=0) {
			int index4 = buho.indexOf("-");
			if(index4>=0) {
				System.out.println(num.get(index4));
				System.out.println("빼기 수행");
				String ab = ""+TheCal(num.get(index4),"-",num.get(index4+1));
				num.remove(index4);
				num.remove(index4);
				num.add(index4, ab);
				buho.remove(index4);
				System.out.println(num.get(index4));
				minus--;
			}
		}
		while(plmicount!=0) {
			int index3 = buho.indexOf("+");
			if(index3>=0) {
				System.out.println(num.get(index3));
				System.out.println("더하기 수행");
				String a = ""+TheCal(num.get(index3),"+",num.get(index3+1));
				num.remove(index3);
				num.remove(index3);
				num.add(index3, a);
				buho.remove(index3);
				System.out.println(num.get(index3));
				plmicount--;
			}
		}
		}
			
		
		System.out.println("결과는!!!!!!"+num.get(0));
		
		Middle = num.get(0);
		return Middle;
	}
	
	

/*-----------------------------수식에 괄호가 있는 경우 추출 메서드----------------------------*/
	public String RG(StringBuffer input2) 
			throws  MyCaluCulLator.OverStackException {
				Stack st = new Stack(); //괄호 쌍 검사용 임시 스택
				int startindex=0;
				int endindex=0;
				int count = 0;
				int count1 = 0;
			for (int i = 0; i < input2.length(); i++){
					if((input2.charAt(i)=='(')){
							st.push('(');
							count1++;
							startindex=i;
													}//end
					
					else if (input2.charAt(i)==')') {
							st.pop();
							count1--;
							endindex=i;
							String middle =input2.substring(startindex+1, endindex);
							System.out.println("이번 괄호는 "+middle+"입니다");
							char[] c = middle.toCharArray();
							for (int j = 0; j < c.length; j++) {
								boolean minor = isbuho(c[j]+"");
								if(j==0&&minor){
									middle = "0"+middle;
									System.out.println("음수감지 0추가"+middle);
									}
								}
							middle = RealCalCul(middle);
	
							c = middle.toCharArray();
							for (int j = 0; j < c.length; j++) {
								boolean minor = isbuho(c[j]+"");
								if(j==0&&minor){
									middle = "0"+middle;
									System.out.println("음수감지 0추가"+middle);
									}
								}
						input2 =input2.replace(startindex, endindex+1,middle);
						RG(input2);
						break;
						}//end
						}
						String input3 = input2.toString();
		if(count1==0) {		
		char[] c= input3.toCharArray();
		for (int j = 0; j < c.length; j++) {
			boolean minor = isbuho(c[j]+"");
			if(minor){
				count++;
			}
		}
		System.out.println("마지막 남은 부호 처리구간, 부호 갯수:"+count);
		System.out.println(input3);
		if(count!=0) {
			input3 = RealCalCul(input3);
		}
		
		}
		return input3;
		
}
	
	
	
/*---------------------------String A&B의 계산 메서드---------------------------*/
	public double TheCal(String A , String b, String B) {
		double a = Double.valueOf(A);
		double c = Double.valueOf(B);
		double result=0;
		switch(b) {
		case "+" : result = sum(a,c); break;
		case "-" : result =sub(a,c);break;
		case "/" : result =divide(a,c);break;
		case "*" : result =multi(a,c);break;
		}
		double per = Double.parseDouble(String.format("%.4f",result));
		return per;
		
	}
/*--------------------------연산자 문자인지 확인 BOOLEAN------------------------*/
	public boolean isbuho(String d) {
			if(d.equals("+")) 		return true;
		else if(d.equals("-")) return true;
		else if(d.equals("/")) return true;
		else if(d.equals("*")) return true;
		else return false;
	}
/*-------------------------기본 4칙연산-------------------------------------*/
	public double sum(double a, double b) {
		return a+b;
	}
	public double sub(double a, double b) {
		return a-b;
	}
	public double multi(double a, double b) {
		return a*b;
	}
	public double divide(double a, double b) {
		return a/b;
	}
/*-------------------------괄호 남는 예외-------------------------------------------*/
	class OverStackException extends Exception{
		OverStackException(String msg){
			super(msg);
		}
	}

}

 

 

'개발자로 업그레이드 되자 > JAVA' 카테고리의 다른 글

JAVA의 IO  (0) 2021.10.24
JAVA 컬렉션(Collection)  (0) 2021.10.05
Java의 기본 개념들을 정리  (0) 2021.09.12
JAVA 별 만들기 코드  (0) 2021.08.15

지금도 그렇지만 프로그래밍은 처음 접했을 때 대부분의 책들이 Hello World! 출력으로 시작했었다.

 

하지만 이제는 시간이 많이 흘렀고 이제 프로그래밍 언어 책을 펴봤다 라고 말 하려면

 

이제 Hello World! 출력해봤어! 보단 별만들기 정도 해봤어! 라는게 더 어울릴것 같다 ㅋㅋ

 

별을 순차척으로 늘리거나 줄이는 코드는 책을 읽으면서도 금방 코드가 떠올랐지만

 

별모양으로 별을 뽑는건 나름의 고민의 시간을 보내고 다른 코드들도 참고하며 완성할 수 있었다.

 

이 별 만들기의 포인트는 2개였던거 같다.

 

1. 중간지점까진 별이 늘어나고 이후 줄어든다

  = (i<num/2) 로 구분

 

2. 줄어드는 부분의 별 공백을 구현할때 변수 설정이 까다롭다.

  = (num/2-i)를 활용해서 i의 증감식을 역으로 활용했다.

public class make_star {

	public static void main(String[] args) {
		int num = 55;
		for(int i = 0 ; i<num ; i++) {
			if(i<num/2){
				for(int j = 0 ; j<num ;j++) 
					{ if(j<num/2-i||j>num/2+i)System.out.printf(" ");
					  else System.out.printf("*"); }
			}
			else if(i>num/2) {
				for(int j = 0 ; j<num ;j++) {
					if(j<i-num/2)System.out.printf(" ");
					else if(j>num-i-1+num/2) System.out.printf(" ");
					else System.out.printf("*");
				}
			}
			else{
				for(int j = 0 ; j<num ;j++) System.out.printf("*");
			}
			System.out.println();
		}
	}
}

 

+ Recent posts