TIL - 초기화오류 | 코드 수정

su·2023년 6월 2일
0

TIL

목록 보기
14/93
post-thumbnail

문제1 - 각 상품의 총 판매 가격이 초기화 되지 않았다!

1) 문제

어제 분명히 코드를 완성했다고 생각하고 편안한 마음으로 잠에 들었는데,
아침에 다시 실행해보니까 어제 발견하지 못한 문제점을 발견했다.

작성한 코드를 말로 설명해보면,
상품 하나 하나를 객체로 선언해 주었는데, 그 상품 안에 Small 사이즈와 Regular 사이즈의 선택지가 있다.
(Coffee메뉴와 IceBlended 메뉴만)
각각의 사이즈를 선택한 후, 수량을 입력받으면 입력받은 수량대로 상품 사이즈의 수량이 변경되고, 장바구니에 상품을 더할 때는 총 수량에 입력받은 수량을 더해준다.

그런데 이걸 장바구니에 담고 나면, 다시 원래대로 수량을 초기화 해주어야 하는데
어제 미처 이 부분을 확인하지 못하고 넘어가는 바람에 코드를 다 완성한줄 알았다.

2) 시도

오류를 발견했으니 수정해보자.
장바구니에 해당 상품을 담을 때의 코드이다.

// getGood() - 선택한 메뉴의 사이즈를 입력받아 장바구니에 추가할 것인지 판단
public void getGood(Goods goods) throws InterruptedException{
    System.out.printf("%-25s | %5s | %s", "\""+goods.getName(), "W " +goods.getPrice(), goods.getDetail()+"\"");                                // 입력받은 상품 그대로 출력하기
    System.out.println("\n위 메뉴의 어떤 옵션으로 추가하시겠습니까?");
    System.out.printf("%-2s %-15s %-2s %-15s\n", "1.", "Small(W " + goods.getPrice() + ")", "2.", "Regular(W " + goods.getPrice2() +")");  // 1.Small(가격) 2.Regular(가격) 출력
    String s = sc.nextLine();
    if (s.contains("Small") || s.contains("1") || s.contains("small")) {                                                                        // 1.Small을 입력했다면
        getGood2(goods);                                                                                                                        // 원래 상품을 출력해주는 getGood() 메소드 호출
    } else if ((s.contains("Regular") || s.contains("2") || s.contains("regular"))){                                                            // 2.Regular를 입력했다면
        System.out.printf("%-25s | %5s | %s", "\""+goods.getName2(), "W " +goods.getPrice2(), goods.getDetail()+"\"");                          // 찾아낸 Regular 상품 출력하기
        System.out.println("\n위 메뉴를 장바구니에 추가하시겠습니까?");
        System.out.printf("%-2s %-7s %-2s %-7s\n", "1.", "확인", "2.", "취소");
        String call = sc.nextLine();
        if ("1.확인".contains(call)) {                    // 1.확인을 눌렀다면
          System.out.print("수량을 입력해주세요: ");        // 상품 수량을 입력받음
          int i = sc.nextInt();
          sc.nextLine();
          System.out.println(goods.getName2() + " 가 장바구니에 추가되었습니다.");
          goods.setNumber2(i);                           // 해당 goods 객체 안의 상품 개수를 입력받은 수량으로 set 해주는 메소드 호출
          order.addOrderList(goods, 2, i);               // 그 후 장바구니 리스트(Order 클래스의 orderList)에 담을 메소드 호출
        }
    } // if ~ else 종료
    mainMenu(); // 다시 메인 메뉴로 돌아가기
} // getGood()

원래는 해당 리스트에 있는 해당 상품의 수량을 수정해서 장바구니에 넣었다.
그래서 그 수정된 값이 그대로 상품에 저장되어버리는 것이다 ...

값을 0으로 set할 메소드를 만들어서 사용하면 괜찮지 않을까?
저 부분을 수정하려면 장바구니에 담고 나서 값을 바꿔주면 된다
주문 완료 코드를 수정해보자

public void orderComplete() throws InterruptedException {
    System.out.println("주문이 완료되었습니다!\n");
    this.orderNumber += 1;
    System.out.println("대기번호는 [ " + this.orderNumber + " ] 번 입니다.");

    System.out.println("(3초 후 메뉴판으로 돌아갑니다.)");
    TimeUnit.SECONDS.sleep(3); // 3초를 지연시킴 (throws InterruptedException 필요)
    goodsListCoffee.stream().forEach(goods -> {goods.setTotalNum1(); goods.setTotalNum2();});
    goodsListTea.stream().forEach(goods -> {goods.setTotalNum1(); goods.setTotalNum2();});
    goodsListIB.stream().forEach(goods -> {goods.setTotalNum1(); goods.setTotalNum2();});
    goodsListDessert.stream().forEach(goods -> {goods.setTotalNum1(); goods.setTotalNum2();});

	order.clearOrderList();            // 장바구니 초기화 후 메뉴판으로 돌아가기
    mainMenu();                        // 그 후에 메뉴판으로 돌아가는 메소드 호출하기
} // orderComplete()

