코드 그라데이션

230317 자바 추가 - 문자열 더하기, break, continue 본문

Java, SpringBoot 추가 공부

230317 자바 추가 - 문자열 더하기, break, continue

완벽한 장면 2023. 3. 21. 21:58

Day01-05 관련 질문

* 문자열 더하기 관련

 

Q. 입력받은 수의 약수를 출력하는 프로그램을 만드세요.

ex) 1. 8의 약수는 1, 2, 4, 8

출력예시 > 8의 약수는 1, 2, 4, 8 입니다. <= 요렇게 나오도록.

public class Q2 {
//8의 약수를 출력하는 프로그램 만들기
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		System.out.print("약수를 구하고 싶은 숫자를 입력하세요. : ");
		int inputNum = sc.nextInt();
		String ment = "";
		
		for(int i = 1; i <= inputNum; i++ ) {
			if (i != inputNum) { // 마지막 숫자에 ,가 붙지 않게 만들어줌
				if (inputNum % i ==0) { // 약수 구하기
					ment += i; // 표기법을 위해 String 방식으로 합산을 해준다.
					ment += ", ";
				
				}
			}
		}
		System.out.println(inputNum + "의 약수는 " + ment + inputNum + " 입니다.");
	}

}

여기서 중요한 개념

+=

문자열 덧셈

 

지금 현재 코드에서 ment는 문자를 모아서 출력해주고자 선언한 문자열

ex) "1, 2, 4...."

아무것도 없을 때는 숫자를 하나씩 더하고,

약수가 나오는 순간 그 수를 ment 에 하나씩 더해가야 한다. "5" 뭐 요런 식으로

더 정확하게 말하면 순서는 이렇게 되는 셈이다.

ex. 약수 중에 5가 나왔다고 가정하면

1) "" + 5 =>  "5"

2) 5를 다시 ment에 저장 : "5" => ment

3) "5" + "," => "5,"

4) "5,"를 다시 ment에 저장 : "5," => ment

예를 들면 이런식으로 출력

public class Test {

  public static void main(String[] args) {

    String ment = "";
    ment += "1, ";
    ment += "3, ";
    ment += "5, ";
    ment += "7, ";

    System.out.println(ment); // "1, 3, 5, 7 " 출력됨
  }
}

 

또 중요한 문자열의 특징 중 하나

문자열은 불변!

그런데 왜 여기서는 더해지는 것처럼(=변해서) 출력될까?

 

그 이유는...

실제 컴파일러는 Stirng ment를 계속 변화시키는 게 아니라,

빈 문자열은 그대로 두고, 합쳐진 문자를 저장할 수 있는 문자열을 새로 만드는 것이다!

 

근데 문자열 더하기 하면 컴퓨터 성능저하된다.

그래서 사용하는게 StringBuilder라는 개념

public class _011 {

  public static void main(String[] args) {

 StringBuilder stringBuilder = new StringBuilder();
 stringBuilder.append(12);
 stringBuilder.append("x");

    System.out.println(stringBuilder);
  }
}

뭐 요런식으로 만든다. 이 값은 12x 이렇게 출력됨

 

 

Continue

=> 실행하지 않고 건너뛴다.

 

도달할 수 없는 명령문이라는 error메시지 발생
이렇게 수정하면

다섯번째 차례에서 end 출력이 한 번 빠져서 나옴.

 

Break

continue와 비교한 예시

5까지 찍히고 반복문이 종료된다.

그런데, 여기서 왜  5가 걸리는 부분인데 5까지 출력되냐?

=> 출력문이 continue 조건보다 먼저 있잖아.

따라서 5 출력이 먼저 되는 상황이므로 해당x.

 

** continue는 맨 아래 있으면 의미가 없다

 

둘 차이!

만약에 체육 야외 수행평가를 한다.

Break : 비가 와서 야외 평가가 불가, 실내로 들어가야 함

Continue : 한 학생이 오늘 몸이 아파서 운동이 불가 => 얘 빼고 다른 친구들은 진행.

 

 

Check를 왜 쓰는가?

예시

/*
보물찾기 하는 상황 가정.
XXXX
XXXX
XOXX
XXXX

O를 찾는 순간 그만.
 */ 이 구문을 짜고 싶으면

 

** 이 상황일 때 나오는 출력은? 

public class _011 {

