자바 뿐만 아니라 어지간한 프로그래밍 언어들은 모두 가지고 있는 조건문과 반복문이다.
이 조건문과 반복문의 가장 큰 목적은 바로 코드 실행의 흐름 제어 이다.
조건문 | 반복문 |
---|---|
if , switch | for , while , do-while |
if문은 조건식의 결과가 true 인지 false인지 에 따라 블록 실행 여부가 결정된다.
if(score < 90) {
System.out.println("점수가 90보다 작습니다.");
System.out.println("등급은 B 입니다.");
}
System.out.println("이 줄은 if문과는 상관없는 실행문 입니다.");
score라는 변수가 90보다 작아서 true가 된다면 if문 블럭 안의 2줄을 실행한 후 아래의 마지막 문장을 출력한다. 또한, if문은 한줄만 쓰게 될 시 중괄호 { ~ }
를 생략 할 수 있다.
if(score < 90) System.out.println("점수가 90보다 작습니다.");
System.out.println("등급은 B 입니다.");
System.out.println("이 줄은 if문과는 상관없는 실행문 입니다.");
그래서 이렇게 쓰게 될 시 "등급은 B 입니다." 또한 if문과는 상관없는 실행문이 된다.
또한 if문에서는 else
라는 키워드를 사용할 수 있다. if문은 else 블럭과 함께 사용되어 조건식의 결과에 따라 실행 블록을 선택할 수 있다.
if(score >= 90) {
System.out.println("점수가 90보다 큽니다.");
System.out.println("등급은 A 입니다.");
} else { // <--score <90 일 경우
System.out.println("점수가 90보다 작습니다.");
System.out.println("등급은 B 입니다.");
}
if-else문의 특징은 첫번째 if문의 조건식의 부정 형태가 else의 조건식이 된다는 것이다.
즉, 오직 한 조건식의 true / false의 여부에 따라서만 코드를 짤 수 있기 때문에 else 뒤에 if를 한번 더 써서 흐름 제어를 하는 것이 가능하다.
if(score >= 90) {
System.out.println("점수가 100~90 입니다.");
System.out.println("등급은 A 입니다.");
} else if(score >=80 ) {
System.out.println("점수가 80 ~ 89 입니다.");
System.out.println("등급은 B 입니다.");
} else{
System.out.println("점수가 80점 미만입니다.");
}
그리고 if문 안에 한번 더 if문을 중첩할 수도 있다. 이때는 더욱 복잡한 실행흐름이 된다.
if-else가 계속 될 수록 복잡해지고 분석이 어려지기 때문에 가독성을 높이기 위해 switch문을 사용한다.
switch문은 if문과 다르게 기준이 되는 변수의 값에 따라서 어떤 코드를 실행 할 지 정할 수 있기 때문에 더욱 코드가 간결해 진다.
switch(변수){
case 값1:
...
break;
case 값2:
...
break;
default:
...
}
근데 경험상 switch문은 if-else가 3번 이상 중첩되지 않는 이상 잘 쓰지 않는다.
왜냐하면 저기 break가 없으면 그 아래의 case를 break 만날 때 까지 모두 실행하기 때문이다.
반복문에서 break를 사용하는 경우가 많은데, switch문을 쓰기 위해 boolean flag = true
를 만들어서 컨트롤 하는 건 if-else를 쓰는 것 보다 복잡하다.
그러나 java12 부터 이런 고충을 해결하기 위해 Expressions를 지원하게 되었다.
switch (grade){
case 'A','a'->{
System.out.println("우수회원 입니다.");
}
case 'B','b'->{
System.out.println("일반 회원입니다.");
}
default -> {
System.out.println("손님입니다.");
}
}
그리고 java13 부터 switch문의 결과를 변수에 대입하는 기능인 yield
라는 키워드가 추가되었다.
//Java 12 문법
int score2 = switch (grade){
case "A"-> 100;
case "B"-> {
int result = 100 - 20;
//Java 13 문법
yield result;
}
default -> 60;
};
System.out.println("score2: "+score2);
단순히 대입을 할 때는 중괄호를 생략하고 100을 대입하면 되지만
특정 코드를 실행해야 한다면 중괄호로 연산을 해 주고 마지막 결과를 yieled result;
해서 대입할 수 있다. 주의할 점은 반드시 default
키워드를 사용해 줘야 한다.
반복문은 특정 실행문을 여러번 반복하고 싶을 때 사용하는 문법이다.
for(1.초기화식; 2.조건식; 3.증감식) {
...
}
여기서 조건식이 true일 때만 해당 for문안을 계속 반복한다.
for(int i = 1; i<=10; i++){
System.out.print(i+" ");
}
변수 i가 10이 되는 순간 10 <= 10 이므로 구문으로 들어와 System.out.print("10 ");
을 출력하고 i는 11이 된다. 그리고 다시 검사했을 땐 11 <= 10 이 false 이므로 반복문이 종료되고 1부터 10까지 출력되는 것이다.
그리고 초기화식에서 만약 정수 대신 실수를 사용할 경우 부동소수점을 쓰는 float를 사용 하면 편차에 의해 정상적으로 작동 안할 수도 있다.
for(float x= 0.1f; x<=1.0f; x+=0.1f){
System.out.println(x);
}
for문은 반복할 횟수를 미리 정해놓고 짠다면 while문은 조건식이 flase가 될 때 까지 무한히 반복한다는 특징이 있다. 엄밀히 말하자면 for문과 while문도 동일하게 조건이 false가 될 때 까지 반복하는 거지만, for문은 변수를 카운팅 함으로서 조건을 false로 만들고 while은 그 외적인 조건을 컨트롤한다. 주로 크기가 얼마나 될지 모르는 외부 파일을 버퍼 스트림으로 읽을 때, 특정 키를 눌러야만 게임이 종료되는 경우, 반복 횟수를 예측할 수 없을 때 사용한다.
int i = 1;
while (i <=10){
System.out.println(i+" ");
i++;
}
앞서 배운 for문을 그대로 while로 옮긴 것이다.
보통 while문의 경우 while(조건식) 안에 실제 조건식을 넣기 보다는 boolean 변수를 flag로 쓰거나 while(true)
로 시작해서 if(조건) break;
를 쓴다.
boolean run = true;
int speed = 0;
while (run){
System.out.println("------------------");
System.out.println("1. 증속 | 2. 감속 | 3. 중지");
System.out.println("------------------");
System.out.print("선택>");
String strNum = sc.nextLine();
if(strNum.equals("1")){
speed++;
System.out.println("현재 속도 : "+speed);
}else if(strNum.equals("2")){
speed--;
System.out.println("현재 속도 : "+speed);
}else if(strNum.equals("3")){
run = false;
}
}System.out.println("프로그램 종료");
그 다음으로 알아볼 것은 do-while 문이다.
do-while문은 while문과 거의 똑같지만 최초실행 1회를 보장한다는 특징이 있다.
do{
...
} while(조건문)
여기서 코드 흐름이 반드시 do를 먼저 거치기 때문에 시작부터 조건문이 false라서 아에 while문 자체를 돌지 않는 현상은 일어나지 않는다. while(조건문)
이 시작부터 false라도 do의 블럭을 한번 거치고 멈춘다. 해당 구문은 예외를 줄이고 더욱 안전하게 코딩하기 위해 있는 기능이다.
break; 는 말 그대로 for, while, do-while 구문을 중지할 때 사용한다.
그런데 앞서 말했듯 for문과 switch등이 중첩될 때 break를 만나면 가장 가까운 구문만 빠져나온다는 문제가 있다. 그래서 label을 통해 break를 조절해 줄 수 있다.
Outter: for(char upper = 'A'; upper<='Z'; upper++){
for(char lower = 'a'; lower<='z'; lower++){
System.out.println(upper+"-"+lower);
if(lower=='g'){
break Outter;
}
}
}
이렇게 반복문이 시작하기 전에 라벨명:for ...
으로 라벨을 선언 할 수 있고 break 뒤에 라벨명을 써주면 해당 라벨 이하의 반복문을 종료시킨다.
continue; 는 반복문 안에서 사용 할 수 있으며, continue; 아래의 구문을 무시한 체 다시 처음 반복으로 돌아간다. 말로 쓰면 이해가 잘 되지 않으니 예제로 보겠다.
for(int i = 1; i <=10; i++){
if(i%2 != 0){
continue;
}
System.out.println(i+" ");
}
여기서 if문을 만족할 때, 즉 i가 홀수 일 때 if문 블럭으로 들어온다.
그 때 continue를 만나게 되고 아래의 System.out.println(i+" ");를 출력하지 않은 체 다시 for문의 최상단으로 올라간다. 그래서 출력결과는 다음과 같다.
2
4
6
8
10
2번, int, double 뿐만 아니라 String, char도 가능하다.
이건 자바 13 부터 쓰는 yield와 자바 12부터 쓰는 키워드 (->
)를 활용하면 된다.
String grade = "B";
int score1 = switch(grade){
case "A" -> 100;
case "B" ->{
int result = 100 - 20;
yield result;
}
default -> 60;
}
int result = 0;
for(int i = 1; i<=100; i++){
if(i % 3 == 0) result += i;
}
System.out.println(result);
i % 3 == 0
이 i가 3의 배수면 참이 되므로 원하는 결과를 얻을 수 있다.
while(true)
{
int a = (int)(Math.random()*6) + 1;
int b = (int)(Math.random()*6) + 1;
System.out.println("("+a+","+b+")");
if((a + b) == 5) break;
}
랜덤 1~6을 2개 a,b에 각각 할당해 주고 if문에 합이 5인지를 구분하는 코드를 넣어주면 된다.
for(int x = 1; x<=10; x++){
for(int y = 1; y <=10; y++){
if((4*x + 5 * y) == 60) System.out.println("("+x+","+y+")");
}
}
5번과 비슷한 문제다.
for(int i = 1; i <= 5; i++){
while(true){
int ran = (int)(Math.random()*Integer.MAX_VALUE)+1;
if(ran == i){
for(int j = 0; j<ran; j++) System.out.print("*");
break;
}
}
System.out.println();
}
ㅋㅋㅋ 이론상 운만 좋으면 바로 출력될 수도 있다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int myAccount = 0;
while (true){
System.out.println();
System.out.println("------------------------------------");
System.out.println("1. 예금 | 2. 출금 | 3. 잔고 | 4. 종료");
System.out.println("------------------------------------");
System.out.print("선택> ");
String userSelect = sc.nextLine();
if(userSelect.equals("1")){
System.out.print("예금액>");
myAccount += (Integer.parseInt(sc.nextLine()));
}else if(userSelect.equals("2")){
System.out.print("출금액>");
myAccount -= (Integer.parseInt(sc.nextLine()));
}else if(userSelect.equals("3")){
System.out.print("잔고>");
System.out.println(myAccount);
}else if(userSelect.equals("4")){
System.out.println("프로그램 종료");
break;
}
}
}
}