각각의 총합 개수를 0으로 초기화하는 코드를 넣어주었다.
(원래 이렇게 안하고, orderList안에 있는 상품들만 초기화해주면 된다. 급해서 일단 이렇게..)

그런데? 이렇게 했더니 총 판매 상품 목록으로 저장해두었던 sellList 안의 상품들에도 영향이 있었다.
그렇다면 ... orderList에 상품을 집어넣을 때 다른 Goods 객체를 만들어서 넣어주어야 하나?

다시 수정해보자.

// getGood() - 선택한 메뉴의 사이즈를 입력받아 장바구니에 추가할 것인지 판단
public void getGood(Goods goods) throws InterruptedException{
	Scanner sc = new Scanner(System.in);
	System.out.printf("%-35s | %5s | %s", "\""+goods.getName(), "W " +goods.getPrice(), goods.getDetail()+"\""); // 입력받은 상품 그대로 출력하기
    System.out.println("\n위 메뉴의 어떤 옵션으로 추가하시겠습니까?");
    System.out.printf("%-2s %-15s %-2s %-15s\n", "1.", "Small(W " + goods.getPrice() + ")", "2.", "Regular(W " + (goods.getPrice()+0.5) +")");
    String s = sc.nextLine();
    if (s.contains("Small") || s.contains("1") || s.contains("small")) {
    	getGood2(goods);
    } else if ((s.contains("Regular") || s.contains("2") || s.contains("regular"))){
    	System.out.printf("%-35s | %5s | %s", "\""+goods.getName2(), "W " +goods.getPrice2(), goods.getDetail()+"\""); // 찾아낸 Regular 상품으로 출력하기
        System.out.println("\n위 메뉴를 장바구니에 추가하시겠습니까?");
        System.out.printf("%-2s %-7s %-2s %-7s\n", "1.", "확인", "2.", "취소");
        String call = sc.nextLine();
        if ("1.확인".contains(call)) {
        	System.out.print("수량을 입력해주세요: ");
            int i = sc.nextInt();
            sc.nextLine();
            Goods newgoods = goods;
            System.out.println(newgoods.getName2() + " 가 장바구니에 추가되었습니다.");
            newgoods.setNumber2(i);
            order.addOrderList(newgoods, 2, i); // 장바구니 객체에 담을 메소드 호출
		}
	}
    mainMenu(); // 다시 메인 메뉴로 돌아가기
} // getGood()

새로운 Goods 타입의 상품을 newgoods라고 생성해두고, 그 안에 goods를 대입해서 진행해보았다.

달라진게 없었다. 대체 이유가 무엇이지 ..
아 혹시 내가 한 복사방법이 얕은 복사라서 복사한 값에다가 무언가를 수정하면, 원래 값에도 영향이 미치는건가 ?? 싶어서 깊은 복사 방법을 사용해보기로 했다.

3) 해결

깊은 복사를 사용하려면 Goods 클래스에 가서 생성자를 하나 더 만들어주어야 한다.
new Goods() 안에 Goods 타입의 변수를 받을 수 있도록 만들어주었다.

public Goods(Goods g) {
	super(g.getNum(), g.getName(), g.getDetail());
    this.price = g.price;
    this.price2 = g.getPrice2();
    this.number = g.getNumber();
    this.number2 = g.getNumber2();
    this.number_total = g.getNumber_total();
    this.number2_total = g.getNumber2_total();
	this.totalp = g.getTotalp();
} // Goods()

새로 만든 생성자를 이용해서 복사한 상품으로 장바구니에 넣어보자 !!

