프로그램의 흐름을 제어함에 있어서 중요한 것 중에 하나는
사람이 일일히 명령하지 않아도 반복하며 계산을 진행하는 것입니다.
이를 가능하게 해주는 반복문에 대해서 알아보도록 합시다.
while문
가장 자주 사용되는 반복문은 for문일 수 있으나,
가장 간단한 형태의 반복문은 while문입니다.
while문은 아래와 같습니다
while(조건 A){
내용 B
}
조건이 True, 참인 동안 계속 반복합니다.
이를 순서대로 풀어보자면A 확인(참) -> B 실행 -> A 확인(참) -> 실행 -> A 확인(거짓) -> 끝
처럼 작동합니다.
다시 말해, 처음 시작할 때부터 조건 A가 거짓이라면A 확인(거짓) -> 끝
으로 내용 B가 실행되지 않습니다.
그리고 조건이 거짓이 되지 않는다면, 무한히 반복하게 되는데
이를 의도적으로 이용할 수도 있으나, 보통은 프로그램을 무한히 반복하면
메모리 초과 등을 이유로 프로그램이 정지합니다.
문제를 통해 while문의 사용을 보겠습니다.
#include <iostream>
using namespace std;
int main(){
int N;
cin >> N;
int i=1;
while(i<=N){
cout << i << "\n";
i++;
}
return 0;
}
i가 1부터 시작해서 N이 될 때 까지는 정상적으로 출력문을 실행 시키고,
i가 이후 N+1이 되면 i<=N
이 거짓이 되어, 블럭 안의 출력문이 실행되지 않고 프로그램이 끝납니다.
for문
while문보다 보다 높은 빈도로 사용되는 반복문입니다.
보다 다양한 기능을 할 수 있습니다.
for(시작 A; 조건 B; 실행 C){
내용 D
}
앞선 백준 2741번 예제의 소스코드에서
i++;
구문이 while문 안에 있었는데,
이런 반복문의 조건을 결정하기 위한 구문들을
따로 모아서 관리할 수 있게 해줍니다.
시작 A
는 최초 실행시에 단 한번 실행되는 구문이고,조건 B
는 while문과 똑같이 실행을 결정하는 논리구문입니다.실행 C
는 {}
블럭이 끝난 뒤에 매번 실행되는 구문이고,내용 D
는 반복하게 될 블럭 안의 구문들입니다.
실행 순서를 순서대로 적어보자면A -> B(참) -> D,C -> B(참) -> D,C -> B(거짓) -> 끝
과 같이 작동하게 됩니다.
따라서, for문을 똑같은 역할을 하는 while문으로 옮겨적을 수 있으며,
옮겨적으면 아래와 같습니다.
시작 A;
while(조건 B){
내용 D
실행 C
}
정 반대로, 다음과 같이 작성한 for문은 while문과 동일합니다.
for(;조건 A;){
내용 B
}
아까 보았던
문제를 for문을 이용해 해결하면
아래와 같습니다.
#include <iostream>
using namespace std;
int main(){
int N;
cin >> N;
for(int i=1; i<=N; i++){
cout << i << "\n";
}
return 0;
}
반복문을 구성하기 위해 필요한 구문이 한 곳에 모여있어서, 앞선 while문으로 작성하는 것보다 한눈에 보기에 더 편하게 작성할 수 있습니다.
가독성이 좋은 프로그램을 작성하기 위하여, 앞으로는 for문을 더 적극적으로 사용하게 될 것입니다.
break와 continue
반복 도중에 흐름을 바꿔주는 구문으로써, break와 continue 라는 구문이 존재합니다.
이들은 블록의 끝까지 가지 않고도 블록을 탈출할 수 있게 해주는 구문으로,
주로 무한반복을 막거나 탈출 조건이 너무 복잡해지는것을 막기 위해 사용합니다.
예를 들어서,1, 2, 3, 4, 5 ... N
다음과 같은 출력을 요구하는 프로그램이 있다고 해보겠습니다.
제일 마지막 N을 출력할 때에만 ,
이 출력되어서는 안됩니다.
#include <iostream>
using namespace std;
int main(){
int N;
cin >> N;
for(int i=1; i<=N; i++){
cout << i;
if(i != N){
cout << ", ";
}
}
}
다음과 같은 if문을 작성해서 방금 출력한 수가 N이 아닐 때에만 ,
를 출력하게 할 수 있지만, 이를 break를 사용하면 아래와 같습니다.
#include <iostream>
using namespace std;
int main(){
int N;
cin >> N;
for(int i=1; i<=N; i++){
cout << i;
if(i == N){
break;
}
cout << ", ";
}
return 0;
}
break 구문이 실행되면, 두 개의 블록을 동시에 나가고 그 아래로 이동합니다. 이 예시에서는 if문과 for문 두개의 블록을 동시에 나갔으며, 그렇기에 그 바로 다음에 실행되는 구문이 return 0;
이 되어 프로그램이 종료됩니다.
또 다른 예시로써 continue문을 사용, N 이하의 짝수만을 출력하는 프로그램을 작성해보면 아래와 같습니다.
#include <iostream>
using namespace std;
int main(){
int N;
cin >> N;
for(int i=1; i<=N; i++){
if(i%2 == 1){
continue;
}
cout << i << "\n";
// continue문이 실행된 이후 여기로 이동합니다.
}
return 0;
}
continue문은 한개의 블록을 탈출하고, 다른 하나의 블록의 가장 끝으로 이동해서 다음 반복을 시작시킵니다.
주석을 통해 표기한 부분으로 이동하여서, for문의 실행 순서에 따라i++
가 실행되고 그 이후 반복을 계속 하기 때문에 continue라는 이름을 받았습니다.
결론
반복문 까지 익히신 지금 시점부터 본격적인 알고리즘 문제해결이 시작됩니다. 작성자가 생각한 논리에 따라 다양하게 반복하며 원하는 값들을 계산해 낼 수 있기 때문입니다.
본격적으로 풀어볼 수 있는 문제의 난이도가 상승하며,문제 > 새싹 > 반복
부분을 해결하실 수 있게 됩니다.
언어를 다루기 시작하면 가장 흔하게 다루는 예제들 중 하나인별 찍기
를 시도해 보실수 있습니다.
별 찍기 문제들의 모음집인 위 링크의 낮은 난이도 문제를 해결해보시면서
반복문에 대한 이해를 다지는데에 활용해주세요.