코딩

Day 06 - Switch 조건문과 While반복문

Ledlaputa 2019. 12. 25. 07:46

지난 시간에 If 조건문과 for 반복문에 대해서 배워보았다.  If조건문과 for 반복문의 활용도가 매우 높다고 강조했으나 조건문과 반복문에는 이 두가지 이외에도 다양한 활용도를 지닌 문법들이 존재한다. 그중 대표적인 Swich와 While문에 대해서 배워보도록 하겠다.

Switch 조건문과 While반복문 또한 매우 자주 사용하게 되는 문법이니 잘 알아둘 필요가 있다. 

 


Swtch 조건문 

switch 문은 다중 if를 해결하기 위해서 등장하였다. 여러개의 다중 조건문을 사용하는 경우 If의 경우 복잡해지는 경우가 있다 이럴때 switch 문을 사용하면 효율적일 수 있다. 

switch (조건) 

{

  case 값1: //실수는X, case 3.4:(x)

   실행문장2;

      break;

  case 값2;

   실행문장2;

      break;

....

   default: // default 전체를 생략할 수 있다. 

   실행문장;

      break;

}

여기서 주의할 사항은 case 뒤의 값은 실수가 아닌 정수 타입의 변수여야 한다. 단 JDK7부터는 switch다음 괄호안에 문자열 타입의 변수도 지원하다. 

switch (조건) 

{

  case "A":

   실행문장2;

      break;

  case "B";

   실행문장2;

      break;

....

   default:

   실행문장;

      break;

}

예제1) 값을 입력받아 1이면 바다로, 2이면 산으로 가자는 문장 출력 (1,2도 아니면 도시로) 

		System.out.println("어디로 갈래?");

		int kab=sc1.nextInt();
		
		switch(kab) {
		case 1: 
			System.out.println("바다로 가자");
			break;
		case 2:
			System.out.println("산으로 가자");
			break;
		default:
			System.out.println("도시로 가자");
			break;
		}

 

예제2) 학생점수를 입력받아 학점을 구하는 프로그램 

점수 산정 방식은 아래와 같다. 

    90-100 A 

    80-89 B

    70-79 C

    60-69 D

    이하 F 학점

   case 값으로 학생의 점수를 10으로 나눈 몫만 사용하면 점수 구간을 구할 수있다.

		System.out.println("학점을 입력하세요");
		int score1 = sc1.nextInt();
		
		int score = score1/10;
		
		switch (score) {
		case 10:
			System.out.println("A학점");
			break;
		case 9:
			System.out.println("A학점");
			break;
		case 8:
			System.out.println("B학점");
			break;
		case 7:
			System.out.println("C학점");
			break;
		case 6:
			System.out.println("D학점");
			break;	

		default:
			System.out.println("F학점");
			break;
		}

위의 문제 풀이를 보면 case 10과 case9는 동일하게 A학점이다. 동일한 내용이므로 이런 경우는 중간에 break를 빼버리면, 그다음 break까지 계속 실행한다. 

           switch (score) {
           case 10:
//              System.out.println("A학점");
//              break;
           case 9:
                System.out.println("A학점");
                break;

위와 같이 case 10과 case 9가 같은 내용이므로 case10에 내용과 break를 없애도 된다. 

 

문제2) 월을 입력받아 해당월의 날짜수를 출력하시오 

		System.out.println("월을 입력하세요");
		int days = sc1.nextInt();
		
		System.out.print(days+"월의 날은 ");
		switch (days) {
		case 1:
        	System.out.println("31일입니다. ");
			break;
		case 3:
        	System.out.println("31일입니다. ");
			break;
		case 5:
        	System.out.println("31일입니다. ");
			break;
		case 7:
        	System.out.println("31일입니다. ");
			break;
		case 8:
        	System.out.println("31일입니다. ");
			break;
		case 10:
        	System.out.println("31일입니다. ");
			break;
		case 12:
			System.out.println("31일입니다. ");
			break;
		// 여기까지가 31일인 달 모음 
		case 4:
        	System.out.println("30일입니다. ");
			break;
		case 6:
        	System.out.println("30일입니다. ");
			break;
		case 9:
        	System.out.println("30일입니다. ");
			break;
		case 11:
			System.out.println("30일입니다.");
            break;
		//여기까찌가 30일인 달 모음 
		default: 
			System.out.println("28일입니다.");
			break;
		}	

