7 min read

cpp[4] - 반복문(while/for)

프로그램의 흐름을 제어함에 있어서 중요한 것 중에 하나는
사람이 일일히 명령하지 않아도 반복하며 계산을 진행하는 것입니다.
이를 가능하게 해주는 반복문에 대해서 알아보도록 합시다.

while문

가장 자주 사용되는 반복문은 for문일 수 있으나,
가장 간단한 형태의 반복문은 while문입니다.

while문은 아래와 같습니다

while(조건 A){
	내용 B
}

조건이 True, 참인 동안 계속 반복합니다.
이를 순서대로 풀어보자면
A 확인(참) -> B 실행 -> A 확인(참) -> 실행 -> A 확인(거짓) -> 끝
처럼 작동합니다.

다시 말해, 처음 시작할 때부터 조건 A가 거짓이라면
A 확인(거짓) -> 끝
으로 내용 B가 실행되지 않습니다.

그리고 조건이 거짓이 되지 않는다면, 무한히 반복하게 되는데
이를 의도적으로 이용할 수도 있으나, 보통은 프로그램을 무한히 반복하면
메모리 초과 등을 이유로 프로그램이 정지합니다.

2741번: N 찍기

문제를 통해 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
}

아까 보았던

2741번: N 찍기

문제를 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라는 이름을 받았습니다.

결론

반복문 까지 익히신 지금 시점부터 본격적인 알고리즘 문제해결이 시작됩니다. 작성자가 생각한 논리에 따라 다양하게 반복하며 원하는 값들을 계산해 낼 수 있기 때문입니다.

본격적으로 풀어볼 수 있는 문제의 난이도가 상승하며,
문제 > 새싹 > 반복 부분을 해결하실 수 있게 됩니다.

언어를 다루기 시작하면 가장 흔하게 다루는 예제들 중 하나인
별 찍기 를 시도해 보실수 있습니다.

문제집: 별 찍기 (시리즈)

별 찍기 문제들의 모음집인 위 링크의 낮은 난이도 문제를 해결해보시면서
반복문에 대한 이해를 다지는데에 활용해주세요.