JAVA LV 3-1

조건문과 반복문

Posted by Gihoon on March 14, 2023

조건문 - if, switch

조건문은 조건식과 문장을 포함하는 블럭{}으로 구성되어 이씅며, 조건식의 연산결과에 따라
실행할 문장이 달라져서 프로그램의 실행흐름을 변경할 수 있다.
조건문은 if문과 switch문, 두 가지가 있으며 주로 if문이 사용된다. 처리할 경우의 수가 많을 때는
if문보다 switch문이 효율적이지만, switch문은 if문보다 제약이 많다.

if문

if문은 가장 기본적인 조건문이며, 다음과 같이 ‘조건식’과 ‘괄호{}’로 이루어져 있다.
‘if’의 뜻이 ‘만일 ~이라면’이므로 ‘만일 조건식이 참이면 {}안의 문장들을 수행하라’라는 의미로 이해하면 된다.

1
2
3
if (조건식) {
	//조건식이 참일때 수행할 문장을 적는다
}

조건식

if문에 사용되는 조건식은 일반적으로 비교연산자와 논리 연산자로 구성된다.

조건식을 작성할 때 실수하기 쉬운 것이, 등가비교 연산자 ‘==’ 대신 대입 연산자 ‘=’를 사용하는 것이다.
예를 들어 ‘x가 0일때 참’ 인 조건식은 ‘x == 0’ 인데, ‘x=0’일고 적으면 에러가 발생한다. **자바에서 조건식의 결과는 반드시 true 또는 flase 여야만 한다.

블럭{}

괄호{}를 이용해서 여러 문장을 하나의 단위로 묶을 수 있는데 이것을 ‘블럭’이라고 한다.
블럭의 끝에는 문장의 끝을 의미하는 세미클론 ; 을 붙이지 않는다는것을 주의하자.
블럭 내의 문장들은 탭으로 들여쓰기를 해서 블럭안에 속한 문장이라는 것을 알기 쉽게 해주는 것이 좋다.

1
2
3
4
	if (score > 60)
	{
		System.out.println("합격입니다.");
	}

