많은 프로그래밍의 문제들이 동일한 데이터에 반복적인 작업을 함으로써 풀린다. 컴퓨터 프로그램은 단순한 계산의 반복이지만 이 단순작업도 한두번이 아니라 100번 1000번 반복하면 어려운 문제를 풀 수 있다.
프로그래밍에서 자주 등장하는 단어가 있는데 Iteration 이라는 단어다. 한글로는 반복하는 것, 되풀이 하는 것이라는 뜻이다. 되풀이하는 방법에도 여러가지가 있는데 C++은 Iteration 의 주요한 방법으로 loop 를 사용한다.
goto 문
초창기의 loop에는?
- goto 문이 있었다. 컴퓨터 소프트웨어 발전의 초창기에는 goto 문을 loop하는데 사용했다. 이름에서 추측할 수 있듯이 goto (~ 어느 지역으로 가라) 는 특정한 라벨을 붙인 곳으로 프로그램 카운터를 jump 해서 반복하는 형식이었다.
goto문으로도 충분히 반복문을 수행할 수 있었다. 그런데 결론적으로 goto문을 사용한 코드는 나날이 복잡해졌다. 현재의 for문이나 while문 처럼 엄격한 조건속에서 반복하는게 아니라 원하는 곳으로 jump 할 수 있는 기능이었기 때문이다.
C++ 프로그램이 main 함수의 첫줄에서 실행되면 한줄씩 실행하며 다음 줄로 이동한다. goto문은 label이 붙은 곳이라면 어디라도 점프할 수 있다. 즉 앞쪽으로 점프할 수도 있고 뒤쪽으로 점프할 수도 있다. 이렇게 점프를 하다보니 코드의 로직이 점점 꼬여서 읽을 수 없게된 코드를 spaghetti code 스파게티 코드라고 한다.
그래서 goto문은 일반적인 프로그래밍에서는 사용하지 않도록 되어있다. goto 문은 저레벨 프로그래밍언어인 어셈블리어와의 호환을 위해서인지 문법에서 없애진 않아서 기능은 남아있다.
쓸일은 없겠지만 어떤 것인지 한번 체크 정도 해보자. goto 문을 사용하려면 label을 만들고 : 콜론을 붙이면 된다.
int main()
{
cout << "Welcome!\n";
cout << "--------\n";
int count = 0;
label1:
cout << "GOTO EXAM count : " << count << endl;
count++;
if (count >= 3)
goto label2;
goto label1;
label2:
cout << endl;
return 0;
}
goto 문으로 loop 를 만들었다. 문법이 느슨한 것을 느낄 수 있다. 어떤 라인이건 바로 점프할 수 있기 때문에 코드가 길어지면 가독성이 크게 떨어진다. 어쨋든 쓰지 말라는 것은 다 이유가 있는 것이다. 특별히 써야할 일이 있을지 모르지만 일반 애플리케이션의 설계에는 사용할 수 없는 코드다. 만약 공동 프로젝트에 goto를 사용하면 X 욕을 받을 가능성이 높다.
(쓰는 사람이 없을거라 생각한다.)
반복문의 대표는 while과 for문이 있다. 사용하기에 따라 둘다 똑같이 사용할 수 있으나 굳이 두 종류의 반복문을 사용하는 것은 이유가 있다.
while 문은 조건에 초점이 맞춰져 있고 for문은 횟수에 초점을 맞춘다.
- while 문은 조건식이 충족되는 범위에서 반복하는 코드를 작성할 때 사용한다.
- for 문은 횟수가 정해져 있는 코드에 사용한다.
이게 꼭 정해진 법은 아니지만 원래 취지에 맞게 사용할 때 코드의 가독성이 좋다. 사실 프로그래밍은 고도의 창의성을 필요로 하는 작업인데 그 창의성을 발휘하기 위해서 엄격해져야 하는 순간이 있다. 어느 것이 정답이라고 말하기는 어렵지만 직장인이라면 직장의 룰에 따르는 것이고 프로그래밍을 학습이나 다른 차원에서 사용한다면 자신의 기준에 따르면 된다. 코드를 비효율적으로 작성한다고 해서 법이 막지는 않는다. 그렇다 하더라도 일반적으로 인정할 수 있는 좋은 코드라는 것이 존재한다.
(미래에는 코드가 공공재가 되서 코드의 작성을 법으로 규제할지도 모른다)
참고로 while 문은 대부분의 gui 애플리케이션에서 메인루프에 사용한다. 눈에 보이지는 않지만 웹브라우저도 while 루프를 돌면서 이벤트를 대기하고 있다.
while 문의 간단한 예제를 살펴보자.
- while 문에 진입하기 전에 main 의 지역변수인 count 를 0으로 초기화해서 count 가 5가 될 때까지 사용하였다.
- while 문은 조건식이 참일 때 { } 중괄호 코드블록을 실행한다. 블록의 실행이 끝나면 다시 조건식을 검사한다. 아래 코드에서는 count 가 4일 때까지 실행하고 5가되는 시점(cout 을 출력하고 난 후)에 거짓이되어 while 루프를 탈출한다.
int main()
{
cout << "Welcome!\n";
cout << "--------\n";
int count = 0;
while (count < 5)
{
count++;
cout << "count : " << count << endl;
}
cout << endl;
return 0;
}
이게 기본 사용법인데 while 문안에 if문을 중첩한다거나 while의 조건식에 논리연산을 한다거나 사용하기에 따라 복잡한 로직을 사용할 수 있다.
continue 와 break 키워드는 while이나 for문에서 흐름 제어를 하는데 사용할 수 있다. continue는 다음 조건식으로 건너뛰기, break는 현재의 반복문을 종료할 수 있다.
* continue문 예제
- count가 짝수의 경우 블록 다음의 문장들을 건너 띈다.
int main()
{
cout << "Welcome!\n";
cout << "--------\n";
int count = 0;
while (count < 10)
{
count++;
if (count % 2 == 0) continue;
cout << "count : " << count << endl;
}
cout << endl;
return 0;
}
* break문 예제
- count가 5에 도달하면 while 문을 종료한다.
int main()
{
cout << "Welcome!\n";
cout << "--------\n";
int count = 0;
while (count < 10)
{
count++;
if (count == 5) break;
cout << "count : " << count << endl;
}
cout << endl;
return 0;
}
continue와 break 는 조건문에 따라 흐름을 제어하는데 사용할 수 있다.
while(1) 은 조건식이 언제나 참이기 때문에 무한루프를 실행한다. 무한정 루프를 돌기 때문에 중단하지 않는다.
이런 코드가 어디에 쓰일까 싶지만 GUI같이 이벤트를 대기하는 프로그램은 무한루프를 돈다.
키보드 인터럽트로 끝낼 수 있다. 윈도우는 Ctrl + C 이다.
int main()
{
cout << "Welcome!\n";
cout << "--------\n";
int count = 0;
while (1)
{
count++;
cout << "count : " << count << endl;
}
cout << endl;
return 0;
}
- do while과 while문의 차이는 while문은 처음의 조건식부터 거짓이면 아예 실행이 되지 않는데, do while은 한번은 실행한다. while 은 { } 중괄호 다음에 나오며 세미콜론 ; 으로 구분해줘야 한다.
int main()
{
cout << "Welcome!\n";
cout << "--------\n";
int count = 0;
cout << "반복횟수를 입력하시오." << endl;
cin >> count;
do
{
cout << "count : " << count << endl;
count--;
} while (count > 0);
cout << endl;
return 0;
}
* count가 0이 되면 while문의 조건식에 처음부터 부합하지 않지만 처음 한번은 콘솔에 결과값을 출력한다.
do 하고 while 문을 검사해라... 는 문법이다. 한번은 실행하고 조건식을 검사해라. 는 뜻.
C++의 while문은 다른 C계열 언어와 문법이 비슷하니 처음에 개념을 잡으면 좋다.