  public static void main(String[] args) {


    int[][] matrix = new int[4][4];

    for (int i=0; i<4; i++) {
      for (int j = 0; j<4; j++) {
        if(matrix[i][j] == 'O') {
          break;
        }
      }
    }
  }
}

break는 가장 가까운 반복문을 탈출하는 것이기 때문에, 안쪽 for문만 탈출하고, 

바깥쪽 for문은 여전히 유효한 상태로 돌아가게 된다.

따라서 행 반복은 끝까지 지속된다는 말이다!!!

(** 여기서 바깥쪽 for문은 행을 의미하고, 안쪽 for문은 열을 의미한다는 것을 알아두자.)

따라서  위 코드에서의 break는 O가 들어있는 3열에서만 효과를 발휘하는 것이다

=> 즉, 3열의 O 뒤에 있는 XX(2개) 만 빼고 행을 다 돈다.

 

즉, 출력값은

XXXX
XXXX
XO
XXXX

 

이렇게 나오게 되는 것이다.

 

그렇다면,,,

바깥쪽 for문에게 목적 달성을 했다는 것을 알려줘야하겠지.

가장 쉬운 방법은 변수에 값을 담아서 표현해주면 된다.

그게 수업에서 배운 check!

 

이런 식으로 나오게 되는 것.

public class _011 {

  public static void main(String[] args) {

/*
보물찾기 하는 상황 가정.
XXXX
XXXX
XOXX
XXXX

O를 찾는 순간 그만.
 */
    int[][] matrix = new int[4][4];

    boolean check = false; // 처음 : 보물을 못찾았다.

    for (int i=0; i<4; i++) {
      for (int j = 0; j<4; j++) {
        if(matrix[i][j] == 'O') {
          check = true; // 찾았으면, 찾았다고 표시해줌.
          break;
        }
      }
      if(check) { // 안쪽 for문에서 찾았나보다!
        break;
      }
    }
  }
}

 

문제 풀던 것 중에 이해가 안 되었던 것.

public class Q02 {
// 내 답안
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.println("숫자를 입력하세요. : ");
    int inputNum = sc.nextInt();

    String num1 = " ";
    String num2 = " ";

    for(int i = 1; i<inputNum; i++) {
      if (i % 2 == 0) { //짝수일때 if 를 진행한다.
        num2 += i; // num2(짝수)에 i를 계속 넣어준다.
        continue; // 즉, 짝수일 때 다시 for 반복문으로 돌아간다..
      }
      num1 += i; // 홀수일 때 진행
    }
    System.out.println(num1);
    System.out.println(num2);
  }

}

지금 여기서 continue가 좀 어려웠는데, 그 이유가 무엇이었냐면,

일단 짝수일 때, i 값을 num2 에 계속 누적해줬고, 그리고 continue를 써서 더 이상 하지 않고 처음으로 돌아간다.

그런데 여기서 문제는, continue가 없으면 틀린 답이 됨.

왜냐면 짝수가 담기면 그만 두고 다른 숫자를 실행하는 것을 반복해야 하는데,

짝수일때도 홀수가 담겨버리는 불상사가 발생하기 때문이다.

 

그리고 이 코드는 읽기에 불편

리펙토링을 좀 하면, 일단 num1, num2 보다는 직관적인 변수명을 써주는 게 좋다.

 

public class Q02 {
// 내 답안
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.println("숫자를 입력하세요. : ");
    int inputNum = sc.nextInt();

    String oddString = " ";
    String evenString = " ";

    for(int i = 1; i<inputNum; i++) {
      if (i % 2 == 0) { //짝수일때 if 를 진행한다.
        evenString += i; //  
      }
      else {
      	oddString += i;
      }
    }
    System.out.println(num1);
    System.out.println(num2);
  }

}

 

선생님 코드

package megait.backend_lecture.Day05.Prac05;

import java.util.Scanner;

public class Q02_T {

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    String h = "";
    String j = "";
    System.out.print("숫자 입력 : ");
    int num = sc.nextInt();

    int i = 1;
    while(i<num) {
      if(i % 2 == 0) { //짝수
        j = j + i +" "; //j += i + "";
      }
      else {//홀수
        h = h + i +" " ; //h += i + "";
      }
      i++;
    }

    System.out.println("짝수 : "+ j);
    System.out.println("홀수 : "+ h);
  }

}

 

Break 탈출 관련

버거테스트 예제

package Day06;

