본 글은 [자바의 정석 3판 - 남궁성] 에 있는 조건문, 반복문 파트와 자바의 정석 유튜브(남궁성의 정석코딩 - YouTube)를 보고 요약한 글입니다.
조건문, 반복문
조건문과 반복문은 제어문(flow control statement)이다.
조건문: 조건을 만족할 때만 { }를 수행(0~1번)
반복문: 조건을 만족하는 동안 { }를 수행(0~n번)
if문
조건식이 참(true)일 때, 괄호 { }안의 문장들을 수행한다.
if (조건식) {
// 조건식이 참(true)일 때 수행될 문장들을 적는다
}
블럭 { }
여러 문장을 하나로 묶어주는 것
if(score > 60)
{
System.out.println("aa");
}
위와 같이 조건문이 참일때 나오는 결과가 한 줄일 경우
아래와 같이 { }를 생략할 수 있다.
if(score > 60)
System.out.println("aa");
그러나 한 줄까지만 적용되고 두 줄이상부터는 적용되지 않는다.
if(score > 60)
System.out.println("aa"); // if문에 속한 문장
System.out.println("bb"); // if문에 속한 문장이 아님
if-else문
둘 중의 하나 - 조건식이 참일 때와 거짓일때로 나눠서 처리
if(조건식) {
// 조건식이 참(true)일 때 수행될 문장들을 적는다.
} else {
// 조건식이 거짓(false)일 때 수행될 문장들을 적는다.
}
if-else if문
여러 개 중의 하나 - 여러 개의 조건식을 포함한 조건식
if(조건식1){
조건식1의 연산결과가 참일 때 수행될 문장을 적는다.
}else if(조건식2){
조건식2의 연산결과가 참일 때 수행될 문장들을 적는다.
}else if(조건식3){
조건식3의 연산결과가 참일 때 수행될 문장들을 적는다.
}else {
마지막은 보통 else블럭으로 끝나며, else 블럭은 생략 가능하다.
위의 어느 조건식도 만족하지 않을 때 수행될 문장들을 적는다.
}
조건식 1이 거짓이면 조건식2를 수행하고 조건식2가 거짓이면 조건식3의 수행하고 조건식 3이 거짓이면 else { } 블럭 안의 내용을 실행한다.
만약 조건식1이 참이면 조건식 { } 블럭 안에 내용을 실행하고 if else문을 빠져 나온다.
중첩 if문
if(조건식1) {
조건식1이 true일때 수행될 문장들을 적어주면 된다.
if(조건식2){
조건식1이 true이고 조건식2가 true일때 수행될 문장
}else{
조건식1이 true이고 조건식2가 false일때 수행될 문장
}
} else {
조건식1이 false일때 수행될 문장
}
중첩 if 문에서 조심해야될 부분은 아래와 같이 { } 대괄호 구분없이 else를 지정할때
해당 else가 if(num >= 0)의 else인지, if(num != 0)의 else인지 구분이 명확하지 않다.
이때 else은 제일 가까이에 있는 if에 else로 적용된다.
if(num >= 0)
if(num != 0)
sign = '+';
else
sign = '-';
즉, 해당 else는 제일 가까이 있는 if(num !=0)에 해당되는 else이기에 아래와 같이 적용된다.
if(num >= 0){
if(num != 0){
sign = '+';
} else{
sign = '-';
}
}
위와 같이 내부의 if문은 외부의 if문 보다 안쪽으로 들여쓰기를 해서 두 if문의 범위가 명확히 구분될 수 있도록 작성해야한다.
중첩if문에서는 괄호 { }의 생략에 더욱 조심해야한다.
switch문
처리해야 하는 경우의 수가 많을 때 유용한 조건
switch의 조건식에는 정수, 상수, 문자, 문자열이 올 수 있다(단, if문은 true 또는 false 올 수 있음)
1. 조건식을 계산한다.
2. 조건식의 결과와 일치하는 case문으로 이동한다.
3. 이후의 문장들을 수행한다.
4. break문이나 switch문의 끝을 만나면 switch문 전체를 빠져나간다.
만약 조건식의 결과와 일치하는 case문이 하나도 없는 경우에는 default문으로 이동한다.
default문은 if문의 else블럭과 같은 역할을 한다고 보면 이해가 쉬울 것이다.
* default문의 위치는 어디라도 상관없으나 보통 마지막에 놓기 때문에 break문을 쓰지 않아도 된다.
switch(조건식){
case 값1:
조건식이 값1과 같은 경우 수행될 문장들
break;
case 값2:
조건식이 값2와 같은 경우 수행될 문장들
break;
default :
조건식의 결과와 일치하는 case문이 없을 때 수행될 문장들
}
* 만약 break이 없으면, 해당 case들 조건이 맞으면 문장을 실행하고 그 이후에 있는 다른 case의 문장이 실행된다.
그리고 다른 case의 break 또는 switch문의 끝을 만날 때까지 모두 수행한다.
그래서 case를 실행할 문장 맨 뒤에는 break를 붙여주어야 한다.
* 간혹 break와 일부러 뺀 로직을 만들기도 한다. 해당 로직는 아래와 같다.
switch (level) {
case 3:
grantDelete();
case 2:
grantWrite();
case 1:
grantRead();
}
여기서 level = 3 인 경우 : 레벨 3을 찾고 grantDelete(); 실행한다. 그러나 break가 없기 때문에 또 다른 break나 switch의 ' } ' 끝부분이 나올때 까지 실행한다. 그래서 level = 3이면 grandDelete(), grantWrite(), grantRead(); 3가지의 권한을 가진다.
반면 level = 2 인 경우 : 레벨 2이면 case 중에서 2를 찾고 해당 실행 문구를 실행한다. 그러나 break가 없기 때문에 또 다른 break나 switch의 ' } '끝부분이 나올때 까지 실행한다. 그래서 level = 2이면 grantWrite(), grantRead(); 2가지의 권한을 가진다.
switch문의 제약조건
switch문의 제약조건
1. switch문의 조건식 결과는 정수, 상수, 문자 또는 문자열(jdk 1.7 이후)이어야 한다.
2. case문의 값은 정수 상수(문자 포함) 변수 안됨, 문자열만 가능하며, 중복되지 않아야 한다.
* jdk 1.7 부터 문자열 허용됨. 원래 정수만 가능했음.
3. 문자 타입 가능함: char타입은 하나의 문자를 다루기 위한 것이지만,char 타입의 값은 사실 문자 아닌 정수(유니코드)로 저장되기 때문에 이처럼 char타입의 값도 switch문의 조건식과 case문에 사용할 수 있다.
int num, result;
final int TWO = 2;
switch(result) {
case '1': // OK
case 'A': // OK
case 3: // OK
case "asdf":// OK
case TWO // OK, 상수이기 때문에
case 1.0f // Error, 정수가 아니기 때문
case num // Error, 변수 불가
}
* case문은 한 줄에 하나씩 쓰던, 한 줄에 붙여서 쓰던 상관없다.
case 1:
case 2:
case 3:
System.out.println("1");
아래/위 코드 모두 가능함(switch 2가지의 표현방법)
case 1: case 2: case 3:
System.out.println("1");
switch문 중첩 가능
if 처럼 switch문도 중첩가능하나. break 빼먹기 쉽기 때문에 잘 작성해야한다.
switch (day) {
case "월요일":
case "화요일":
case "수요일":
case "목요일":
case "금요일":
switch (timeOfDay) {
case "오전":
System.out.println("일과 시간입니다. 회의와 업무 처리를 진행하세요.");
break;
case "오후":
System.out.println("일과 시간이 끝났습니다. 자유로운 시간을 즐기세요!");
break;
default:
System.out.println("유효하지 않은 시간을 입력했습니다.");
}
break;
case "토요일":
case "일요일":
switch (timeOfDay) {
case "오전":
case "오후":
System.out.println("주말입니다! 여유로운 시간을 즐기세요.");
break;
default:
System.out.println("유효하지 않은 시간을 입력했습니다.");
}
break;
default:
System.out.println("유효하지 않은 요일을 입력했습니다.");
}
임의의 정수 만들기
Math.random() - 0.0과 1.0 사이의 임의의 double 값을 반환
0.0 <= Math.random() < 1.0
* 2~6의 정수를 만드려면
1. 각 변의 5를 곱한다.
0.0 * 5 <= Math.random() * 5 < 1.0 * 5
0.0 <= Math.random() * 5 < 5.0
2. 각 변에 int로 형변환한다.
(int)0.0 <= (int)(Math.random() * 5) < (int)5.0
0 <= (int)(Math.random() * 5) < 5
3. 각 변의 2을 더한다.
0 + 2 <= (int)(Math.random() * 5) + 2 < 5 + 2
2 <= (int)(Math.random() * 5) +2 < 7
2 <= (int)(Math.random() * 5) + 2 < 7
Math.random() * 5 : 곱하기 5는 값의 범위이고
(int)(Math.random() * 5) + 2 : 더하기 2는 시작하는 값의 최소값이다.
for문
조건을 만족하는 동안 블럭{ }을 반복 - 반복횟수를 알 때 적합
조건식은 i++, i=i*2, i=i+2 등 다양하게 올 수도 있다.
for(int i = 1; i<=10; i = i*2){ // 1,2,4,8 총 4번 시행
System.out.println(i)
}
for(int i = 0; i<=10; i = i+2){ // 0,2,4,6,8,10 총 6번 시행
System.out.println(i)
}
for(int i = 10; i>=1; i = i-2){ // 10,8,6,4,2 총 5번 시행
System.out.println(i)
}
for(int i = 100; i>10; i=i/2){ // 100,50,25,12 총 4번 시행
System.out.println(i)
}
반복하려는 문장이 단 하나일때는 괄호{ } 를 생략할 수 있따.
for(int i = 1; i<=10; i = i*2)
System.out.println(i);
아래의 조건식이 1 = 1라면 항상 true이기 때문에 무한으로 돈다.
for(int i =0; 1 = 1; i++){
System.out.println(i)
}
초기화와 증감식 각각 2개씩 넣을 수도 있다.
아래에서 나타내는 int i 와 int j는 반복문 안에서만 사용할 수 있는 지역변수이다.
초기화 타입이 둘 다 같아야 한다.
for(int i = 1, j = 11; i <=10; i++,j--){
System.out.println("i="+i+",j="+j);
}
위와 같이 초기화 값과 증감식을 각각 2개씩 넣을 수 있다.
단, 초기화의 타입변수가 각각 같아야 한다.
for(;;)은 무한루프는 돈다.
초기화, 조건식, 증감식은 안 적어도 된다(필수는 아님)
for(;;){ // 무한루프
System.out.println("a");
}
for(;true;){ // 무한루프
System.out.println("a");
}
중첩 for문
for문 내에 또 다른 for문을 포함시킬 수 있다.
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= 9; j++) {
System.out.printf("%d * %d = %d%n", i, j, i * j);
}
}
바깥쪽 for문에게는 안쪽 for문 전체가 하나의 문장이므로 바깥쪽 for문은 { } 괄호 생략가능함.
for (int i = 1; i <= 9; i++)
for (int j = 1; j <= 9; j++) {
System.out.printf("%d * %d = %d%n", i, j, i * j);
}
향상된 for문
JDK 1.5부터 배열과 컬렉션에 저장된 요소에 접근할 때 기존보다 편리한 방법으로 처리할 수 있도록 for문의 새로운 문법을 추가되었다.
for( 타입 변수명: 배열 또는 컬렉션){
// 반복할 문장
}
while문
조건을 만족시키는 동안 블럭 { } 을 반복 - 반복횟수 모를 때
while(조건식) {
조건식의 연산결과가 참(true)인 동안, 반복될 문장들을 적는다.
}
for(int i = 5; i<=10;i++){
System.out.println(i);
}
위와 아래의 반복문을 같다. 이렇게 for문과 while은 변경 서로가 가능하다.
int i = 5;
while(i<=10){
System.out.println(i);
i++;
}
int i = 10;
while(i--> 4){
System.out.println(i);
}
위의 코드 처럼 조건식 안에 증감식을 넣을 수도 있다.
do-while문
블럭{ }을 최소한 한 번 이상 반복 - 사용자 입력받을 때 유용
do {
// 조건식의 연산결과가 참일때 수행될 문장들을 적는다.(처음 한 번은 무조건 실행)
} while (조건식); - 끝에 ' ; '을 잊지 않도록 주의
1. do { } 문장을 실행
2. 다음 while(조건식) 확인
반면 do-while이 아닌 while은
1. while(조건식)이 참(true)이여야만
2. { } 블럭 실행
while(조건식){
//실행할 문장
}
즉 do-while과 while은 1번과 2번이 서로 반대 순서로 시작된다.
break문
자신이 포함된 하나의 반복문을 벗어난다.
switch문에도 있지만 반복문에서도 break를 만나면 해당 반복문을 벗어난다.
아래의 코드는 while(true)이기 때문에 무한으로 반복문이 실행된다.
그러나 if(sum > 100)을 만나면 break; 실행되고 반복문을 벗어나게 된다.
for문은 무한 반복문을 실행시키기 위해서 for(;;)를 사용하면 되지만
while문은 꼭 while(true)를 true를 적어주어야 한다(true는 생략 불가)
int sum = 0;
int i = 0;
while(true) {
if(sum > 100){
break;
}
++i;
sum += i;
}
continue문
자신이 포함된 반복문의 끝으로 이동 - 다음 반복으로 넘어감
전체 반복 중에서 특정 조건시 반복을 건너뛸 때 유용
아래의 코드는 반복문을 돌때 i가 2의 배수이면 반복문의 끝으로 이동하여 다음 반복을 실행하는 코드이다.
break와 달리 반복문을 벗어나진 않는다.
for문의 경우: 증감식으로 이동
while 또는 do-while문의 경우: 조건식으로 이동
for(int i = 0 ;i < 10;i++){
if(i%2==0){
continue;
}
System.out.println(i); // 1,3,5,7,9
}
이름붙은 반복문
반복문에 이름을 붙여서 하나 이상의 반복문을 벗어날 수 있다.
continue Loop1도 가능하지만 거의 사용하는 경우가 없다.
Loop1: for (int i = 1; i <= 9; i++) { // for문에 Loop1이라는 이름을 붙였다.
for (int j = 1; j <= 9; j++) {
System.out.printf("%d * %d = %d%n", i, j, i * j);
if(j==5)
break Loop1; // 안쪽에 있는 for문이 아닌 Loop1인 바깥쪽에 있는 하나 이상의 반복문으로 부터 벗어남
break; // 제일 가까운 반복문만 벗어나서 바깥쪽 반복문에서 실행함
}
}
Loop1는 위에서 사용해도 된다. 아래는 해당 예시 코드이다.
Loop1:
for (int i = 1; i <= 9; i++) { // for문에 Loop1이라는 이름을 붙였다.
for (int j = 1; j <= 9; j++) {
System.out.printf("%d * %d = %d%n", i, j, i * j);
if(j==5)
break Loop1; // 안쪽에 있는 for문이 아닌 Loop1인 바깥쪽에 있는 하나 이상의 반복문으로 부터 벗어남
break; // 제일 가까운 반복문만 벗어나서 바깥쪽 반복문에서 실행함
}
}
'java' 카테고리의 다른 글
collection framework : LinkedList (0) | 2023.08.29 |
---|---|
[java] 배열 (0) | 2023.08.12 |
[정규표현식과 Pattern] (0) | 2023.03.14 |
[java] 연산자 (0) | 2023.03.11 |
[Java: 변수] (0) | 2023.03.08 |
댓글