💙 들어가며
앞으로 수없이 많이 만나게 될 반복문 while과 for
잘 알아보고 정확한 용도대로 사용해보자.
✏️ 학습내용 정리
#while과 for은 각각 언제 사용하는 것일까?
while과 for함수는 둘 다 반복을 한다는 개념에서 굉장히 비슷한 메소드들이다.
그러나 둘은 확실히 나눠서 생각할 필요가 있는 메소드이다.
결론부터 말하자면, 몇 회를 반복하는 지가 뚜렷하다면 while이 아니라 for을 써야한다.
#while과 for의 각각 특징
그렇다면 왜 반복횟수가 정해져있다면 for을 써야하는 것일까?
두 메소드의 특징을 살펴보면 특정 횟수를 반복할 때 for의 장점이 두드러진다.
- while: 반복하는 개수에 제한이 없고 어떤 특정한 조건이 만족하는 경우에 반복
- for: 특정 수만큼 반복
while문과는 다르게 for문 안에 인덱스(index, i)를 가지고 있다는 게 큰 차이점이다.
(인덱스를 사용한다는 것이 for문의 가장 중요한 점)
위의 설명에서처럼 for문은 선언 시에 인덱스값을 꼭 같이 선언해줘야 하는데,
이 인덱스를 통해서 우리가 몇 번 반복이 되는지를 직관적으로 확인해볼 수 있다는 강점이 있다.
따라서, 현재 반복되는 위치와 횟수를 알고 싶다고 하면 무조건 for문을 사용해야 한다.
그렇다면 for문을 제대로 사용하기 위해서는
인덱스를 올바르게 사용하는 방법을 제대로 알고 있어야 하겠다.
(선생님께서 실제로도 많은 사람들이 잘못 알고 쓰고 있다고 말씀하셨다.)
#★오늘의 핵심★인덱스(index)란?
우리가 for문을 쓰는 이유는 index를 사용할 수 있기 때문이라고 앞서 설명했다.
그렇다면 구체적으로 인덱스란 무엇일까?
인덱스란 0부터 시작하는 일련번호이다.
이점이 정말 기본이면서도 굉장히 중요한 것인데
인덱스의 이런 성질 때문에 반드시 시작하는 값을 0으로 설정해야 한다.
따라서, for문안에 들어가는 인덱스는 int i=0으로 시작한다. 다른 숫자로 셋팅하면 안 된다!!!
(선생님께서는 만약 반복할 때 0이 아닌 다른 숫자로 시작하는 내용으로 설정할 시에는
index를 뜻하는 i가 아닌 다른 문자를 쓰라고 까지 하셨다.)
이렇게 인덱스를 0으로 시작하게 되면 반복될 횟수를 직관적으로 표시할 수 있다.
for(int i=0; i<인덱스가 반복될 횟수;i++)
for(int i=0; i<인덱스가 반복될 횟수;i++)
i가 몇 회 반복될 지를 명시적으로 적어주어서
for문만 보아도 몇 번 반복인 지를 바로 알 수 있어야 한다.
그리고 for문에 들어가는 i는 for문 안에서만 사용되는 변수이기 때문에
계속 재사용될 수 있으니 i, j, k, l, m 등으로 바꿀 필요 없다.! (는 내 이야기)
밑에 여러번 for문이 나와도 인덱스는 다 i로 쓰면 됨!
인덱스에 대한 명확한 개념을 바로 잡고 for문을 배우기 시작해서 다행이다.
잘못된 인덱스 형식으로 인덱스가 있는데 인덱스가 없는 상황이 되지 말자.
#for문 연습문제
위에서 인덱스의 중요성에 대해서 제대로 알아 보았으니
앞으로 우리는 절대로 index를 수정하지 않는 것을 기본으로 for문을 작성하는 습관을 들여야 한다.
그럼 for문을 연습해보자.
#연습문제 풀기 전 알아두기
응용문제에서는 먼저 인덱스를 건드리지 않은 상태에서 인덱스를 출력해보고
그 값을 기준으로 어떻게 바꿔야 할 지를 생각해보면 된다.
만약 1부터 10까지를 출력하고 싶다면?
1. 인덱스를 몇 회 반복할 것인지를 표현하고 인덱스를 출력
출력하면 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10까지가 나온다.
2. 0부터 9까지 출력되었으니 인덱스 값에 +1을 하여 1~10이 출력되게 만든다.
다음과 같이 인덱스를 먼저 기본으로 출력해서 출력값을 수정해가는 방식으로 활용하자!
그러면 몇 번 반복인지도 명시적으로 보이고, 수정하는 것도 훨씬 쉬워짐‼️
Q. (LV.0) 1을 10번 출력하라
절대 index를 수정하지 말아라!!
문제에서 말하는 것은 인덱스를 바꾸라고 하지 않았음, 1을 10번 출력하라고 했을 뿐
인덱스를 통해 우리는 총 10회가 반복된다는 것을 알았고, 1을 10회 출력하였다.
for(int i=0;i<10;i++)
System.out.printf("%d", 1);
Q. (LV.1) 1부터 10까지 출력
절대 index를 수정하지 말아라!!
문제에서 말하는 것은 인덱스를 바꾸라고 하지 않았음, 1부터 10까지 출력하라고 했을 뿐
인덱스를 통해 우리는 총 10회가 반복된다는 것을 알았고,
인덱스에 1을 더해줌으로써(i+1) 10회 반복하여 1에서 10까지 출력할 수 있다.
for (int i=0; i<10; i++)
System.out.printf("%d", i+1);
Q. (LV.1) 10부터 1까지 출력
절대 index를 수정하지 말아라!!
문제에서 말하는 것은 인덱스를 바꾸라고 하지 않았음, 10부터 1까지 출력하라고 했을 뿐
인덱스를 통해 우리는 총 10회가 반복된다는 것을 알았고,
인덱스를 10에서 빼는 방법을 통해서 10부터 1의 순서대로 출력할 수 있다.
❌ 잘못된 코드작성 방법:
인덱스를 건드려서 몇 번 반복되었는지 모르겠음 (인덱스가 없음)
for(int i=10;i>0;i--) {
System.out.printf("%d", i);
⭕올바른 코드작성 방법:
인덱스를 통해 반복 횟수 등 인덱스 의미를 알 수 있음 (인덱스 있음)
for(int i=0;i<10;i++) {
System.out.printf("%d", 10-i);
Q. (LV.2) 3부터 7까지 5개의 숫자를 출력
절대 index를 수정하지 말아라!!
문제에서 말하는 것은 인덱스를 바꾸라고 하지 않았음, 3부터 7까지 5개 숫자만 출력하라고 했을 뿐
인덱스를 통해서 우리는 5회를 출력한다는 것을 알고,
3부터 출력될 수 있도록 인덱스에 3을 더해 5회를 반복 출력했다.
for(int i=0;i<5;i++) {
System.out.printf("%d", i+3);
}
Q. (LV.2) 1, 3, 5, 7, 9의 5개 숫자를 출력
절대 index를 수정하지 말아라!!
문제에서 말하는 것은 인덱스를 바꾸라고 하지 않았음, 1, 3, 5, 7, 9까지 5개 값을 출력하라고 했을 뿐
그리고 for문 안에서만 사용하는 변수라면
for을 선언할 때 소괄호() 안에 인덱스와 같이 변수를 선언해줄 수도 있다.
선생님 풀이에서처럼 for(int i= 0, n=1; i<5; i++, n+2)와 같이 인덱스와 별개로 n을 선언할 수 있다.
내가 풀이한 방법대로 하면, i를 어떻게든 끌고 가려고 하려다 보니 식이 복잡해질 수 있다.
생각해보면 인덱스를 건드리지 말라고 했을 뿐, 일반 변수를 얼마든지 사용할 수도 있다.
선생님이 활용하신 방법처럼 변수 하나를 더 들여서 코드를 깔끔하게 만들 수 있다면
인덱스를 가지고 고군분투 할 필요 없다.
⭕ 내가 풀이한 방법:
for (int i=0;i<5;i++) {
System.out.printf("%d", i+(i+1));
}
🚨 조금 헷갈렸던 것:
이렇게 해도 i가 2씩 증가되나 이렇게 되면 횟수가 10번이 되어야 함
우리는 인덱스를 건드리지 말아야 하므로 출력이 정상적으로 되더라도 잘못된 답으로 생각해야 한다.
for (int i=0;i<5;i++) {
System.out.printf("%d", ++i);
}
⭕👍🏻 선생님 풀이 방법:
for문 안에 아예 변수를 설정하고 들어가서
인덱스로 어렵게 생각할 필요 없이 코드가 훨씬 깔끔하고 쉬워졌다.
for(int i=0, n=1; i<5; i++, n+=2)
System.out.printf("%d", n);
System.out.println();
#인덱스(idex)와 넘버(number)의 차이점
위의 풀이처럼 우리가 반복문을 사용하다보면 인덱스가 아니라 넘버가 필요해질 때가 있다.
그럴때는 for문 안에 같이 선언해줄 수 있다.
두 개는 어떤 차이가 있을까?
- index: 0 ~ (N-1)의 값
- num: 1~(N)의 값
때문에 1부터 시작되는 값을 표현하고 싶을 때는 i+1보다는 변수 n(넘버)을 들여와서 활용하면 쉬워진다.
아래와 같이 for문 안에 넘버를 같이 선언해 줄 수 있다.
별개로 for문 밖에 인덱스를 써줄수도 있지만 그렇게 되면 변수 i가 되고 더 이상 인덱스라고 볼 수 없다.
그리고 맨 마지막에 for(;;)는 무한반복을 하게 하는데 오류는 안나지만 이렇게 쓰지 않고 while2를 쓴다고 한다.
즉, 인덱스에 한해서는 for문 밖으로 뺄 필요 없이 정석대로 사용하면 되겠다.
다시 돌아가서 업그레이드 문제를 풀어보자.
Q. (LV.3) 6, 10, 14, 18, 22, 26, 30, 34, 38, 42의 10개 숫자를 출력
절대 index를 수정하지 말아라!!
문제에서 말하는 것은 인덱스를 바꾸라고 하지 않았음
6, 10, 14, 18, 22, 26, 30, 34, 38, 42까지 10개 값을 출력하라고 했을 뿐
이제 더 이상 인덱스 1개만을 가지고 빈곤하고.. 어렵게.. 풀 필요가 없다.
우리는 변수를 도입하여 조금 더 쉽게 식을 풀이할 수 있게 되었다.
나와 팀원들은 넘버의 의미를 담은 변수 n을 선언하여 n을 출력하는 식으로 풀이를 했다.
그렇게 풀이를 하였더니 식이 훨씬 깔끔해지게 되었다.
⭕ 처음 풀이했던 방법:
n을 6으로 시작했다.
for(int i=0, n=6;i<10;i++, n+=4) {
System.out.printf("%d ", n);
}
⭕ 팀원들과 같이 풀이한 방법:
n을 1로 시작했다.
이 방법이 작성하기에 훨씬 직관적이고 좋은 것 같다.
for(int i=0, n=1;i<10;i++, n+=4) {
System.out.printf("%d ", n+5);
}
그러나, 지금 나와 팀원들이 푼 방식은
꼭 4씩 늘어나는 등차수열만 구할 수 있는 방법이라서 활용도가 매우 낮다..!
그래서 선생님은 활용도를 더 늘리는 방법을 알려주셨는데,
for문 안에 변수를 하나 더 추가하고 그 변수에는 수식을 추가하셨다.
⭕👍🏻 선생님 풀이 방법:
그런데 사실 위 풀이대로 직관적으로 풀면 등차수열만 표현할 수 있고,
등비나 계차수열은 표현할 수 없게되어, 활용도가 낮아진다.
그래서 선생님은 for문 안에 an이라는 변수와 수식까지 선언하셨다.
※ 참고
등차수열의 일반항: an = a1+(n-1)*차이값 여기서 n은 횟수,
차이값은 첫 번째 두 번째 값 끼리의 차
for(int i=0, n=1, an=6; i<10; i++, n++, an=6+(n-1)*4)
▶ 등차수열이구나를 알 수 있음
for(int i=0, n=1, an=6; i<10; i++, n++, an=4*n+2)
▶ 구조를 풀어버려서 의미가 불명확해짐, 가급적 구조는 풀지 말고 그대로 두기
System.out.printf("&d", an);
우리는 이런 식으로 for문에 들어간 조건만 하나 수정하면 언제든지
변수만 수정해도 하위 코드를 다 수정할 필요 없이 원하는 값을 출력해 낼 수 있게 되었다.
for문의 무궁무진한 활용👍🏻
#(주의)변수를 선언할 때
선생님께서는 변수를 선언할 때 어디에 선언할 지를 중요하게 생각하셨다.
우리가 변수를 여러번 남발해서 사용하게 되면
전체 코드에 변수명을 사용하는데 한계가 생기고 어떤 영향을 줄 지 알 수 없기 때문에,
하나의 코드블럭 안에서만 사용하는 경우라면 묶어서 지역화하라고 알려주셨다!
(변수를 선언하려고 할 때마다 이미 사용중인 변수라고 하면 코딩 할때 고려해야 할 게 얼마나 많아질까?)
그래서 for문의 경우는 가급적이면 for( 여기 ; ; )문 안에 설정하라고 하셨다.
단, 이 경우에는 같은 자료형 (int면 int들만, String이면 String들만)만 선언할 수 있기 때문에
자료형이 다른 경우에는 어쩔 수없이 for문 밖에 선언해야 하는 경우가 있을 수 있겠다.
그러면 이렇게 이런 저런 이유로 반복문 밖에 선언해야 하는 변수라면 어떻게 지역화 할 수 있을까?
답은 중괄호{}이다.
중괄호 안에 코드를 넣어주면 그 괄호 안의 메소드에만 유효한 변수(지역화)가 된다.
중괄호는 최대한 적게 사용하여 코드를 깔끔하게 유지하되, 지역화가 필요한 경우에는 잘 활용하도록 하자.
🚨 전체 코드에 영향을 줄 수 있는 경우 (주의해서 사용)
아래와 같이 변수를 선언하게 될 경우에는
for, while 외에 다른 코드에도 영향을 끼칠 수 있는 변수가 된다.
그리고 이 밑으로는 sum이라는 변수명을 사용할 수가 없다.
(EX1)
int sum = 0;
for(int i=0;i<10;i++)
sum += i;
System.out.println(sum);
(EX2)
int sum = 0;
while(i<10){
sum += i;
System.out.println(sum);
i++;
}
⭕👍🏻 지역화한 좋은 예
그렇다면 중괄호를 사용하여 위의 코드들을 아래와 같이 고쳐보자!
(EX1)
for문 안에 넣기
for(int i=0,sum=0;i<10;i++)
sum += i;
System.out.println(sum);
(EX2)
바깥에 중괄호 넣기
{
int sum = 0;
while(i<10){
sum += i;
System.out.println(sum);
i++;
}
}
중괄호를 잘 활용하자.
💙 마치며
1.
오늘도 선생님이 말씀하신 것, 구조를 우선 고려해라‼️
(속도나 메모리는 여러가지 전제조건이 있을 때 그 때 가서 생각하는 것이다.)
for문을 보았을 때, 같이 사용하는 사람들이 바로 이 반복문의 횟수와 활용도를 파악할 수 있도록
작성할 때부터 구조를 생각하면서 코드를 짜보자.
(EX) an =a1+(n-1)d를 풀어서 쓰지 말고 그대로 두어서 사람들(나, 같이 일하는 사람들)이
의미를 쉽게 파악할 수 있도록 하자
2.
인덱스가 있으나 인덱스가 없는 상황이 되어버리지 말자.
'JAVA' 카테고리의 다른 글
[뉴렉처 6기] JAVA│이중 반복문(for~for)의 핵심과 인덱스의 활용 방법(230616) (1) | 2023.06.18 |
---|---|
[뉴렉처 6기] JAVA│건너뛰기(continue)와 중단하기(break) (230615) (0) | 2023.06.17 |
[뉴렉처 6기] JAVA│제어 구조에 대해 배워보자1 (while, if, for) (3) | 2023.06.14 |
[뉴렉처 6기] JAVA|형 변환(명시적, 묵시적)|연산자(산술, 비교, 논리, 단항, 비트)|Big Endian vs Little Endian (230612) (4) | 2023.06.13 |
[뉴렉처 6기] JAVA|자바 프로그래밍과 번역기(컴파일러)|자바 설치(JDK/JRE/JVM)|환경 변수 세팅하기 (0) | 2023.06.12 |