위에서 31일인 달은 모아 우선 나열하고 그다음 30일인 달을 그리고 마지막으로 28일 달을 나열하였다. 

31일인 달에서 보기 좋게 중복된 부분을 제하고 마찬가지로 30일에서도 동일하게 제하고나면 아래와 같아진다. 

 

		System.out.println("월을 입력하세요");
		int days = sc1.nextInt();
		
		System.out.print(days+"월의 날은 ");
		switch (days) {
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			System.out.println("31일입니다. ");
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			System.out.println("30일입니다.");
			break;
		default: 
			System.out.println("28일입니다.");
			break;
		}	

만약 이 switch문을 if문으로 했다면 상당히 길어지고 간결하지 못한 형태로 나왔을 것이다. 물론 if조건문을 쓰면 안된다는 것은 아니나 위와 같이 switch문으로 깔끔하게 작성을 할 수 있다면 사용하지 않을 필요가 없다. 

다양한 경우의 조건에 대해 취해야 하는 경우, 그 조건이 반복적인 규칙을 가지고 있는 경우 (정수 혹은 문자)에는 활용도가 높으니 연습을 해보도록하자. 


While 반복문

while 반복문은 for 반복문과 더불어 자주 사용되는 반복문이다. 

        while (조건) { // 조건이 안맞으면 시작도 안함
        
          문장;
          
        }

while문의 활용

단순한 조건을 실행할 때, 무한루프로 많이 사용 // 이외에는 사용 빈도가 다소 떨어짐

	while(true){} // 현재 상태가 true, 무한루프로 사용

    - 가장 흔히 사용되는 무한 루프로 true인 상태에서 계속 반복하는 것이다. 

	while(true){
		if(재료가 없어?, 물온다고 70도 아래... 등 중단 조건이 필요);
		break; // if 조건에서 중단 조건이 되면 break로 문장에서 나옴   
	}

    - 이러한무한 루프에서 빠져 나오지 못하는 경우 내에 if조건문을 활용해 특정 조건에 해당되면 break로 문장에서 빠져 나오게 할 수 있다. 

	int sw==0; // sw기법, flag 기법
	while(sw==0){
		if(중지 조건...);
		sw=1; // sw가 0이 아니라 중지됨.
	}

     - 좀더 활용성이 높은 방안은 일명 flag기번이다. 하나의 flag 변수를 만들고 그 변수 값이 조건과 다르면 해당 flag변수 값을 바꾸어 다음 반복에서 조건에 맞지 않게해 반복문을 중지 시키는 방법이다. 

while문은 일단 무한 반복에 가장 많이 사용된다. 이외에는 아래와같은 경우에도 사용된다.

가장 정확할때

언제 끝날지 모를때 

 

하지만 아래와 같은 형태에서는 작동이 되지 않는다. 

	int aa=10;
	while (aa>100){
		돌아라;
	} 

예제1) 10번 love단어를 출력하라 . 

		int i=1;
		
		while (i<=10) {
			System.out.println("love"+i);
			i++;
		}
		

Do While문 

Do While문은 While문과 유사하지만 실행 전에 조건과 무관하게 먼저 한번 실행하고 그뒤에 다시 조건에 부합하면 실행하는 방법이다. 

그게 무슨 차이가 있나 하겠지만 어떤 경우는 조건 이전에 반드시 한번 먼저 실행해야 하는 경우가 존재한다. 

	do {
		문장들;
	} while(조건):
    

사용상 주의

	int aa=10;

	do {

		System.out.println("출력");

	} while(aa>100); // 조건이 안맞았으나, 위에 출력이 한번 되어 버린다. 

Do While 문은 메뉴에 사용 시 주로 활용 (수정, 삭제, 편집 등의 메뉴)

 

예제2) 메뉴 만들기, 1.짜장 2.짬뽕 메뉴가 보인후 1,2번 하나를 누르면"맛있게 드세요"를 출력하고 끝나고 3,4,5...9등을 누르면 계속 메뉴가 다시나오는 프로그램을 작성하세요

           // 메뉴가 나오는 프로그램
           int menu=0;
           
           do {
                System.out.println("중국집에 오신것을 환영합니다.  ");
                System.out.println("1.짜장");
                System.out.println("2.짭뽕");
                
                System.out.println("원하시는 메뉴를 고르세요");
                int food1=sc1.nextInt();
                
                if(food1==1) {
                     System.out.println("1.짜장, 맛있게 드세요  ");
                     menu=1;
                }
                else if(food1==2) {
                     System.out.println("2.짬뽕, 맛있게 드세요");
                     menu=1;
                }
                else {
                }
           } while (menu==0);

