코드프레소 Java 웹 개발 체험단 활동 중 이번엔 제어문에 대한 포스팅을 하려 한다. 제어문은 진짜 없어서 안될 문법이고 1주차 강의 중 중요한 강의라고 생각한다.
제어문을 처음 접했을 땐 좀 복잡하다고 생각했었지만, 지금와서 보면 개념은 어렵지 않다. (그땐 공부가 너무 하기 싫기도 했었고...ㅎ)
주요 토픽은 조건문, 반복문인데 이에 대해 알아보자.
제어문
자바 프로그램은 기본적으로 위에서 아래로 순차적으로 실행된다.
프로그램의 실행 순서를 제어 가능
- 조건에 따라 실행 코드를 분기 - 조건문
- 특정 코드를 반복해서 실행 - 반복문
조건문
조건에 따라 서로 다른 코드가 실행되도록 분기 처리
ex) 홀수, 짝수 판별 프로그램
- 주어진 숫자를 2로 나눈 나머지가 0이면 짝수 출력
- 주어진 숫자를 2로 나눈 나머지가 1이면 홀수 출력
조건문은 if, else, else if, switch 의 키워드를 사용하여 조건문을 구성한다.
단일 if 문의 활용
문법
- if 다음에 나오는 조건식을 체크 (조건식의 결과는 true or false)
- 조건식의 결과가 true 이면 if 내부의 코드를 실행
- 조건식이 결과가 false 이면 if 내부의 코드를 실행하지 않음
if (조건식) { 조건식의 결과가 true 인 경우 실행할 코드; }
중괄호와 들여쓰기
- 조건문의 중괄호 { } 와 들여쓰기는 필수
- 중괄호 { }는 수행할 코드를 구분하는 역할
- 중괄호 { } 내에서 실행할 코드 작성 시 앞에 들여쓰기는 필수
- 수행할 명령어가 한 줄인 경우 중괄호 { } 생략 가능하지만 표시하는 것을 권장
최근 아프리카tv 신입 공채에서 면접 질문으로 이 if문 중괄호 관련 질문이 들어왔다.
중괄호 없이 한 줄로 표기 가능한 if문이 있을 경우, 중괄호를 그래도 사용할 것이냐 안 할 것이냐 그리고 답에 대한 이유도 서술해야 했다.
나는 학부 수업에선 사용하지 않았지만, 실무에서는 사용을 해야 한다고 대답을 하였다. 이유는 중괄호를 사용함으로써 코드 범위의 가독성이 좋을 뿐더러 해당 if 문에서 코드 수정이 용이할 수 있기에 괄호를 사용하는 것이 좋다고 답변하였다. 그러나 정답이 존재한 답변이 아니고 나 역시 확실한 답변이라고 할 순 없으나 지금도 이것이 최선의 답변이라고 생각한다.
마찬가지로 코드프레소 이러닝 강의 수강 중 가독성에 대한 이야기를 해주셨고 사용하는 것에 대해 권장 사항이라 하였으니 개인적으로 옳은 답변을 했다고 생각한다.
boolean 자료형과 조건문
boolean 결과를 가지는 명령은 조건식을 구성할 수 있다.
age < 19 (X % 2) == 0 password.equals("1234") boolean isSystemReady = false;
boolean isSystemReady = true; if (isSystemReady) { System.out.println("System is ready for use!"); }
if - else 문의 활용
조건식의 결과가 true 이면 if 내부의 코드만 실행
조건식이 결과가 false 이면 else 내부의 코드만 실행
if (조건식) { 조건식의 결과가 true 인 경우 실행할 코드; } else { 조건식의 결과가 false인 경우 실행할 코드; }
else 구문은 if 구문의 조건식 없이 단독으로 사용 불가!
int errorCode = 500; if (errorCode >= 500) { System.out.println("Server Error!"); } else { System.out.println("Client Error!"); }
예제로 에러 코드가 500 이상인 경우 서버 에러 메세지를 출력하고 에러 코드가 500 미만인 경우 클라이언트 에러 메세지를 출력한다.
이 코드는 나중에 할 프로젝트에서도 ORM 기반을 사용하게 되면 많이 볼 코드 같다.... 캡스톤 프로젝트를 하면서 처음으로 에러 코드를 접해봤었는데, 아직 공부해야 할 부분이 많다고 느꼈다.
if - else - else if 활용
else if는 다중 조건인 경우 사용된다.
if (조건식1){ 조건식1의 결과가 true인 경우 실행할 코드; } else if(조건식2) { 조건식2의 결과가 true인 경우 실행할 코드; } . . . . . . . . else { 모든 조건식의 결과가 false 인 경우 실행할 코드; }
조건식 1이 false이면 다음 else if문을 조건문을 실행하고 해당 코드가 true인 경우 실행을 한다.
String memberShip = "VVIP"; if(memberShip.equals("VVIP")){ discountRate = 0.2; coupons = 5; } else if(memberShip.equals("VIP")){ discountRate = 0.1; coupons = 4; } else{ discountRate = 0.0; coupons = 2; } System.out.println(discountRate + "\n" + coupons);
이와 같이 VVIP에 대한 서비스를 제공할 때 제어문으로 할인율과 쿠폰을 책정한다.
- if 문은 반드시 최초에 1번 사용
- else if 문은 없거나 1번 이상 다중 사용 가능
- else 문은 없거나 마지막에 1번 사용
조건문의 중첩
if - else if - else 문 하위에 또 다른 if (else, else if) 문이 중첩된 형태
이와 같은 순서도로 조건식 안에 조건식을 넣어 범위 안에 또 다른 조건 범위를 생성하는 것이다.
int score = 98; int attendance = 71; // score가 70 이상인 경우 if (score >= 70) { if(attendance >= 80) { // 조건내에 attendance가 80 이상인 경우 result = "PASS"; // result는 PASS } else { // 그렇지 않은 경우 result = "FAIL"; // result는 FAIL이 된다. } } else { // 만약 score가 70 미만인 경우는 attendance를 따지지 않고 result는 FAIL이 된다. result = "FAIL"; }
중첩 조건문은 코드 가독성을 저하
- 깊은 레벨로 중첩된 조건문은 코드의 가독성을 저하시킨다.
- 복잡도를 낮추고 가독성을 높이기 위한 고민 필요
- 조건을 단순화할 수 있을지 고민
- 다형성 활용
이 다형성 활용은 객체지향에서 다루겠지만 정말 중요한 개념으로 많이 사용된다.
switch - case 문
조건문을 switch - case 문으로 표현 가능
조건식의 경우 수가 많아지더라도 간결하게 표현할 수 있다.
처리속도가 if - else if 문보다 빠르다.
switch - case 문의 작성
switch 문에는 조건식을 기재하고 중괄호 { }로 블록을 만든다.
case 문에는 조건식에 대한 결과 값을 명시하고, 끝에 콜론 : 을 붙인다.
case 문 내에는 각각 수행할 코드와 끝에 break; 를 작성한다.
default : 문을 작성한다.
switch (조건식) { case 값1 : // 조건식의 결과가 값1인 경우 수행할 코드 break; case 값2: // 조건식의 결과가 값2인 경우 수행할 코드 break; default: // 조건식의 결과와 일치하는 case 문이 하나도 없는 경우 수행할 코드 }
switch - case 문의 순서
- switch 문의 조건식을 계산함
- 결과와 일치하는 case 문을 찾아서 코드를 수행한다.
- break 문을 만나면 1의 switch 문을 빠져 나간다.
String result; String grade = "A0"; switch (grade) { case "A+": case "A0": result = "Excellent"; break; case "A-": case "B+": case "B0": case "B-": result = "Good"; break; default: result = "Poor"; } System.out.println(result);
grade가 A0이므로 Excellent가 출력될 것이다.
배열
배열의 선언
자료형 뒤에 [ ]를 붙여서 배열임을 선언할 수 있다.
자료형[] 변수명;
ex) int[] array;
- Java 배열은 객체이며, 선언과 동시에 객체 생성이 가능
- new 키워드를 사용
- 생성 시 배열의 길이를 명시한다.
자료형[] 변수명 = new 자료형[길이];
ex) int[] array = new int[10];
길이가 10인 int 형의 배열 객체를 생성한 것이고 array 변수에 생성한 배열 객체의 참조를 저장한다.
또한 배열의 선언 동시에 생성과 초기화를 하는 문법도 제공되어
자료형[] 변수명 = {값1, 값2, ..., 값n};
배열의 크기는 중괄호 안의 comma로 구분된 값의 개수에 따라 결정된다.
배열의 index
- 배열의 각 값들은 고유한 번호를 갖고 있는데 이를 index라고 부른다.
- index는 0부터 길이-1까지의 범위를 가지고 있다.
- index를 활용하여 배열 내부 값을 사용해 연산도 가능하다.
- ex) System.out.println(ages[0] + ages[1]); // index 0번과 1번의 더하기 연산 값 출력
index를 활용해 배열 값 변경
- 생성된 배열의 내부 값을 변경 가능하다.
- 변경할 index를 지정하여 대입 연산자의 왼편에 위치한다.
변수명[index] = 새로운 값;
배열의 길이 확인
- 배열은 객체이고, 객체는 속성을 갖고 있다.
- 배열 객체는 length라는 속성을 보유하며 변수의 길이를 가지고 있다.
ex) System.out.println(ages.length); // ages 배열의 길이를 출력
반복문
특정 코드 집합(코드 블록)을 반복적으로 수행
주어진 조건을 만족할 때까지 반복하거나, 일정 횟수만큼 반복
for문
- 반복문을 위한 for 키워드를 사용하여 구문을 시작
- 반복을 위한 특정 조건을 (초기식; 조건식; 증감식)으로 구분
- 중괄호 { }로 for문의 코드 블록을 명시
- 조건식의 결과가 true인 동안 반복적으로 실행할 코드들을 입력
for (초기식; 조건식; 증감식) { 조건식의 결과가 true인 동안 반복적으로 실행할 코드들; }
for문의 흐름
- 초기실을 실행한다.
- 조건식을 실행하여 조건식의 결과가 true이면,
- 반복문 내의 코드를 실행한다.
- 코드 실행이 모두 끝나면 증감식을 실행한다.
- 만약 조건식의 결과가 false이면, 반복문이 종료된다.
for문의 제어 - 증감식
- 반복문을 제어하는 변수의 값을 증가 또는 감소시키는 식
- 증가 연산자(++), 감소 연산자(--)를 통해 제어한다.
- 대입 연산자(i+=2)를 활용할 수도 있다.
String text = "I AM YUNBEOM"; for (int i = 0; i < text.length(); i++){ System.out.println(text.charAt(i)); } // text를 한문자씩 출력 int startIdx = text.length() - 1; for(int i = startIdx; i >= 0; i--){ System.out.println(text.charAt(i)); } // text를 역순으로 출력
반복문과 배열
- 배열 객체에 저장된 데이터를 반복적으로 접근할 때 반복문을 활용할 수 있다.
- 배열의 길이를 가져오는 배열명.length를 활용
- 배열의 값을 가져오는 경우는 배열명[index]를 활용
String[] languages = {"Java", "Python", "C", "C++"}; for(int i = 0; i < languages.length; i++){ System.out.println(languages[i]); }
여기서 약간의 함정?이 있다. 위에 예제에 배열이 아닌 문자열일 때, for안에 조건식에서 length()를 쓰는데 배열에서는 length를 사용한다.
배열일 때는 배열의 길이를 가져오기 위해 length만을 사용하고 문자열일 땐 length 메서드를 포함하고 있으니 length()를 사용한다. 이 점의 차이를 알고 사용하는 것이 좋다.
반복문에 조건문 넣기
반복문 내에서 특정 조건을 확인하기 위한 별도의 조건문을 넣을 수 있다.
이번 라이브 강의에서 연습문제 1,2번의 문제가 반복문에 조건문 넣기 문제였다.
예제 겸 연습문제 리뷰를 이번 토픽에서 하려 한다.
//1. 1부터 100까지의 숫자 중 2의 배수와 3의 배수와 5의 배수와 7의 배수를 모두 제외하고 출력하세요 public class Excercise1 { public static void main(String[] args) { for(int i = 1; i <= 100; i++){ if((i % 2 != 0) && (i % 3 != 0) && (i % 5 != 0) && (i % 7 != 0)) System.out.println(i); } } }
1번 문제는 1에서 100 사이의 2,3,5,7의 배수만을 제외한 숫자를 출력하는 것이다.
문제를 해석할 땐 조건을 파악하고 제어문으로 어떻게 코드로 옮기는지와 제어문을 얼마나 이해하는지에 출제 의도가 있다.
바로 보자마자 !=, && 연산자와 if문 내에 괄호를 이용하여 풀었다.
// 2. 1부터 1000까지의 숫자 중 3의 배수이면서, 동시에 5의 배수인 숫자를 출력하시오 // - 조건1: 출력 된 숫자가 10개가 되면 프로그램 종료 // - 조건2: 프로그램 종료 전 출력 된 10개의 숫자의 합을 출력 public class Excercise2 { public static void main(String[] args) { int sum = 0, check = 0; for(int i = 1; i <= 1000; i++){ if((i % 3 ==0) && (i % 5 == 0)) { sum += i; System.out.println("Found number = " + i); check++; } if(check == 10){ break; } } System.out.println("Sum = " + sum); } }
2번 문제도 1번 문제와 비슷한 조건을 사용하는데 이번엔 3,5의 배수가 동시에 충족되면서 조건이 2개 더 추가되었다.
어렵게 느끼지는 않는다. 변수 추가와 if문 추가하면 바로 풀리는 문제이다.
- 우선 누적할 int형 변수 sum을 0으로 초기화하고, 출력 개수를 체크할 check변수를 0으로 초기화하여 선언한다.
- 1부터 1000까지의 반복문을 선언한다.
- 다음 조건에 맞는 3,5의 배수 조건문을 선언하고
- 조건문 내에 += 연산자를 활용하여 sum 변수에 누적하고, 출력문이 출력될 시 ++ 연산자로 check를 증감한다.
- 조건문을 추가하여 check가 10이 되면 반복문을 탈출하도록 break;를 걸어준다.
- 마지막으로 sum 출력한다.
Enhance for문
- 배열 내 저장된 모든 값을 순차적으로 참조하기 위한 다른 형태의 for문
- for-each style 이라고도 불린다.
String[] languages = {"Java", "Python", "C", "C++"}; for(String language : languages){ System.out.println(language); }
- for문의 첫 번째 값은 저장할 원소 데이터의 자료형과 변수명을 명시
- 콜론 : 을 기재
- 원소 데이터가 저장되어 있는 배열의 이름을 명시
- 중괄호 { } 내에는 명시한 배열의 길이만큼 실행할 코드를 작성
for (자료형 변수명 : 배열명 ) { 명시한 배열의 길이만큼 반복문 내에 실행할 코드; }
여기서 자료형 변수명은 임의로 해도 무방하지만, 가독성이 좋은 이름이 더 좋다.
- Enhanced for 문은 별도의 종료 조건을 명시하지 않음
- 배열에서 가져올 원소 데이터가 더 이상 없는 경우 반복문은 종료됨
- 주로 배열, 컬렉션 등에 저장된 원소 데이터를 읽는 목적으로 사용됨
Enhance for문의 흐름
- 배열로부터 원소 데이터를 가져와 변수에 저장한다.
- 반복문 내의 코드를 실행한다. 이때, 배열의 원소 데이터가 저장된 변수를 활용할 수 있다.
- 코드 실행이 끝나면 1부터 반복한다.
중첩 for문
for문 안에는 또 다른 for문을 중첩하여 실행할 수 있다.
중첩의 횟수는 제한이 없으나, 가독성 및 복잡성을 고려하여야 한다.
String[] orderList = {"Order_1", "Order_2", "Order_3"}; String[] processList = {"Checking", "Cooking", "Packaging", "Delivering"}; for (String order : orderList) { for (String process : processList) { System.out.println(order + "is in " + process + " stage."); } System.out.println(); }
while 문
반복문 구현을 위한 방법 중에 하나로 구조가 비교적 간결함
- 반복문을 위한 while 키워드를 사용하여 구문을 시작
- 반복을 위한 조건식을 작성
- 중괄호 { } 내에는 조건식의 결과가 true인 동안 실행할 코드들을 작성
while (조건식) { 조건식의 결과가 true인 동안 반복적으로 실행할 코드들; }
- while 문 조건식의 결과가 true 이면,
- 반복문 내의 코드를 실행한다.
- 코드의 실행이 모두 끝나면 1번 조건식을 다시 실행한다.
- 1번 조건식이 false이면 반복문이 종료된다.
이번엔 연습문제 3번을 리뷰해보려 한다.
3번은 while문과 switch - case 문 활용한 문제이다.
//3. 간단한 블로그 프로그램을 작성하세요 // - 기능1: 프로그램이 시작 되면 메뉴를 정보를 출력하세요(1 - View blog list, 2 - Write a blog post, 3 - Quit) // - 기능2: 사용자로부터 메뉴를 입력 받으세요 // - 기능3: 사용자가 1을 선택할 경우 작성 된 블로그 리스트를 출력하세요. // 블로그 리스트 출력 후에는 다시 메뉴 정보가 노출됩니다. // - 기능3: 사용자가 2를 선택할 경우 블로그 글을 작성할 수 있습니다. // 블로그 글은 제목과 내용이 저장 됩니다. 블로그 글 저장이 끝나면 다시 메뉴 정보가 노출됩니다. // - 기능4: 사용자가 3을 선택할 경우 프로그램이 종료 됩니다. // - 조건2: 블로그 글은 최대 20개까지만 저장할 수 있습니다. public class Excercise3 { public static void main(String[] args) { String[] titles = new String[20]; String[] posts = new String[20]; int menu; int countOfPosts = 0; boolean isQuit = false; while(!isQuit) { System.out.println("\n1 - View blog lists"); System.out.println("2 - Write a blog post"); System.out.println("3 - quit"); System.out.print("Enter the menu : "); Scanner input = new Scanner(System.in); menu = input.nextInt(); switch (menu) { case 1: for(int i = 0; i < countOfPosts; i++) System.out.println(titles[i] + " | " + posts[i]); break; case 2: System.out.print("Enter title : "); Scanner inputTitle = new Scanner(System.in); String title = inputTitle.nextLine(); titles[countOfPosts] = title; System.out.print("Enter post : "); Scanner inputPost = new Scanner(System.in); String post = inputPost.nextLine(); posts[countOfPosts] = post; countOfPosts++; break; case 3: isQuit = true; break; } } } }
3번 문제는 간단한 블로그 프로그램이다.
- 1,2,3번의 메뉴 기능이면 거의 switch - case 문을 생각한다.
- 메뉴를 선택하고 다시 메뉴 정보를 노출하도록 요구사항이 있으면 while(true) 이 문법이 생각해본다.
- 변수는 정확이 어느 것이 필요한 지 미리 구상해본다.
- 필요한 변수는 블로그의 title, post String 배열과 포스팅된 블로그 개수를 누적할 countOfPosts를 0으로 초기화해서 선언, 메뉴를 선택할 int형 menu 변수, 그리고 while문 탈출 여부를 결정할 boolean 변수 isQuit 정도 있으면 된다.
- 추가로 Scanner를 다루지는 않았지만 C의 scanf를 사용하듯이 사용하면 된다.
- 먼저 isQuit를 false로 초기화하여 while문 조건 true로 실행한다.
- 다음 출력문과 메뉴를 선택할 menu 변수를 입력받는다. (1,2,3 외 다른 번호에 대한 예외 처리는 하지 않았습니다.)
- switch - case문으로 1,2,3의 기능을 정의한다.
- 1번 메뉴는 포스팅된 개수만큼 title과 post 내용을 출력한다.
- 2번 메뉴는 블로그를 작성할 수 있도록 title과 post의 문자열을 입력한다. 입력 후에는 countOfPosts를 증감한다.
- 3번 메뉴는 isQuit를 true로 하여 반복문을 탈출할 수 있도록 한다.
무한 루프
while문은 조건식 결과가 계속 true 이면 반복문을 실행한다.
while문 중괄호 { } 내에서는 조건식의 결과를 false로 만들 수 있는 별도의 코드가 필요하다.
그렇지 않으면 무한 루프가 발생한다.
while문을 활용한 반복문 작성 시에는 코드 내에서 의도하지 않은 무한 루프가 발생할 가능성이 있는지 여부를 충분히 검토해야 한다.
break와 continue
반복문은 조건식의 결과가 true인 동안에는 반복적으로 실행된다. 따라서, 원하는 시점에 반복문을 제어하는 명령어인 break와 continue가 존재한다.
- break: 반복문을 완전히 탈출
- continue: 현재 반복을 중단하고 다음 반복으로 넘어간다.
break
- 자신과 가장 가까운 반복문 전체의 실행을 중단한다.
- 주로 반복문 초입에 if문과 함께 사용된다.
- 사용 예시는 문제 2번과 3번에 나와있다.
continue
- 반복문 진행 중에 continue를 만나면 현재 반복을 중단하고, 다음 반복을 위해 조건식으로 이동하여 true이면 반복문을 계속 실행한다.
- if문 내부에서 주로 사용된다.
int[] userPermission = {1, 5, 0, 4, 2, 5, 3, 0, 1}; for(int permission : userPermission) { if(permission == 0){ System.out.println("Permission Denied!"); continue; } System.out.println("This permission(" + permission + ") allow access to data!"); }
'Java' 카테고리의 다른 글
Java - 상속, 다형성, 메소드 오버라이딩, 컬렉션 (0) | 2022.01.25 |
---|---|
Java - 객체지향 설계, 클래스, 생성자, 메소드 오버로딩 (2) | 2022.01.21 |
Java 입문 (자료형 및 연산자) (2) | 2022.01.17 |