import java.util.Scanner;

public class BugerTest {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*
		 * 메인메뉴 -> 숫자
		 * 1. 갈릭버거 2. 페페로니 3. 페포로니치킨 4.콜로수워치킨 5 종료
		 * 사이드메뉴 -> 숫자
		 * 1. 감자튀김 2.콜라 3. 사이다
		 * 결제 -> 문자열 입력
		 * 카드 상품권 현금
		 * 
		 * 주메뉴 : 갈릭버거 사이드 메뉴 : 감자튀김 결제방법 : 카드
		 * 
		 * 메인메뉴 1~5이외에 다른숫자를 입력하면 잘못된 입력
		 * 사이드메뉴 1~3이외에 다른숫자르 입력하면 잘못된 사이드 입력입니다.
		 * 결제 문자열이 다른게 들어오면 결제 수단이 없습니다.
		 * 
		 * Switch문을 많이 씁니다.
		 */
		
		Scanner sc = new Scanner(System.in);
		String menu;
		String sideMenu;
		String pay;
		
		boolean check = true;
		while(check) {
			System.out.print("메뉴를 입력하세요.>");
			int num = sc.nextInt();
			switch(num) {
			case 1: // 갈릭버거
				menu = "갈릭버거";
				System.out.print("사이드메뉴를 입력하세요.>");
				int num1 = sc.nextInt();
                
				switch(num1) {
				case 1:
					sideMenu = "감자튀김";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break; // 사이드 메뉴 탈출
                    
				case 2:
					sideMenu = "콜라";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break; // 사이드 메뉴 탈출
                    
				case 3:
					sideMenu = "사이다";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break; // 사이드 메뉴 탈출
                    
				default:
					System.out.println("잘못된 사이드 메뉴입력입니다.");
					break; // 사이드 메뉴 탈출
				}
                
				break; // 주메뉴 탈출
                
			case 2: // 페페로니
				menu = "페페로니";
				System.out.print("사이드메뉴를 입력하세요.>");
				int num2 = sc.nextInt();
				switch(num2) {
				case 1:
					sideMenu = "감자튀김";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break;
				case 2:
					sideMenu = "콜라";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break;
				case 3:
					sideMenu = "사이다";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break;
				default:
					System.out.println("잘못된 사이드 메뉴입력입니다.");
					break;
				}
				break;
			case 3: // 3.페포로니치킨
				menu = "페포로니치킨";
				System.out.print("사이드메뉴를 입력하세요.>");
				int num3 = sc.nextInt();
				switch(num3) {
				case 1:
					sideMenu = "감자튀김";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break;
				case 2:
					sideMenu = "콜라";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break;
				case 3:
					sideMenu = "사이다";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break;
				default:
					System.out.println("잘못된 사이드 메뉴입력입니다.");
					break;
				}
				break;
			case 4: // 4.콜로수워치킨 
				menu = "콜로수워치킨";
				System.out.print("사이드메뉴를 입력하세요.>");
				int num4 = sc.nextInt();
				switch(num4) {
				case 1:
					sideMenu = "감자튀김";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break;
				case 2:
					sideMenu = "콜라";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break;
				case 3:
					sideMenu = "사이다";
					System.out.print("결제 방법을 선택해주세요.>");
					pay = sc.next();
					if(pay.equals("카드") ||pay.equals("현금")||pay.equals("상품권")) {
						System.out.println("주메뉴 : "+menu+"사이드 메뉴 : "+sideMenu + "결제 방법 : "+pay);
					}
					else {
						System.out.println("결제 수단이 없습니다.");
					}
					break;
				default:
					System.out.println("잘못된 사이드 메뉴입력입니다.");
					break;
				}
				break;
			case 5: // 5.종료
				System.out.println("프로그램을 종료합니다.");
				check = false;
				break; // switch 탈출 => 다시 while로 감. 즉, 메뉴 반복을 위함
			default:
				System.out.println("잘못된 입력입니다.");
				break; // 여기도 switch만 탈출시키는 break.
			}
		}
	}
}

그래서 trick이 하나 있는 게 case 5의 check = false;

이게 없으면 계속 while문으로 되돌아가서 무한 반복이 될 것이기 때문인데,

5번을 우리가 선택하면 종료를 시키고 프로그램이 off 가 되어야 하잖아.

그걸 구현하기 위해서 눈속임을 하는 것.

 

728x90
Comments