우선 메뉴를 호출하는 flag변수를 menu를 만들어 숫자 0을 할당한다. 1번이나 2번을 누르지 않으면 계속 반복하게 된다. 

안에서 우선 메뉴를 출력하는 문장을 작성하고 그뒤에 메뉴에 대한 숫자를 입력 받는다. 정확히 메뉴에 해당되는 숫자를 입력 받으면 if 문에서 해당메뉴의 내용을 출력하고 menu변수를  0에서 1로 바꾼다. 

menu변수값이 1이 되면 while조건 문에서 menu==0이 아니므로 while문은 종료하게 된다. 

 

위의 예제를 조금더 간단한 형태로 풀 수도 있다. 

           int sun1;
           do {
				System.out.println("중국집에 오신것을 환영합니다.  ");
                System.out.println("1.짜장");
                System.out.println("2.짭뽕");
                sun1=Integer.parseInt(sc1.next());
                 // nextInt가  반복되면 오류가 발생해서 char로 받아 int로 변환한다.
           } while(sun1!=1 && sun1!=2); //1 or 2의 반대 --> !1 &&  !2
           
           System.out.println("맛있게 드세요");

 

While(sun1 != 1 && sun1 != 2); // 입력된 sun1에 대한 조건으로 판단해서 while문에서 머물거나, 빠져 나온다. 

즉 sun1이라는 변수에 사용자가 선택한 메뉴 숫자를 대입하고 그 숫자가 1이나 2가 아니면 반복을 멈추는 조건을 추가한 것이다. 

그앞의 문제 풀이에 비해 코드가 매우 간결해졌으나 조건을 잘 이해해야 할것이다. 

flag방식이 아니라 변수값이 1과 2가 아닌경우만 반복하게 만든 것이라고 이해하면 된다. 

 

이경우 입력받은 값이 반드시 int(정수값)이여야 하는데 문자로 입력되어 오류가 발생할 수 있어 그것을 해결하기 위해 sc1.next()로 입력 받은 값에 대해서 형변환 이라는 것을 하게 된다. 

(중요) sun1=Integer.parseInt(sc1.next()); // nextInt가 반복되면 오류가 발생해서 char로 받아 int로 형변환한다.

Integer.parseint(값A)은 값A를 int로 형 변환시키는 방법이다. 형 변환에 대해서는 이후에 다시한번 다루도록 하겠다.  

 

문제2) 앞의 문제1)에서 문자를 입력 받았을때 처리 방법 

           String sun1; //
           do {
                System.out.println("1.짜장");
                System.out.println("2.짭뽕");
                sun1=sc1.next(); //
                System.out.println(sun1);
           } while(sun1!="1" && sun1!="2");
           
           System.out.println("맛있게 드세요");

자 이제 조금 문제를 바꾸어 보았다. 기존의 변수 sun1은 숫자정수인 int였으나 이번에 이 변수를 문자열인 String을 사용해서 입력받고 조건에서 사용하려고 한다. 

위의 문제 풀이는 어떻게 실행 될까? 해보면 에러를 발생할 것이다. 

 

String aa="Text"; 

값("Text")은 Heap Memory(메모리 크기 큼)에 잡힘

  • 문자열 값은 힙 메모리 어딘가에 메모리 번호로 기억한다. 
  • 문자열은 기본 메모리가 아니므로 힙 메모리에 저장
  • int와 같은(기본메모리)것은 스택에 저장 ) 
  • 해당 heap메모리의 주소를 1000번지라고 가정하자. 

변수(aa)는 Stack Memory(메모리 크기 작음)에 잡힘

  • 변수는 스택에 메모리 번호로 저장
  • aa = 1000 (heap momory의 주소를 저장하고 있음 )
  • heap 1000번 주소 = "Text" 저장 

aa변수는 --> Heap 1000번지로 --> Heap "Text" 과정을 거쳐 값을 찾게 된다. 

그래서 while조건 부분이 int와 같은 형태에서 문자로만 바꾼다고 제대로 비교가 되지 않는다. 

           String sun2; //
           do {
                System.out.println("1.짜장");
                System.out.println("2.짭뽕");
                sun2=sc1.next(); //
           } while(!sun2.equals("1") && !sun2.equals("2"));  //값을 비교
           
           System.out.println("맛있게 드세요");

