Java Control Flow Statements
Java 프로그래밍, 제어문 ( Control Flow Statements )
제어문 ( Control Flow Statements )
프로그램을 구성하는 코드가 실행될 때 흐름을 제어하기 위해 사용되는 문장이다. 예를 들어, 코드의 일부분을 일정한 횟수만큼 반복해서 실행한다든가, 조건에 따라서 실행할 것인지 그냥 지나갈 것인지를 결정할 수 있는 수단이 필요할 때 제어문을 사용하게 된다
제어문에는 조건문(if, switch), 반복문(for, while, do~while), 분기문(break,continue,return) 등이 있다
가장 간단한 if 문장의 예
public class Tutorials { public static void main(String[] args) { // Scanner를 사용하여 이용자의 키보드 입력을 받아서 이용자를 인증하는 예를 들어보자 // 문자열을 비교할 때는 equals()를 사용한다는 것도 알아두자 Scanner scanner = new Scanner(System.in); System.out.print("아이디와 암호를 공백으로 구분하여 입력하세요:"); String id = scanner.next(); String pwd = scanner.next(); // if문장의 () 안에 있는 조건식은 boolean 값으로 판정되는 변수, 상수, 표현식 등이 올 수 있다 // 조건식이 true 일 경우에만 if 문장의 블럭({ })안에 있는 문장들이 실행되고 false 일 경우에는 // 블럭이 실행되지 않고 바로 블럭 아래의 코드로 분기한다 if(id.equals("SMITH") && pwd.equals("1234")) { System.out.println("로그인에 성공했습니다"); } System.out.println("프로그램 종료..."); } }
위의 코드 실행결과 화면
아이디와 암호를 공백으로 구분하여 입력하세요:SMITH 1234
로그인에 성공했습니다
프로그램 종료...
위의 코드에서 로그인에 실패한 경우에도 이용자에게 경고 메시지를 보여줄 필요가 있을 때는 다음과 같이 if ~ else 문장을 사용할 수 있다. if 의 조건식이 false로 판정되면 else {} 블럭은 반드시 실행되는 방식으로 흐름이 제어된다
if ~ else 를 사용하여 위의 코드를 약간 수정한 예
public class Tutorials { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("아이디와 암호를 공백으로 구분하여 입력하세요:"); String id = scanner.next(); String pwd = scanner.next(); if(id.equals("SMITH") && pwd.equals("1234")) { System.out.println("로그인에 성공했습니다"); } else // if 의 조건식이 false 로 판정될 때 else 블럭은 반드시 실행된다 { System.out.println("에구! 로그인 실패!"); } System.out.println("프로그램 종료..."); } }
다수개의 조건을 검사하려는 경우에는 if~else if~else if 형식을 사용하여 다수개의 조건을 나열할 수 있으며 그 중 한개의 블럭만 실행되도록 할 수 있는 제어문이다
if ~ else if ~ else if 를 사용하여 위의 코드를 약간 변경한 예
public class Tutorials { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("아이디와 암호를 공백으로 구분하여 입력하세요:"); String id = scanner.next(); String pwd = scanner.next(); if(id.equals("SMITH") && pwd.equals("1234")) // 조건 1 { System.out.println("로그인에 성공했습니다"); } else if(!id.equals("SMITH")) // 조건 2 { System.out.println("아이디를 확인해 주세요"); } else if(!pwd.equals("1234")) // 조건 3 { System.out.println("암호를 확인해 주세요"); } System.out.println("프로그램 종료..."); } }
if 문장에 포함된 그 어떤 조건에도 맞지 않은 경우에 실행되는 블럭이 필요하다면 마지막에 else {} 블럭을 두면 된다
if ~ else if ~ else if ~ else 문장을 사용하는 예
public class Tutorials { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("아이디와 암호를 공백으로 구분하여 입력하세요:"); String id = scanner.next(); String pwd = scanner.next(); if(id.equals("SMITH") && pwd.equals("1234")) { System.out.println("로그인에 성공했습니다"); } else if(!id.equals("SMITH") && pwd.equals("1234")) { System.out.println("아이디를 확인해 주세요"); } else if(!pwd.equals("1234") && id.equals("SMITH")) { System.out.println("암호를 확인해 주세요"); } else { System.out.println("아이디, 암호를 모두 확인해 주세요"); } System.out.println("프로그램 종료..."); } }
switch 문장
switch 문장은 if 문장과 달리 다수개의 영역이 실행되도록 할 수 있다. if 문장은 어떠한 경우에도 2개 이상의 블럭이 동시에 실행되도록 할 수 없지만 switch 문장은 가능하다. Calendar를 통해 구한 요일은 숫자형태로 제공되므로 문자열로 변환하여 출력하는 예를 들어본다
switch 문장을 사용할 때 주의할 점은 switch 에 break 를 사용하는 것은 필수가 아니며 필요에 따라서 사용하지 않을 수도 있다. 만약 break를 사용하지 않으면 그 아래의 case 영역도 순차적으로 실행된다
public class Tutorials { public static void main(String[] args) { Calendar cal = Calendar.getInstance(); int today = cal.get(Calendar.DAY_OF_WEEK); String sDate = null; switch(today) // byte,short,char,int 그리고 이들의 Wrapper클래스들, String { case 1: // 반드시 상수이어야 한다 sDate = "일"; break; case 2: sDate = "월"; break; case 3: sDate = "화"; break; case 4: sDate = "수"; break; case 5: sDate = "목"; break; case 6: sDate = "금"; break; case 7: sDate = "토"; break; default: sDate = "오류"; } System.out.printf("오늘은 %s 요일입니다 %n", sDate); } }
switch 문장이 if 문장과 다른 점은 여러개의 조건을 나열하고 그 중 일치하는 조건부터 그 아래의 모든 실행문을 순차적으로 모두 실행할 수 있다는 점이다. 즉, break 문장을 사용하지 않으면 아래에 있는 case 도 무조건 실행되는 방식이다. 이 경우 case 는 switch 문장의 엔트리 포인트 기능을 한다
아래의 예제는 임의의 수 (1 ~ 5)를 추첨하여 해당 수부터 5까지 합산하여 그 결과를 출력하는 경우이다. 프로그램을 실행할 때마다 다른 결과가 나온다
break 없는 switch 문장을 이용하여 임의의 수부터 5까지 합산하는 예
public class Tutorials { public static void main(String[] args) { // Random 클래스를 이용하여 임의의 수를 구하는 방법도 아울러 알아보자 Random random = new Random(); int rdNum = random.nextInt(5); // 0 ~ 4 사이의 임의의 수를 리턴함 rdNum += 1; // 1 ~ 5 사이의 수로 보정한다 int sum = 0; switch(rdNum) { case 1: sum += 1; case 2: sum += 2; case 3: sum += 3; case 4: sum += 4; case 5: sum += 5; //default: 필수적인 요소가 아님 } System.out.printf("%d ~ %d 합산 결과 = %d %n", rdNum, 5, sum); } }
while 반복문
while 문장은 반복문으로 코드의 일정한 영역에 있는 문장들을 반복적으로 실행하고자하는 경우에 사용된다. 특히 코딩시에 반복 실행의 횟수를 미리 정할 수 없는 경우에 자주 사용된다
예를 들어, 1 ~ 10 사이의 수 중에서 중복되지 않도록 5개의 수를 추첨해야 한다면 몇번 추첨해야 중복되지 않게 5개를 모을지 알 수 없는 상황이므로 while문장을 사용하여 5개의 수가 모일 때까지 반복해서 추첨해야 할 것이다.
while 문장은 조건식이 true인지 확인하여 true일 경우에만 while블럭을 실행한다. 블럭이 실행된 후에 다시 조건식을 검사하여 여전히 true이면 다시 while블럭이 반복된다.
또한, 반복문 안에서는 continue, break 등의 제어문도 사용할 수가 있는데, continue 를 사용하면 그 아래 라인을 실행하지 않고 반복문의 처음으로 다시 돌아가 실행되며, break가 반복문에 사용되면 반복문을 종료하고 블럭 밖으로 제어가 이동한다
while 문장을 이용하여 1~10사이의 수로부터 5개를 중복되지 않게 추첨하여 출력하는 예
public class Tutorials { public static void main(String[] args) { int[] nums = new int[5]; // 중복되지 않는 수를 저장할 배열 int tmp = 0; // 추첨된 수를 임시로 저장할 변수 int cnt = 0; // 추첨된 수를 저장할 변수 Random random = new Random(); while(cnt<5) { tmp = random.nextInt(10)+1; // 제어문에서 실행문을 1개만 가지는 블럭은 {}기호를 생략할 수도 있다(권장되지는 않음) if(tmp==nums[0] || tmp==nums[1] || tmp==nums[2] || tmp==nums[3] || tmp==nums[4]) continue; //아래를 실행하지 않고 루프의 처음으로 되돌아간다 nums[cnt++] = tmp; } System.out.println("중복되지 않게 추첨된 수는 다음과 같습니다"); String sNums = Arrays.toString(nums); System.out.printf("%s %n", sNums); } }
위의 코드를 실행한 결과화면
[7, 6, 4, 10, 8]
do { } while(조건); 문장의 필요성
위의 예제에서는 cnt = 0; 으로 설정한 후에 중간에 cnt 값을 변경한 적이 없는데도 while( cnt<5 ) 부분에서 cnt의 값을 검사하고 있다. 변경하지도 않은 값을 검사한다는 것은 합리적이지 않다고 할 수 있다. 일단 한번이라도 cnt 값을 변경한 후에 그 값을 검사하는 것이 당연할 것이다. while 문장을 사용할 때 주의할 점은 while 문장의 끝에 바드시 문장의 마침표( ; )를 사용해야 한다는 것이다
위의 while 문장을 do while 문장으로 변경한 예
public class Tutorials { public static void main(String[] args) { int[] nums = new int[5]; // 중복되지 않는 수를 저장할 배열 int tmp = 0; // 추첨된 수를 임시로 저장할 변수 int cnt = 0; // 추첨된 수를 저장할 변수 Random random = new Random(); do { tmp = random.nextInt(10)+1; // 제어문에서 실행문을 1개만 가지는 블럭은 {}기호를 생략할 수도 있다(권장되지는 않음) if(tmp==nums[0] || tmp==nums[1] || tmp==nums[2] || tmp==nums[3] || tmp==nums[4]) continue; //아래를 실행하지 않고 루프의 처음으로 되돌아간다 nums[cnt++] = tmp; } while(cnt<5); System.out.println("중복되지 않게 추첨된 수는 다음과 같습니다"); String sNums = Arrays.toString(nums); System.out.printf("%s %n", sNums); } }
do while 반복문을 이용하여 무한루프를 사용하는 예
로그인에 성공할 때까지 무한히 로그인 입력을 받아서 검사하는 예제이다
public class Tutorials { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String id = null; String pwd = null; do { System.out.print("아이디와 암호를 공백으로 구분하여 입력해주세요:"); id = scanner.next(); // 아이디 pwd = scanner.next(); // 암호 scanner.nextLine(); // 다음 입력을 위해 입력버퍼를 비운다 if(id.equals("SMITH") && pwd.equals("1234")) { System.out.println("로그인 성공!"); break; // 로그인에 성공하면 반복문을 벗어난다 } } while(true); // 조건이 상수 true 으로 설정되었기 때문에 무한 루프가 될 수 있다 scanner.close(); System.out.println("프로그램 종료..."); } }
for 반복문
for 반복문은 제어문 중에서 가장 복잡한 구조를 가지고 있는 만큼 활용도가 높은 제어문이다. for 문장을 이해하는 핵심은 그 실행순서를 분명히 이해하는 것인데 실행 순서를 이해하면 for 문장을 활용할 수 있는 자신감과 응용력이 생기게 될 것이다. 먼저 아래의 그림을 잘 이해하고 각 부분의 실행순서와 기능에 대해서 아주 자세하게 말할 수 있어야 한다.
for 반복문 사용 예
for 루프는 배열과 함께 자주 사용되므로 여기서도 배열을 초기화하고 배열의 원소를 합산하는 기능을 for 루프를 이용하여 작성하려고 한다.
Random 클래스를 이용하여 무작위 수를 10 추첨하여 배열에 저장하고 또 하나의 for 문장을 이용하여 배열의 원소를 모두 합산하는 코드를 작성해보자.
public class Tutorials { public static void main(String[] args) { Random random = new Random(); int[] nums = new int[10]; // 1~10 사이의 수를 추첨하여 배열에 저장한다 for(int i=0;i<nums.length;i++) { nums[i] = random.nextInt(10)+1; } // 배열에 저장된 수를 모두 합산한다 int sum = 0; for(int i=0;i<nums.length;i++) { sum += nums[i]; } String sArr = Arrays.toString(nums); System.out.printf("배열합산,%s -> %d %n", sArr,sum); } }
위의 코드를 실행한 결과화면
배열합산,[10, 7, 6, 9, 7, 3, 2, 6, 1, 3] -> 54
중첩 for 문장( Nested For Loop )을 이용하여 다차원 배열을 다루는 예
public class Tutorials { public static void main(String[] args) { // 3명의 학생에 대한 5과목의 점수를 배열에 저장하고 각 학생의 평균점수를 출력해보자 // 학생 1명당 5과목 점수를 저장할 데이터 구조가 필요하다. // 각 학생당 5개 과목의 점수는 1차원배열로 생각할 수 있고 3명이므로 원소가 5개인 1차원 배열 3개를 // 저장할 수 있는 데이터 구조는 원소 3개를 가진 2차원 배열을 생각할 수 있다 int[][] students = { {79,90,84,77,98}, {97,98,77,86,89}, {80,88,96,79,88} }; // 2차원배열에 저장된 데이터는 다음과 같이 for문장을 중첩하여 사용하면 쉽게 다룰 수 있다 for(int i=0;i<students.length;i++) { int total = 0; for(int j=0;j<students[i].length;j++) { total += students[i][j]; } int avg = total/students[i].length; System.out.printf("학생 %d 평균=%d %n", i+1, avg); } } }
위의 코드를 실행한 결과화면
학생 2 평균=89
학생 3 평균=86