블럭의 시작을 의미하는 { 의 위치는 아래의 경우 처럼 두가지가 있는데 취향에 맞게 선택하면 된다.

1
2
3
	if(조건식){
	...	
	}
1
2
3
4
	if(조건식)
	{	
	...	
	}

블럭 안에는 보통 여러 문장을 넣지만, 한 문장만 넣거나 아무런 문장도 넣지 않을수도 있다.
만일 블럭 내의 문장이 하나뿐일때는 괄호{}를 생략할 수있다.

1
2
if(score>60)
	System.out.println("합격입니다")

if-else문

if문의 변형인 if-else 문은 다음과 같다.

1
2
3
4
5
	if (조건식) {
	...
	} else {
	...
	}

조건식의 결과에 따라 이 두개의 블럭 중 어느 한 블럭의 내용이 수행되고 전체 if문을 벗어나게 된다.
두 블럭의 내용이 모두 수행되거나, 모두 수행되지 않는 경우는 없다.

if-else if문

if-else 문은 두 가지 경우 중 하나가 수행되는 구조인데, 셋이상의 경우면 if else if문을 사용한다.

1
2
3
4
5
	if(조건식) {
	} else if (조건식){
	}  else if (조건식){
	} else {
}

첫번째 조건식부터 순서대로 평가해서 결과가 참인 조건식을 만나면, 해당 블럭만 수행하고 전체 if문을 벗어난다.
만일 참인 조건식이 없으면 마지막에 있는 else블럭의 문장들이 수행된다. 그리고 else 블럭은 생략이 가능하다.
생략되었을 경우에는 if-else if문의 어떤 블럭도 수행되지 않을 수 있다.

중첩 if문

if문의 블럭 내에 또 다른 if문을 포함시키는 것이 가능한데 이것을 중첩 if문이라고 부른다. 중첩의 횟수는 제한이 없다.

1
2
3
4
5
6
7
8
9
	if (조건식) {
	...
		if (조건식2) {
		} else {
		...	
		}
	} else {
	...		
	}

위와 같이 내부의 if문은 외부의 if문보다 안쪽으로 들여쓰기를 해서 두 if문의 범위가 구분되도록 작성해야한다.

switch문

if문은 조건식의 결과가 참과 거짓 밖에 없으므로 경우의 수가 많아지면 else-if를 계속 추가해야하므로 복잡해지고 처리시간도 오래걸린다.
이러한 if문과 달리 switch문은 단한의 조건식으로 만ㅎ은 경우의 수를 처리할 수있다.
따라서 경우의 수가 많은 경우에는 if문보다 switch문으로 작성하는 것이 좋다. 다만 switch문은 제약조건이 있기 때문에, 경우의 수가 많아도 if문을 사용해야하는 경우가 있다.
switch문의 계산 방식

  1. 조건식을 계산한다.
  2. 조건식의 결과와 일치하는 case문으로 이동한다.
  3. 이후의 문장들을 수행한다.
  4. break문이나 switch문의 끝을 만나면 switch문 전체를 빠져나간다.
1
2
3
4
5
6
7
8
9
10
	switch (조건식) {
		case 값1 :
			...	
			break;
		case 값2 :
			...		
			break;
		default :
		...// 조건식의 결과와 일치하는 case문이 없을 때 수행될 문장들
	}

만일 조건식의 결과와 일치하는 case문이 없을 경우에는 default문으로 이동한다.
switch문에서 break 문은 각 case 문의 영역을 구분하는 역할을 하는데, break문을 생략하면 case문 사이의 구분이 없어지므로 다른 vreak문을 만나거나 블럭의 끝을 만날때까지 나오는 모든 문장을 수행한다. 이러한 이유로 case문의 끝에 break문을 뺴먹는 실수를 하지 않도록 한다.
경우에 따라서는 고의적으로 break문을 생략하는 경우도 있다.

1
2
3
4
5
6
7
8
	switch (level) {
		case 3 :
			grantDelete();
		case 2 :
			Write():
		case 3 :
			Read();
	}

위의 코드는 사용자의 등급을 체크하여 등급에 맞는 권한을 부여하는 방식이다.
레벨 3의 사용자는 세가지의 권한을 사용할 수있고, 2의 사용자는 write,read의 권한만을 갖게된다.

switch문의 제약조건

switch문의 조건식은 결과값이 반드시 정수이어야 하며, 이 값과 일치하는 case문으로 이동하기 때문에 case문의 값 역시 정수이어야한다.
또한 중복되지 않아야 한다. 게다가 case문의 값은 반드시 상수 이어야 한다. 따라서 정리하면 아래와 같다.
switch문의 조건식 결과는 정수 또는 문자열이어야 한다. case문의 값은 정수 상수만 가능하며, 중복되지 않아야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.util.*;

class FlowEx6 {
	public static void main(String[] args) { 
		int month = 0;

		System.out.print("현재 월을 입력하세요>");

		Scanner scanner = new Scanner(System.in);
		String tmp = scanner.nextLine(); // 
		month = Integer.parseInt(tmp);   //

		switch(month) {
			case 3: 
			case 4: 
			case 5:
				System.out.println("현재의 계절은 봄입니다..");
				break;
			case 6: case 7: case 8:
				System.out.println("현재의 계절은 여름입니다..");
				break;
			case 9: case 10: case 11:
				System.out.println("현재의 계절은 가을입니다..");
				break;
			default:
	//		case 12:	case 1: case 2:
				System.out.println("현재의 계절은 겨울입니다.");
		}
	} // main     
}

간단한 해당하는 계절을 출력하는 예제이다.
case문은 한 줄에 하나씩 쓰던 한줄에 붙여 쓰던 상관없다

switch문의 중첩

if문처럼 switch문도 중첩이 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class FlowEx11 {
	public static void main(String[] args) { 
		char gender;
		String regNo = "";
		System.out.print("       ֹι ȣ    Է  ϼ   .(011231-1111222)>");

		Scanner scanner = new Scanner(System.in);
		regNo = scanner.nextLine();

		gender = regNo.charAt(7); //  Է¹      ȣ   8  °    ڸ  gender       

		switch(gender) {
			case '1':
			case '3':
				switch(gender) {
					case '1':
					System.out.println("      2000                     Դϴ .");
						break;
					case '3':
					System.out.println("      2000      Ŀ             Դϴ .");
				}
				break;    //    break             ʵ        
			case '2':
			case '4':
				switch(gender) {
					case '2':
					System.out.println("      2000                     Դϴ .");
						break;
					case '4':
					System.out.println("      2000      Ŀ             Դϴ .");
						break;
				}
				break;
			default:
				System.out.println("  ȿ           ֹε Ϲ ȣ Դϴ .");;
		}
	} // main     
}

주의할점은 중첩 switch문에서 break문을 빼먹으면 안된다.

반복문 -for, while, do-while

반복문은 어떤 작업이 반복적으로 수행되도록 할 때 사용된다.
for문이나 while문에 속한 문자은 조건에 따라 한번도 수행되지 않을 수 있지만 do-while 문에 속한 문장은 무조건 최소한 한번은 수행될 것이 보장된다.
반복문은 주어진 조건을 만족하는 동안 주어진 문장들을 반복적으로 수행하므로 조건식을 포함하며, if문과 마찬가지로 조건식의 결과가 true이면 참이고, false이면 거짓이다.
for문과 while문은 구조와 기능이 유사하여 서로 변환이 가능하므로 어느쪽을 선택해도 좋으나 for문은 주로 반복횟수를 알고 있을때 사용한다.

for문

for문은 반복횟수를 알고 있을떄 적합하다. 간단한 예를 보자.

1
2
3
	for (int i=1;i<=5;i++) {
		System.out.println("i can do it");
	}

변수 i에 1을 저장한 다음 매 반복마다 i의 값을 1씩 증가시킨다. 그러다가 i의 값이 5를 넘으면 반복을 마치게 된다.

for문의 구조와 수행순서

for문은 아래와 같이 ‘초기화’, ‘조건식’, ‘증감식’ ‘블럭’ 모두 4부분으로 이루어져 있으며 조건식이 참인 동안 블럭내의 문장을 반복하다가 거짓이 되면 반복문을 벗어난다.

1
2
3
for (초기화;조건식;증감식 {
...
}

초기화

반복문에 사용될 변수를 초기화하는 부분이며 처음에 한번만 수행된다. 보통 변수 하나로 for문을 제어하지만, 둘 이상의 변수가 필요할 때는 아래와 같이 콤마를 구분자로 변수를 초기화 하면 된다. 단, 두변수의 타입은 같아야 한다.

1
for(int i=1,j=0;i<=10;i++){}//int 타입의 변수 i와 j를 선언하고 초기화

조건식

조건식의 값이 참이면 반복을 계속하고, 거짓이면 반복을 중단하고 for문을 벗어난다.
조간식을 잘못 작성하면 {}내의 문장이 한번도 수행되지 않거나 영원히 반복되는 무한반복에 빠지기 쉬우므로 주의해야한다.

증감식

반복문을 제어하는 변수의 값을 증가 또는 감소시키는 식이다. 다음와 같이 다양한 증감식이 있다.

1
2
3
4
for(int i=1;i<=10;i+)
for(int i=1;i<=10;i--)//10부터 1까지 1씩 감소
for(int i=1;i<=10;i+=2)//1부터 10까지 2씩 증가
for(int i=1;i<=10;i*=3)//1부터 10까지 3배씩 증가

중첩 for문

if문과 마찬가지로 for문안에 또 다른 for문을 포함시킬 수 있다. 중첩의 횟수는 거의 제한이 없다.

향상된 for문

1
2
3
for (타입 변수명 : 배열 또는 컬렉션) {
...
}

위의 문장에서 타입은 배열 또는 컬렉션의 요소의 타입이어야 한다. 배열 또는 컬렉션에 저장된 값이 매 반복마다 순서대로 하나씩 읽혀서 변수에 저장된다.

1
int[] arr = {10, 20, 30, 40}

배열 arr을 위와같이 선언 했을때 이 배열의 모든 요소를 출력하는 for문은 다음과 같다.

1
2
3
for(int i=0;i < arr.length; i++) {
	System.out.println(arr[i]);
}

위의 예제는 일반적인 for 문이지만 향상된 for문으로 간략하게 만들 수 있다. 다음 예시를 보자.

1
2
3
for(int tmp : arr) {
	System.out.println(tmp);
}

while문

for문에 비해 while 문은 구조가 간단한다. if 문처럼 조건식과 블럭만으로 이루어져있다.
다만 if문과 달리 while문은 ‘참인동안’, 즉 조건식이 거짓이 될 때까지 블럭내의 문장을 반복한다.

1
2
3
	while (조건식) {
		// 조건식의 연산결과가 참인동안 반복될 문장들을 적는다.
	}

while문은 먼저 조건식을 평가해서 조건식이 거짓이면 문장 전체를 벗어나고 , 참이면 블럭내의 문장을 수행하고 다시 조건식으로 돌아간다.

for문과 while문의 비교

1부터 10까지 정수를 순서대로 출력하는 for문을 whlie문으로 변경하면 다음과 같다.

1
2
3
4
5
6
7
8
9
10
for문
	for(int i=1;i<=10;i++;){
	System.out.println(i);
	}
while문
	int i=1;
	while(i<=10){
	System.out.println(i);
	i++;
	}

while문의 조건식은 생략 불가

한가지 주의할점은 for문과 달리 while문의 조간식은 생략할 수 없다는 것이다.

do- while문

do-while 문은 while문의 변형으로 구조는 while 문과 같으나 조건식과 블럭의 순서를 바꾼것이다. 그래서 while문과 반대로 블럭을 수행한 후에 조건식을 평가한다. whlie문은 조건식의 결과에 따라 블럭이 수행되지 않을 수 있지만 do-while문은 최소한 한번은 수행될 것을 보장한다.

1
2
3
	do {
	...
	}while (조건식);

break문

break문은 자신이 포함된 가장 가까운 반복문을 벗어난다. 주로 if문과 함꼐 사용되어 특정 조건을 만족하면 반복몬을 벗어나도록 한다.

continue문

continue문은 반복문 내에서만 사용할 수있으며, 반복이 진행도는 도중에 continue문을 만나면 반복문의 끝으로 이동하여 다음 반복으로 넘어간다.
for문의 경우 증감식으로 이동하며, while문과 do-while문의 경우 조건식으로 이동한다.
break문과는 다르게 반복문 전체를 벗어나지 않고 다음 반복을 계속 수행한다는 점이 다르다.
주로 if문과 함꼐 사용되어 특정 조건을 만족하는 경우에 continue문 이후의 문장들을 수행하지 않고 다음 반복으로 넘어가서 계속 진행하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
	public static void main(String[] args) {
		for(int i=0;i <= 10;i++) {
			if (i%3==0)
				continue;
			System.out.println(i);
		}
	}
}
실행결과:
1
2
4
5
7
8
10

1과 10사이의 숫자를 출력하되 그 중에서 3의 배수인 것은 제외하도록 작성한 코드이다.
i의 값이 3의 배수인 경우 if문의 조건식이 참이 되어 continue문에 의해 반복문의 블럭으로 이동하게 된다.
즉 continue문과 반복문 블럭의 끝 사이의 문장들을 건너뛰고 반복을 이어가는 것이다.

이름 붙은 반복문

break문은 근접한 단 하나의 반복문만 벗어날 수 있기 때문에, 여러개의 반복문이 중첩된 경우에는 break문으로 중첩 반복문을 완전히 벗어날 수없다.
이때는 중첩 반복문 앞에 이름을 붙이고 braek문과 continue문에 이름을 지정해 줌으로써 하나 이상의 반복문을 벗어나거나 반복을 건너뛸수있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class FlowEx33 {
	public static void main(String[] args)
	{
        // for     Loop1 ̶    ̸     ٿ   .
		Loop1 : for(int i=2;i <=9;i++) {	
				for(int j=1;j <=9;j++) {
					if(j==5)
						break Loop1;
//						break;
//						continue Loop1;
//						continue;
					System.out.println(i+"*"+ j +"="+ i*j);
				} // end of for i
				System.out.println();
		} // end of Loop1

	}
}
실행결과:
2*1=2
2*2=4
2*3=6
2*4=8

구구단을 출력하는 예제이다. 제일 바깥에 있는 for문에 Loop1이라는 이름을 붙였다. 그리고 j가 5일때 break문을 수행하도록 했다. 반복문의 이름이 지정되지 않은 break문은 자신이 속한 하나의 반복문만 벗어날 수 있지만, 지금처럼 반복문에 이름을 붙여주ㅗ break문에 반복문 이름을 지정해주면 하나 이상의 반복문도 벗어 날 수있다.
j가 5일때 반복문 loop1을 벗어나도록 했으므로 2단의 4번째 줄까지 밖에 출력되지 않는다.
만약 이름이 지정되지 않은 break문이었다면 2단부터 9단까지 모두 4줄씩 출력됬을 것이다.