while(sun1!="1" && sun1!="2"); //번지를 비교하는 것 대신 (stack 메모리)

while(!sun1.equals("1") && !sun1.equals("2")); // 값을 비교하는것 (heap 메모리) 

변수의 번지를 비교하는 것이 아니라 그 변수의 값을 비교해야하는 것이다. 변수의 주소와 변수의 값은 다른 메모리에 위치하고 있기 때문이다. 

 

갑자기 머리에 쥐가 날 수있다. 이전에 한번 간단히 자료형에 대해서 설명한 적이 있다. 그때 대부분의 자료형은 Stack메모리 였으나 마지막 String은 Heap 메모리였던것을 기억하는가? 

앞으로도 이 메모리 관련 부분에 대해서는 틈틈히 언급을 할 것이다. 나또한 이러한 메모리의 구조에 대해서 확실히 다 알고 있다고 장담하지는 못한다. (뒤돌아서면 까먹기 일수이다) 

 

하지만 프로그래밍에서 메모리에 대한 부분은 매우 중요하다. 자바에서는 포인터를 사용자가 직접 다루지 않는다. 그래서 메모리에 관련해서는 분명 C나 C++같은 언어에 비해 수월한것이 사실이나, 그렇다고 메모리를 전혀 몰라도 된다는 것은 아니니 피하지 말고 부딛혀 보기 바란다. 


 

자바에서 변수와 값에 대한 참고 사항 (번지 주소, 값)

1. 변수와 값1 : 번지주소와 값이 모두 같은 경우

   두 변수의 값(String)이 같은 경우 

           String aa="aze"; //Stack aa(1000번 주소)
           String bb="aze"; //Stack bb(1000번 주소) 
           if(aa==bb) { // 번지주소가 같다. 번지 비교
                System.out.println("==같네");
           }
           if(aa.equals(bb)) { // 함수, 메소드 , 값이 같다. 값 비교
                System.out.println("equals 같네");
           }

실행 결과 "==같네"와 "equals 같네" 가 출력

변수 aa와 변수 bb 는 동일한 값인 "aze"를 지니고 있고 같은 값의 주소를 가리키게 된다. 

aa==bb에서 같은 번지 주소를 가르키고있어 번지를 비교하면 조건에 충족하게 된다. 

값을 비교해도 물론 동일하여 두 조건 모두 만족하여 값을 출력하게 되는 것이다. 

 

2. 변수와 값2 : 번지와 값이 모두 틀린 경우 

    두 변수의 값이 틀린 경우 

           String aa2="Aze1";  
           String bb2="Aze2";  // 번지 주소와 값이 모두 틀리다.
           
           if(aa2==bb2) { // 번지 비교
                System.out.println("==같네");
           }
           if(aa2.equals(bb2)) { // 값 비교
                System.out.println("equals 같네");
           }

실행결과 출력되는 것이 없다 

이경우 변수가 가르키는값의 주소가 모두 다르고 또 값 또한 다르므로 출력 되는 것이 없다 .

 

3. 변수와 값3 : 값만 같은 경우(번지는 틀린경우) 

           String cc=new String("Aze");
           String dd=new String("Aze"); // 번지주소는 틀리지만 값이  같다
           if(cc==dd) {
                System.out.println("cc==dd같네");
           }
           if(cc.equals(dd)) {
                System.out.println("cc.eqauls(dd)같네");
           }

실행 결과 "cc.eqauls(dd)같네"가 출력

번지주소를 틀리게 하기 위해 변수를 각각 객체 생성하여 할당 하였다. 즉 두 값은 한곳이 아니라 다른곳에 동일한 값으로 저장되어 있다는 것이다. 그러니 당연히 가르키는 주소는 틀리나 그 값은 동일한 문자이니 값 비교한 부분의 조건문만 충족하게 된다. 

 

변수가 가르키는 값의 주소와 값의 차이를 설명하기 위해 위의 3가지 예시를 정리했으나 여전히 이해가 안될 수도 있다.

너무 실망하지 말자 아재의 근성으로 다시 한번 보고 또보면 (내 설명이 부족하다면 좀더 구글링을 해서 찾아보는 것도 좋은 방법이다) 분명 이해 될수 있는 부분이다.

 

이부분은 이후에 값의 비교나 주소의 비교 등으로 자주 등장하니 당장 이해가 안되도 뒤에 반복하면서 익힐수 있을것이다. 그러니 정 지금 과정에서 이해가 안되면 개념만이라도 정리하자 

 