public void getGood(Goods goods) throws InterruptedException{
	Scanner sc = new Scanner(System.in);
    System.out.printf("%-35s | %5s | %s", "\""+goods.getName(), "W " +goods.getPrice(), goods.getDetail()+"\""); // 입력받은 상품 그대로 출력하기
    System.out.println("\n위 메뉴의 어떤 옵션으로 추가하시겠습니까?");
    System.out.printf("%-2s %-15s %-2s %-15s\n", "1.", "Small(W " + goods.getPrice() + ")", "2.", "Regular(W " + (goods.getPrice()+0.5) +")");
    String s = sc.nextLine();
    if (s.contains("Small") || s.contains("1") || s.contains("small")) {
    	getGood2(goods);
    } else if ((s.contains("Regular") || s.contains("2") || s.contains("regular"))){
        System.out.printf("%-35s | %5s | %s", "\""+goods.getName2(), "W " +goods.getPrice2(), goods.getDetail()+"\""); // 찾아낸 Regular 상품으로 출력하기
        System.out.println("\n위 메뉴를 장바구니에 추가하시겠습니까?");
        System.out.printf("%-2s %-7s %-2s %-7s\n", "1.", "확인", "2.", "취소");
        String call = sc.nextLine();
        if ("1.확인".contains(call)) {
            System.out.print("수량을 입력해주세요: ");
            int i = sc.nextInt();
            sc.nextLine();
            Goods newgoods = new Goods(goods);
            System.out.println(newgoods.getName2() + " 가 장바구니에 추가되었습니다.");
            newgoods.setNumber2(i);
        	order.addOrderList(newgoods, 2, i); // 장바구니 객체에 담을 메소드 호출
    	} // 안쪽 if문 종료
    } // 바깥쪽 if~elseif문 종료
	mainMenu(); // 다시 메인 메뉴로 돌아가기
} // getGood()

이렇게 설정해두면, 아예 Goods 타입의 새로운 상품을 만들어서 장바구니에 넣어준 것이라,
기존의 Goods에는 영향을 미치지 않게 되었다.

원하는 대로 출력이 잘 되었고,
총 판매 목록도 추가하는 상품들 별로 다 보여주고, 가격도 잘 계산되는 것을 확인할 수 있었다.

4) 배운 점

얕은 복사와 깊은 복사의 차이점에 대해 다시 한 번 깨달았다.
둘의 차이를 생각해내지 못했다면 아마 이 문제는 해결하지 못했을 듯 하다.
처음부터 생각해냈다면 제일 좋았겠지만, 원하는 대로 다시 결과를 바꿀 수 있어서 다행이라고 생각한다.

카페 키오스크 만드는 과제 수정

장바구니가 비어있을 경우

원래는 장바구니가 비어있어도 그냥 빈 장바구니를 출력해주거나, 취소화면으로 들어갈 수 있었다.
하지만 딱히 그럴 필요가 없다고 생각해서, 장바구니가 비어있을 경우에 다시 메인 메뉴화면으로 돌아가도록 코드를 수정해보았다.

 public void order() throws InterruptedException {
    Scanner sc = new Scanner(System.in);
	if (order.getOrderList().isEmpty()) {
        System.out.println("장바구니가 비어있습니다.");
        System.out.println("잠시 후 메뉴판으로 돌아갑니다.");
		try {
            TimeUnit.SECONDS.sleep(1);
        	mainMenu();
		} catch(InterruptedException e) {
        	System.out.println(e.getMessage());
    	}
	} else { ... }
} // order()

장바구니 내용을 출력하는 메소드이다.
여기서 orderList 에 담겨있는 것이 없다면, 장바구니가 비어있다는 사실을 알려주고 1초 후에 메뉴판으로 돌아가도록 코드를 추가해주었다.

public void orderCancel() throws InterruptedException{
	Scanner sc = new Scanner(System.in);
	if (order.getOrderList().isEmpty()) {
    	System.out.println("장바구니가 비어 있습니다.");
        System.out.println("잠시 후 메뉴판으로 돌아갑니다.");
        try {
        	TimeUnit.SECONDS.sleep(1);
            mainMenu();
		} catch (InterruptedException e) {
        	System.out.println(e.getMessage());
		}
	} else { ... }
} // orderCancel()

마찬가지로 주문을 취소하는 메소드에도 조건을 추가해주었다.
이렇게 작성하고 실행해보면,


두 경우 모두 다 원하는 대로 출력하는 모습을 확인할 수 있었다.

최대값 찾는 메소드 구현 오류

최대값을 찾는 메소드를 구현하는 도중에 이부분에서 오류가 났다.

illegal start of expression

이라는 내용의 오류가 발생했다. 내용을 찾아보니, 뭔가 문법적인 오류가 있다는 내용이었다.
괄호를 열고서 닫지 않거나, if문이나 for문 등에 문법적 오류가 있거나, public이나 static 등의 키워드를 잘못 사용하는 경우에도 발생한다고 한다.
출처: https://java.ihoney.pe.kr/84

그래서 두 가지로 수정해보았다.



내용이 원하는대로 잘 출력되는 것을 확인할 수 있었다.

profile
(❁´◡`❁)

0개의 댓글