Do While을 활용해서 메뉴를 구성하는 예제와 더불어 조건문의 처리를 위한 변수주소와 값에 대한 부분까지 살짝 깊게 다루어 보았다. 

여기까지 따라왔다면 그래도 자바와 코딩에 대해서 나름 소질이 있다고 해도 될 것 같다. 

 

마지막으로 조건문에서 자주 사용하게 되는 또다른 문법인 Continue 문법을 알아보도록 하자 

 

Continue 문법 (feat. break)

while (조건) {

    if(break 조건) 

    break; // 반복문을 완전히 빠져 나간다. A문장으로... 

    if(continue 조건)

    continue; // 취소하고 반복문(while) 맨 앞으로 돌아간다. 

}

A문장

앞에서 배운 break는 해당 반복문을 완전히 빠져 나가게 된다. 반면 continue는 반복문 내에 실행 부분이 취소되며 다시 해당 반복문의 맨 앞으로 가서 실행하게 된다. 

 

예제1) 반복문 예제 

           int flag=0;
           int cnt=0;
           while (flag==0) {
                cnt++;
                if(cnt==10) {
                System.out.println("오늘 그만팔고 장사 끝~");     
                     break; // 반복문을 완전히 빠져 나간다.
                }
                if(cnt==3) {
                System.out.println("가자 while문으로 ");    
                     continue; // 취소하고 다시 반복문 처음으로  돌아간다.
                }
                System.out.println("커피한잔"+ cnt);
           }

실행 결과 

우선 두개의 변수를 설정한다. 하나는 flag와 값이 증가되는 cnt라는 정수형 변수이다. 두 변수를 모두 0으로 초기화하고 반복문을 실행한다. 

기본적으로 반복문의 조건을 flag==0으로 만들어 무한 반복을 하게 한다. 그리고 반복이 될때 마다 cnt++를 통해 cnt값을 1씩 증가 시킨다. 

if조건문으로 cnt==10일때와 cnt==3인 경우를 조건 비교한다. 

cnt==10이면 break로 조건문을 완전히 빠져나가게 하고 , cnt==3이면 이후 출력문을 건너뛰고 다시 반복문 처음으로 가게 한다. 

결과를 보면 커피한잔+cnt 가 출력되나 이중에 cnt==3인 경우에는 커피한잔3을 출력하지 못하고 대신 가자while문으로가 출력된다. 

그리고 cnt==10이 되는 순간 오늘 그만팔고 장사 끝~이라는 내용을 출력하고 반복문이 종료하게 된다. 


오늘은 Switch 조건문과 While, Do While 반복문 그리고 break와 continue에 대해서 살펴 보았다. 

조금 학습량이 많을 수 있다고 생각하나 지난번 If조건문과 for반복문을 통해 조건문과 반복문에 대한 맛을 배웠으니 아예 포기할 정도로 난해하지는 않을 것이다. 

 

지난번 If조건문과 For 반복문의 활용성이 높다고 했다. 오늘 배운 Switch 조건문과 While, Do While 반복문 그리고 break와 continue도 활용성이 절대 떨어지는 문법은 아니다. 비교해보면 비슷한 부분과 또 다른 부분이 있을 것이다. 하지만 다 조건문이고 반복문이라는 개념에서는 변함이 없다. 

 

학습이 진행되면서 새로운 문법과 개념들을 배우게 될 것이다. 그때마다 이해가 되는 경우도 있지만 또 이해가 되지 않거나 어려운 부분도 분명히 있을 것이다. 이때 포기하지 말고 구글링을 통해 다른 설명이나 예제를 보거나 혹은 유투브를 통해 강의를 본다던가 혹은 자기 수준에 맞는 책을 하나 보는것도 좋을 것이다. 

 

위의 예제를 다시한번 살펴보고 다른 유사한 예제를 만들어 풀어보는 것도 좋을것 같다. 모든 것이 그렇듯이 눈으로 보고 고개를 끄덕이는 것만으로는 자기의 것이 될 수없다. 반드시 이클립스를 켜고 예제를 직접 풀어 결과를 확인해 보도록 하자. 

 

어느덧 2019년도가 저물어간다. 아재들의 시간은 더 빨리 더 아쉽게 흘러가기만 한다. 그렇다고 찌뿌둥한 몸을 소파에 기대있지 말고 무엇인가를 해보자. 그게 운동이던, 코딩이던, 아니면 그 무엇이 되었던.