강좌 첫화면으로 최근 글 보기(Post)
갈래별로 보기 categories




  3.1. 프로그램을 제어하는 제어문



3. 문법규칙과 자동화

(아래에서 [[ 기호와 ]] 기호는 << 기호와 >> 를 대신해서 사용함. HTML 태그 때문에 기호를 변경한 것임.)

이제까지 배운 내용 중에 잘 모르는 부분이 있다면 다시 한 번 복습을 해주시기 바랍니다. 이제부터는 좀더 까다롭고 어려운 프로그램을 다루어야 하기 때문입니다. 만약 그동안 배운 내용 중에서 빼먹거나 이해가 되지 않는 내용이 있다면 다시 한 번 이전 장들을 살펴보면서 잘 정리해주시기 바랍니다. 이제부터는 컴퓨터 혼자서 여러 가지 계산을 해주는 프로그램을 짜보도록 하겠습니다. 이번 마당을 마치면 여러분은 복잡한 계산을 대신해주는 프로그램을 짤 수 있는 실력을 얻게 될 겁니다. 어떻게 해야 컴퓨터가 알아서 척척 계산하는지 알아보도록 하겠습니다.

3.1. 프로그램을 제어하는 제어문


3.1.1. 제어문이란 무엇인가?


프로그램을 짜기 전에 먼저 합리적인 논리구조를 생각해야 합니다.

앞 장에서 test009.cpp를 이용해서 a를 하나씩 높여나갔지만 이런 식으로 100까지 가려면 명령문의 줄 수가 매우 길어질 겁니다. 즉 명령문이 많아지는 겁니다. 그래서 사람들은 좀더 간단하게 프로그램을 짤 수 있는 방법을 강구합니다. 그 결과 나온 명령문이 제어문이라는 것입니다. 제어문은 몇 종류 되지 않기 때문에 익히는 것은 그리 어렵지 않습니다. 그러나 제어문을 사용할 때의 편리함은 말로 표현하기 힘들 정도입니다. 그다지 어렵지는 않지만 가장 쓸만한 명령문이 바로 제어문입니다.

제어문의 기본구조는 사람이 생각하는 합리적인 구조를 닮았습니다. 예를 들어서 1부터 10까지 더한 뒤에 그 값이 얼마인지 출력하는 프로그램을 짜고 싶다고 합시다. 이럴 때는 먼저 1부터 10까지 어떤 방법으로 계산하는 것이 가장 빠를가를 생각해내야 합니다. 아마 대부분은 어렵지 않게 이런 생각을 가질 겁니다.

a라는 변수를 정한 뒤에 a에 1을 더한다. 그리고 a의 값에 2를 더해서 다시 a의 값으로 대입한다. 이렇게 되면 a=3이 된다. a의 값에 3을 더한 뒤에 다시 a의 값으로 대입한다. 그러면 a=6이 된다. 이런 식으로 10을 더할 때까지 반복한다.
그러나 이 방법은 1부터 10까지 각기 다른 숫자를 a에 대입하는 과정을 모두 적어주어야 합니다. 만약 1부터 백만까지 더하는 경우라면 소스파일의 길이가 매우 심각하게 길어집니다.

좀더 효과적인 계산방식은 이렇습니다.
a와 b라는 두 개의 변수를 생각한 다음에 a에는 1부터 시작해서 1씩 더해나갑니다. 그러면 a는 1씩 숫자가 커집니다. 그리고 b라는 변수에는 a의 값이 바뀔 때마다 a의 값을 더해나갑니다. 이 과정을 반복합니다.
이런 계산방식을 사용하면 a에 1씩 더해나가는 공식을 먼저 짠 뒤에 a의 값이 변할 때마다 b에 더해주는 공식 2개만 있으면 되므로 소스파일이 훨씬 간결해집니다. 또한 어떤 큰 수라도 소화해낼 수 있습니다.

이런 생각을 C++언어로 구현하기 위해서는 조금 복잡합니다. 위의 논리를 C++언어의 프로그램 구조도로 표현하면 아래와 같은 과정으로 이루어집니다. 앞의 숫자는 순서를 나타내는 번호입니다.

1. a와 b라는 변수를 선언하면서 각기 0을 대입합니다.
2. a라는 변수에 a+1을 대입합니다. 그럼 a=1이 됩니다.
3. b라는 변수에 b+a를 대입합니다. 그럼 b=1이 됩니다.
4. a가 10보다 작을 때까지 2에서부터 3의 과정을 반복합니다. 그러면 두번째 반복할 때는 a=a+1=2가 되고 b는 b=b+a=1+2=3이 됩니다. 즉 a는 0부터 1씩 더해지고 b는 앞서의 수에 a의 숫자만큼 더해갑니다. b이런 식으로 반복하다가 a가 9가 되면 a=a+1=10이 되므로 프로그램을 끝내도 됩니다. a가 10보다 작을 때까지만 하기로 했으므로 a가 10이 되면 이런 반복과정을 벗어납니다.

1에서 10까지 더하는 과정에 두 개의 바구니를 이용하면 편리합니다.

변수 a와 b를 이슬비와 한강물로 놓고 생각해봅시다. 1부터 10까지 더하려면 이렇게 해야할 겁니다. 먼저 이슬비가 가진 바구니에 사과 한 개를 줍니다. 그리고 이것을 한강물이 가진 바구니에 다시 넣습니다. 그리고 이번에는 이슬비가 가진 바구니에 사과 한 개가 불어난 두 개를 넣습니다. 그리고 역시 이것을 한강물이 가진 바구니에 넣습니다. 이렇게 이슬비가 가진 바구니에는 사과가 열 개가 될 때까지 한 개씩 불어난 사과를 주고, 이슬비는 이것을 다시 한강물의 바구니로 몽땅 넘겨주면 1부터 10까지 더하는 공식이 나오는 셈입니다. 9개를 받고 마침내 이슬비가 10개를 받았습니다. 그럼 이슬비는 이제는 그만 받아도 된다고 알려주고 마지막 10개도 한강물의 바구니에 넣습니다. 이렇게 하면 1부터 10까지 더한 갯수는 한강물의 바구니에 들어간 사과 갯수를 세보면 알 수 있습니다.

자 이상의 과정을 C++언어의 문장으로 표현하면 다음과 같습니다. 다음과 같이 프로그램을 짠 다음에 이 소스파일을 test010.cpp로 저장하고 실행파일로 만들어 실행시켜보기 바랍니다.

// test010.cpp

#include
#include

void main(void)
{
int a=0, b=0; // 정수형 변수 a와 b를 선언하고 0으로 값을 초기화했습니다.

while (a<10) // a가 10보다 작을 때까지 반복합니다.
{ // while 명령문의 시작
a=a+1; // a에 1을 더한 값을 a의 값으로 대입합니다
b=b+a; // b에 a의 값을 더해서 다시 b의 값으로 대입합니다.
printf(" a= %d, b=%d \n",a,b);
} // while 명령문의 끝
}


**그림: while문을 이용한 test010.cpp의 소스파일 내용

이 프로그램을 실행시키면 화면에 다음과 같은 결과가 나올 겁니다.

a= 1, b=1
a= 2, b=3
a= 3, b=6
a= 4, b=10
a= 5, b=15
a= 6, b=21
a= 7, b=28
a= 8, b=36
a= 9, b=45
a= 10, b=55


**그림: test010.exe를 실행했을 때 나타나는 화면

제어문을 사용하면 반복되는 과정을 간결하게 처리할 수 있습니다.

자 예제 소스파일을 하나씩 다시 살펴봅시다.

int a=0, b=0;


정수형인 변수로 a와 b를 선언한 다음에 0을 대입했습니다. a는 이슬비나 이슬비가 가진 바구니라고 보면 됩니다. b는 한강물이나 한강물이 가진 바구니로 보시면 됩니다. 둘 다 빈 바구니를 가지고 시작합니다.

while (a<10)


a가 10보다 작을 동안 while 뒤에 이어지는 문장이나 {} 안의 내용을 반복하라는 명령문입니다. 이때 이 while명령문을 제어문이라고 합니다. 그러니까 이슬비가 가진 바구니의 사과가 9개라면 한 번 더 while 안의 명령을 실행해야 한다는 뜻입니다.

{


제어문 다음에 오는 {와 } 기호를 복문기호라고 합니다.
while 제어문 다음에는 한 줄 짜리 명령문이 올 수 있는데, 이럴 경우에는 ;로 끝나는 한 줄의 명령만 실행하고 끝납니다. 그러나 게속해서 반복하고자 하므로 함수의 본체처럼 {}기호 안에 원하는 문장을 여러 개 넣어서 {와 } 사이를 조건이 만족될 때까지 반복하도록 합니다. { 기호와 } 사이에는 여러 개의 명령어를 넣을 수 있기 때문에 {와 } 기호를 복문기호라도 말합니다.

**요약: 프로그램의 실행과정을 제어하는 명령문을 제어문이라 합니다. 제어문 다음에는 함수처럼 {} 기호를 사용할 수 있는데, {와 } 사이에 여러 개의 명령문을 넣을 수 있기 때문에 복문기호라 합니다.


변수 a와 b에 값을 대입시키는 과정을 반복한 뒤에 출력합니다.


a=a+1;


a 변수에 a+1을 대입시킵니다. 현재 이슬비가 지닌 바구니는 한 개도 없으므로 처음에는 0+1이 대입되어 a는 1이 될 겁니다. 그리고 a가 10보다 작으므로 다시 while문을 반복해야 하고, 다음 번에는 이슬비 바구니에 하나에 하나를 더한 2개를 넣어줄겁니다. 즉 a는 2가 될 겁니다. 그렇게 계속해서 10보다 작을 때까지 반복됩니다. 즉 이슬비 바구니(a)에 든 사과가 9개일 때까지 while문이 반복된다는 뜻입니다.

b=b+a;


b에는 b+a를 대입시킵니다. 그러니까 한강물은 자기가 가진 사과에 이슬비로부터 넘겨받은 사과를 계속 더해 가지는 겁니다. 처음에는 0+1=1이 되지만 두번째에는 1+2가 되어 3이, 세번째에는 3+3이 되어 6이 됩니다. 이슬비가 하나를 넘겨주고, 다음에는 두 개를 다음에는 세 개를, 마지막에는 10개를 넘겨주는데 이것을 전부 가지고 있으면 됩니다. 이렇게 해서 while문이 끝날 때까지 이슬비로부터 넘겨받은 것을 더하는 과정이 반복됩니다.

printf(" a= %d, b=%d \n",a,b);


변수 a와 b를 화면으로 출력하라는 명령문입니다.
이 문장은 cout를 이용할 경우 다음과 같은 문장과 같습니다. 모니터로 출력하기 위해서 cout를 사용할 것인지 printf() 함수를 사용하는 것인지는 물론 여러분의 취향에 따라서 선택될 문제입니다.

cout[[" a= "[[a[[", b="[[b[[" \n";


이때 printf() 함수에 사용된 인수의 위치와 %기호의 갯수를 잘 살펴보시기 바랍니다. 인수의 순서가 a, b 순이므로 처음 나오는 %d에는 a가, 두번째 나오는 %d에는 b가 대입됩니다. 만약 %d가 하나밖에 없다면 첫번째 인수인 a 변수의 내용만 화면에 출력됩니다. 만약 %d가 세 개라면, 세번째 %d에는 이상한 값이 제멋대로 들어갑니다. 그러므로 %기호를 쓸 때는 %기호의 수와 인수(변수나 상수가 될 겁니다.)의 갯수를 맞추어서 정확하게 써야 합니다.

}


while 제어문의 본체가 끝났다는 표시입니다. 자 이 프로그램은 main() 함수의 복문기호({}) 안에 다시 while 명령문의(함수라고 해도 됩니다) 복문기호({} 기호)가 내포된 문장입니다. 물론 while 본체 안에는 또 다시 {} 기호가 내포될 수 있습니다. 그래서 {} 기호가 표시되는 칸의 위치를 조금씩 뒤로 미루어서 내포되는 정도를 쉽게 알아볼 수 있도록 프로그램을 짜는 겁니다.

**요약: printf() 함수를 사용할 때는 표현식 안에 들어가는 %기호와 인수의 갯수를 맞추어야 합니다. %기호에는 인수의 내용이 차례대로 대입됩니다.


[[연습문제]]
test010.cpp의 내용을 고쳐서 ex09.cpp로 저장합니다.
두 개의 변수 a, b를 이용하고 while문을 이용하여 2의 2제곱부터 2의 10제곱까지 계산하여 그 결과를 화면에 보여주도록 합니다.

[[연습문제 정답]]

// EX09.CPP -- while 제어문을 이용해 2의 제곱수 알아보기

#include
#include

void main(void)
{
int a=2, b=2; // a는 제어문을 반복할 변수, b는 2의 제곱을 대입할 변수

while (a<11) // a가 11보다 작을 때까지, 즉 10일 때까지 반복합니다.
{ // while 명령문의 시작
b=b*2; // b의 첫 값이 2이므로 처음에는 2*2가 대입됩니다.
printf(" 2의 %d제곱은 = %d \n",a,b);
a=a+1; // a에 1을 더한 a의 값이 11이 되면 while문을 벗어남
} // while 명령문의 끝
}

for문을 이용해도 while문을 이용할 때와 같은 결과를 얻을 수 있습니다.

이렇게 해서 1부터 10까지 더하는 프로그램은 한 번 짜봤습니다. 그런데 똑 같은 결과를 출력하는 프로그램이나 함수라 하더라도 사람에 따라서 각기 다른 형태로 짤 수 있습니다. 예를 들어서 test010.cpp를 좀더 간략하게 짜기 위해서 다음과 같이 짤 수도 있습니다. 다음과 같이 프로그램을 짠 뒤에 test011.cpp로 저장해서 실행시켜 보기 바랍니다.

// test011.cpp

#include
#include

void main(void)
{
int a,b=0; // 정수형 변수 a와 b를 선언하고 b에는 0을 대입시켜 초기화함
for(a=1;a<=10;a++) printf(" a= %d, b=%d \n",a,b=b+a); // for문을 이용해 루프를 돌림
}


**그림: for문을 이용한 test011.cpp의 소스파일 내용

어떻습니까? test010.cpp와 똑 같은 결과를 화면에 출력함을 알 수 있을 겁니다. 이처럼 똑 같은 결과를 내더라도 프로그램의 내용은 전혀 다를 수 있습니다. 그러니까 프로그램을 짜는 사람의 선호도나 기호, 프로그램 습관에 의해서 프로그램의 내용은 많이 달라집니다.


**그림: test011.exe를 실행했을 때 나타나는 화면

예제 프로그램을 한 번 살펴보도록 하겠습니다. test011.cpp의 프로그램은 2줄로 되어 있습니다.

int a,b=0;

for(a=1;a<=10;a++) printf(" a= %d, b=%d \n",a,b=b+a);


++는 증가연산자를 뜻하는 기호로 a++은 a=a+1과 같습니다.

첫번째 줄에서는 int형인 변수 a를 선언하고, b에는 0을 대입시켰습니다. 왜 b에만 값을 대입시켰는지는 다음 줄에 나옵니다. 다음 줄에서 for문을 사용하면서 a에 1을 대입시키기 때문입니다.
두번째 줄이 조금 복잡한데 설명은 이렇습니다. a 변수에는 1을 대입시킵니다. 그리고 a 변수의 내용이 10보다 작거나 같을 때까지 for 제어문 다음에 나오는 명령문이나 복문의 명령을 실행시킨다는 뜻입니다. 그리고 한 번 for문을 실행시킬 때마다 a++이라는 명령을 실행시킨다는 뜻입니다.
++은 증가연산자라고 해서 어떤 변수의 값을 하나 증가시키는 연산자입니다. 반대의 기능을 하는 연산자로는 -- 라고 하는 감소연산자가 있습니다. 그러니까 a++이라고 쓰면 a=a+1과 동일한 효과를 가지는 명령문입니다.

for문 다음에는 printf() 함수를 사용한 명령문이 나옵니다. 따라서 for문의 조건이 반복될 때까지 printf() 함수를 이용한 명령문을 계속 반복합니다.
'printf(" a= %d, b=%d \n",a,b=b+a);'의 뜻은 처음 나오는 %d에 a를 대입시켜 출력하고, 두번째 나오는 %d에는 b=b+a를 대입시켜서 출력하라는 명령어입니다. for문이 처음 실행될 때 a는 1이고, b는 0인데, 인수를 줄 때 b=b+a라는 공식을 적어서 대입시키므로 두번째 %d에는 b=b+a를 대입시킵니다. 두 번째 %에 들어갈 변수 b의 값도 1이 됩니다.

**요약: a++은 a에 a+1을 해서 대입시키는 기능과 같습니다. ++ 기호를 증가연산자라고 하며, 변수의 내용을 1만큼 증가시켜줍니다.


제어문을 이용하여 같은 구간의 명령을 반복시키는 것을 루프를 돌린다고 합니다.

test011.cpp에서는 for제어문 다음에 {}기호를 사용하지 않았습니다. 한 줄로도 원하는 결과를 얻을 수 있기 때문입니다. 그러나 test011.cpp이 test010.cpp보다 더 잘 짠 프로그램이라고 말하기는 어렵습니다. 각기 취향이 있기 때문입니다. 하여간 똑 같은 결과를 내는 프로그램이라도 프로그램 내용은 전혀 다를 수 있다는 점을 test010.cpp와 test011.cpp를 통해서 알 수 있습니다.

그러므로 좋은 프로그래머란 프로그램을 보기 쉽고 이해하기 쉬우면서도 짧게 짜는 사람을 말합니다. 짧게 짜는 대신 너무 어렵게 짜는 것은 좋지 않습니다. 또 쉽게 짜는 것은 좋지만 너무 길게 짜는 것도 좋지 않습니다. 그리고 결과는 같더라도 결과를 얻기까지의 과정이 프로그램에 따라서 다르기 때문에 결과를 얻기까지의 시간이 달라집니다. 그래서 보통 잘 만든 프로그램이라는 기준은 같은 결과를 얻기 위해서 얼마의 시간이 걸리냐로 판단합니다.

예를 들어서 a라는 변수를 1부터 시작해서 10만이 될 때까지 1씩 더하는 프로그램을 짠다고 합시다. 한 사람은 for문을 이용해서 짰고 한 사람은 while문을 이용해서 짰습니다. 이때 결과는 같이 나오겠지만 결과가 나오기까지의 시간은 다를 수 있습니다. 그래서 어떤 명령어를 어떻게 쓰면 출력결과가 빨리 나온다는 것을 잘 이용해서 프로그램의 계산속도를 조금이라도 더 빨리 할 때 프로그램을 잘 짠다고 말하는 겁니다.

하여간 while문을 사용하든 for문을 사용하든 어떤 동작을 반복시킬 수 있습니다. 이를 통해서 프로그램을 자동화할 수도 있습니다. 이때 동작을 반복시키는 것을 루프(loop)를 돌린다고 표현합니다.

**요약: 제어문에는 여러 가지가 있으며 프로그래머의 취향에 따라서 적절한 제어문을 사용합니다. 제어문을 통해서 어떤 명령어들을 반복시킬 수 있는데, 이렇게 명령어가 반복되는 과정을 루프(loop)를 돌린다고 말합니다.


[[연습문제]]
test011.cpp의 내용을 고쳐서 ex10.cpp로 저장합니다.
한 개의 변수 a를 이용하고 for문을 이용하여 1의 2제곱부터 10의 2제곱까지 계산하여 그 결과를 화면에 보여주도록 합니다.

[[연습문제 정답]]

// EX10.CPP -- for 제어문을 이용해 1부터 10까지 2제곱수 알아보기

#include
#include

void main(void)
{
int a=1; // a는 제어문을 반복할 변수

while (a<11) // a가 11보다 작을 때까지, 즉 10일 때까지 반복합니다.
{ // while 명령문의 시작
printf(" %d의 2제곱은 = %d \n",a,a*a);
a=a+1; // a에 1을 더한 a의 값이 11이 되면 while문을 벗어남
} // while 명령문의 끝
}

3.1.2. 조건이 만족할 때까지 반복하는 while 제어문


while문은 어떤 조건이 만족되는 동안 즉 참인 동안 뒤에 나오는 명령문을 반복합니다.

이제 제어문을 하나씩 배워보도록 하겠습니다. 첫번째로 사용할 제어문은 while 제어문입니다. 이 문장은 어떤 조건이 만족될 때까지 프로그램을 계속 반복하도록 하는 제어문입니다. 그러니까 이슬비 보고 열 개가 되기 전까지는 아까의 수에 하나씩 더하라고 명령을 하거나 물을 열 번 기를 때까지는 놀러나가지 못하도록 할 때 사용합니다. 열 개가 되기 전까지라는 조건이나, 물을 열 번 나를 때까지라는 조건을 달 때 사용하는 제어문이 while 제어문입니다.

조건이 만족되기 전까지는 어떤 일을 하라고 지시를 내릴 겁니다. 그리고 조건이 만족되면 while 제어문이 내린 명령을 그만 하고 while 제어문의 구속으로부터 자유롭게 벗어날 수 있습니다.
원하는 조건이 만족될 때까지 프로그램을 돌릴 수 있으므로 프로그램을 짤 때 while 제어문은 많이 사용하게 될 겁니다. 'a가 100이 되기 전까지' '마지막으로 입력한 글쇠가 ESC가 아닐 때까지' '파일의 끝이 아닐 때까지' 'a가 홀수인 동안'과 같은 조건을 내걸고 어떤 명령문을 반복할 수 있습니다.

조건이 맞는 것을 '참', 조건이 만족되지 않으면 '거짓'이라고 합니다.

while문은 '~하는 동안에'라는 뜻을 가진 낱말입니다. 그러므로 조건이 참인 동안은 계속 반복하는 성질을 가졌습니다. 예를 들어서 while(a<100)이라고 했으면 'a가 100보다 작은 동안에는'이라는 뜻입니다. a가 100보다 작은 동안에는 while 제어문 뒤의 명령어를 반복해야 한다는 뜻입니다. a가 10이 되면 여전히 a는 100보다 작으므로 (a<100)이라는 조건은 참이 됩니다. 그래서 while문을 반복해야 합니다. a가 99가 되어도 여전히 a는 100보다 작으므로 while문을 반복합니다. 이렇게 조건에 맞는 것을 조건이 '참'이라고 말합니다. 거짓의 반대말로 참이라고 사용합니다.
그러나 a가 100이나 200이 되면 a가 100보다 작지 않습니다. 이럴 경우 조건식은 거짓이 됩니다. a가 200이라면 a<100은 200<100이 되기 때문입니다. 200<100이라는 공식은 참이 아니고 거짓입니다. 수학 시간에 참과 거짓에 대해서는 배우셨으리라 생각하므로 더 이상의 설명은 드리지 않겠습니다. 이처럼 조건식이 거짓이 되면 while문을 벗어날 수 있습니다.

**요약: 조건이 맞는 것을 '참', 조건이 만족되지 않으면 '거짓'이라고 합니다. while문은 어떤 조건이 참일 동안 while에 딸린 명령문을 반복하라는 뜻을 지닌 제어문입니다.


while문의 사용형식은 다음과 같습니다.

while(조건식)

{

반복되는 문장이나 명령어들

...

}


조건식이란 어떤 조건을 만족시켰을 때 실행되도록 만든 식을 말하니다.

조건식이란 어떤 조건을 만족했을 때 무엇인가 하도록 만든 식을 말합니다. 예를 들면 a<10이라고 쓰면 a라는 변수가 10보다 작을 때라는 뜻을 지니고 있습니다. 또는 a==b라고 쓰면 a와 b가 같을 때라는 조건식이 되는 겁니다. a가 11이 될 경우에는 a<10이 11<10이 되므로 거짓이 됩니다. 11이 10보다 작을 수는 없으니까요. 이럴 때는 while문 뒤에 나오는 복문의 명령을 실행할 필요가 없습니다.

또는 다음과 같이 사용할 수 있습니다.

while(조건)

문장이나 명령어;


while문은 이미 test010.cpp를 통해서 충분히 배웠기 때문에 더 이상의 설명은 필요하지 않으리라 생각합니다. 만약 while문의 조건이 만족될 때까지 실행해야 할 명령어가 많다면 {}를 이용하여 여러 개의 명령문과 함수를 다시 내포하는 방법을 사용하면 됩니다. 그리고 한 번 정도만 실행시키면 되는 단순한 명령문이라면 {} 기호를 사용하지 않고 바로 다음 줄에 원하는 명령문을 적으면 됩니다. 물론 단문으로 문장이나 명령어를 적을 때는 끝에 ; 기호를 붙이는 것을 잊어서는 안됩니다.

**요약: while문은 조건이 참일 때만 뒤에 딸린 명령을 반복하는 제어문입니다. 제어문에 딸린 명령문은 한 줄 짜리를 이용할 수도 있지만 복문기호를 이용하여 여러 줄을 실행할 수도 있습니다.


아래와 같은 문장으로 프로그램을 짜고 test012.cpp라고 저장하여 실행시켜 보기 바랍니다.

// test012.cpp

#include
#include

void main(void)
{
int a=0;

while (a<4) // a가 4보다 작을 동안
{ a=a+1; // a의 값을 1씩 증가시키면서
cout[[" a= "[[a[[" \n";
}
a=0;
while (a++<8) // a가 8보다 작을 동안, a를 1씩 증가시키면서
printf(" a= %d \n",a);
}


**그림: 반복과정을 두 가지의 방법으로 구성해본 test012.cpp의 소스파일 내용

test012.cpp를 통해 복문의 명령어와 한 줄 짜리 명령어의 실행과정을 비교해봅니다.

test012.cpp를 실행시키면 아래와 같은 결과를 화면에 보여줍니다.

a= 1
a= 2
a= 3
a= 4
a= 1
a= 2
a= 3
a= 4
a= 5
a= 6
a= 7
a= 8


**그림: test012.exe를 실행시켰을 때 나오는 화면

예제프로그램의 명령문을 살펴보겠습니다.

int a=0;


정수형인 변수 a를 선언하고 0을 대입했습니다.

while (a<4)

{ a=a+1;

cout[[" a= "[[a[[" \n";

}


a가 4보다 작을 동안 복문인 {}안의 내용을 반복합니다. 활괄호 안의 내용은 a에 a+1의 값을 대입시킨 후에 a를 화면으로 출력하라는 명령문입니다. 이렇게 해서 a가 4보다 작을 때까지 {}안의 내용을 반복합니다. 그래서 1부터 4까지 화면에 출력된 겁니다.

a=0;

while (a++<8)

printf(" a= %d \n",a);


다시 a 변수를 0으로 만듭니다. 그리고 이번에는 a가 8보다 작을 때까지 다음 문장을 반복합니다. while문이 두 번 반복되지만 앞의 while은 {} 안의 문장을 반복했고, 이번에는 이어서 나오는 printf() 함수 명령어만을 반복합니다.

우선순위에 따라 조건식이 계산된 뒤에 ++연산자가 실행됩니다.

이때 조건식의 a에는 ++연산자가 붙어있으므로 while문을 한 번 되풀이할 때마다 a의 값이 하나씩 올라갑니다. 즉 처음에는 a가 0인 상태에서 while문 뒤의 명령문을 실행시킵니다. a++은 a를 하나 증가시키라는 증가연산자이므로 a는 1이 됩니다.
순서로 따지면 괄호가 더 중요하므로 조건식인 a++<8이 먼저입니다. 그러므로 0<8이 먼저 계산됩니다. 그리고 조건식이 계산 된 뒤에는 a++에 의해서 a에 1이 대입됩니다. 그래서 다음 문장에서 a를 출력하면 0이 아닌 1이 나오는 겁니다.

다시 while문이 반복될 때는 1<8이 될 것이고, 이 조건식이 계산된 뒤에는 a++이 계산되어 a=2가 됩니다. 이런 식으로 a가 8보다 작을 동안 반복하므로 a가 7일 때까지는 while문을 반복합니다. 최종적으로 a가 7이면 a++을 계산하여 a=8이 되고, 8을 화면에 출력한 뒤에 이 프로그램은 끝납니다.
이처럼 제어문은 {} 기호 안에 여러 개의 명령문을 내포해서 반복할 수도 있고, 하나의 명령문만 반복할 수도 있습니다.

제어문을 사용할 때는 조건식을 어떻게 만들 것인가를 고민해야 합니다.

이때 잘 알아두셔야 할 점은 while문의 사용법이 아닙니다. while문의 사용법은 지금 살펴본 것처럼 별로 어렵지 않습니다. 그러나 조건식을 만드는 방법은 매우 어렵습니다. a<10으로 해야 10까지는 더하는 것인지, a<11로 해야 10까지 더하는 것인지 잘 판단해야 합니다. while문에 따르는 명령문으로 어떤 명령문을 사용할 것인가에 따라서 a<10으로 하거나 a<11로 해야 하기 때문입니다.
어떤 조건식을 내걸어야 원하는 숫자만큼 명령문이 반복되는지는 프로그래머만이 알 수 있습니다. 프로그램의 만들고 나서 실행하니 원치 않는 결과가 나왔다면 대부분 조건식을 잘못 주었기 때문입니다. 조건식을 잘 주는 것은 프로그래머의 능력에 해당합니다. 그리고 조건식을 잘 주기 위해서는 논리적인 사고가 필요합니다.

**요약: 제어문을 이용해 제어문에 딸린 명령문을 반복 실행시킬 수 있는데, 명령문은 한 줄 짜리는 물론 복문도 가능합니다. 제어문을 잘 활용하기 위해서는 조건식을 잘 만들어야 하는데, 조건식을 만들기 위해서는 논리적인 사고가 필요합니다.


3.1.3. 좀더 간단한 제어문인 for 순환문


for문은 하나의 문장으로 변수 초기화, 조건식, 명령문 실행이 가능한 제어문입니다.

for 제어문은 while 제어문과 비슷하지만 하나의 문장에 변수의 초기화와 조건식, 간단한 연산, 명령문을 실행시킬 수 있으므로 while보다 좀더 편리하게 사용할 수 있는 제어문입니다. for문의 형식은 다음과 같습니다.

for(변수에 값 대입,변수에 값 대입,...; 조건식; 명령문 실행, 명령문 실행,...);


또는 다음과 같이 사용합니다.

for(변수에 값 대입,변수에 값 대입,...; 조건식; 명령문 실행, 명령문 실행,...)

{

명령문들;

...

}


또는 다음과 같이 사용합니다.

for(변수에 값 대입,변수에 값 대입,...; 조건식; 명령문 실행, 명령문 실행,...)

명령문;


이때 두번째 형식과 세번째 형식을 사용할 때는 for문 끝에 ; 기호가 붙지 않음을 눈여겨 보시기 바랍니다. 그러나 for문 하나로 명령이 끝날 때는 for문 뒤에도 ; 기호를 붙여야 합니다.

**요약: for문은 변수의 초기화(또는 대입)와 조건식, 명령문을 한 문장으로 표현할 수 있는 제어문입니다. for문 하나로 명령이 끝날 때는 ; 기호를 붙입니다.


for문은 세 부분으로 구성되는데 첫번째 부분은 변수 초기화 부분입니다.

for문의 형식을 하나씩 살펴보도록 하겠습니다.
for문은 for()이라는 괄호 안에 각종 명령을 넣을 수 있습니다. while문이 괄호 안에 조건식만을 넣어서 사용한 것과는 달리 여러 개의 다양한 명령어를 넣을 수 있습니다. 명령문은 크게 세 부분으로 나누어집니다. 첫번째 부분은 변수의 값을 초기화하는 부분이고, 두번째 부분은 조건식을 넣는 부분, 세번째 부분은 조건식을 만족할 경우 실행할 명령문을 넣는 부분입니다.

먼저 첫번째로 변수를 초기화하거나 변수에 원하는 값을 대입할 수 있습니다. 앞서 만들었던 예제프로그램을 다시 살펴보면서 말씀드리겠습니다.

int a,b=0;

for(a=1;a<=10;a++)

printf(" a= %d, b=%d \n",a,b=b+a);


괄호 안의 첫번째 명령문은 a=1입니다. 즉 a에 1의 값을 대입시켜서 a의 값을 초기화시키는 것입니다. 초기화시킨다는 말은 처음 상태처럼 만든다는 뜻이니, 이전에 들어있던 값을 무시하고 지금 넣는 값으로 변수의 내용을 채우라는 뜻입니다. while문은 문장이 시작되기 전에 변수에 값을 대입시켰지만 for문에서는 제어문을 시작하면서 변수를 초기화할 수 있어서 편합니다. 변수의 대입이 끝났으면 ; 기호를 통해서 하나의 명령문이 끝났음을 알려주어야 합니다.

만약 첫번째 부분에서 초기화시킬 변수가 a 하나가 아니라 여러 개라면 어떻게 할 수 있을까요? 변수의 초기화 부분에서 배웠던 것처럼 쉼표(,)기호로 각 변수를 구분하면서 여러 개의 변수에 값을 대입시킬 수 있습니다.

for(a=1, b=2, c=5, d=9;a<=10;a++)


이렇게 4개의 변수에 각기 값을 대입시킬 수 있습니다. 물론 원하는 변수만 값을 대입시킬 수도 있습니다. 이 명령문은 우리가 변수의 선언 부분에서 배운 변수의 선언부분만 생략한 문장입니다. 즉 int라는 자료형의 선언만 생략한 것일 뿐 뒷부분은 동일합니다. 변수를 선언할 때 'int a=1, b=2, c=5, d=9; '라고 선언할 수 있는데, 이 문장에서 int라는 낱말만 하나 빠진 셈입니다. 왜냐하면 for문에서 변수를 사용하기 전에 변수는 미리 선언되어야 하기 때문입니다. 그래서 변수의 선언만 빠졌을 뿐 변수의 대입명령어와 같습니다.

for문의 세 부분은 ; 기호로 구분되며 두번째 부분은 조건식이 들어갑니다.

; 기호로 첫번째 명령문의 끝을 알리면 두번째 명령문이 시작되는데 두번째 부분은 조건식입니다. for(a=1;a<=10;a++)이라는 문장에서는 a<=10이라는 것이 조건식입니다. 이 조건식은 a가 10보다 작거나 같을(<=) 동안이라는 뜻입니다.
<=는 왼쪽의 변수나 상수가 오른쪽의 변수나 상수보다 작거나 같다는 뜻입니다. == 는 양쪽이 같을 때 사용하고, >=는 왼쪽이 오른쪽보다 크거나 같을 동안이라는 뜻입니다. <는 왼쪽이 오른쪽보다 작다, >는 왼쪽이 오른쪽보다 크다는 것을 비교하는 비교연산자입니다.
for문에서도 역시 가장 중요한 것은 두번째 문장입니다. 조건식을 제대로 만드는 것이 가장 중요합니다. 두번째 명령문의 끝 역시 명령문 종결기호인 ; 기호로 알려줍니다.

for문의 세번째 부분은 실행 명령문입니다.

세번째 문장은 조건식이 맞을 경우 실행할 명령문을 적습니다. for(a=1, b=2, c=5, d=9;a<=10;a++)라는 제어문에서는 a++을 실행하라고 되어 있습니다. ++는 증가연산자로 a에 1을 더해서 a에 대입시키는 a=a+1의 기능과 같은 연산을 한다고 말씀드렸습니다. 그러므로 조건이 만족되고 for문이 한 번씩 돌 때마다 a의 값은 1씩 올라갑니다.
세번째 명령문의 명령문 역시 여러 개를 넣을 수 있습니다. 그리고 각 명령문은 쉼표로 구분할 수 있습니다. for(a=1, b=2;a<=10;a++, b=b+2, c=c+3)와 같이 사용하면 a에는 하나씩 더하고, b에는 두 개씩 더하고, c에는 세 개씩 더해서 변수에 값을 대입시키라는 명령문이 됩니다. 세번째 명령문은 ; 기호를 넣지 않습니다. 왜냐하면 앞에서 ; 기호가 두 번 들어간 것으로 마지막 세번째 부분이라는 것을 알 수 있기 때문입니다.

for문을 사용하면 프로그램의 구조가 간결해집니다.

for문 안에 여러 개의 명령문이 들어가기 때문에 사용법이 까다로와 보이지만 실제로는 사용하기 편한 제어문입니다.
for(a=1;a<=10;a++)라는 명령문을 이슬비를 들어서 설명하면 이렇습니다. 이슬비의 바구니에 사과 한 개를 넣는다. 이슬비의 바구니에 넣는 사과가 10개보다 작거나 같을 때까지 이슬비의 바구니에 사과를 한 개씩 더해서 넣는다. 이런 명령문입니다. 그러므로 사과가 10개일 때까지는 for문을 반복하는 셈입니다.
for문을 이용하면 앞서 우리가 만들었던 1부터 10까지 더하는 프로그램을 좀더 간결하게 줄일 수 있습니다. 아래와 같이 프로그램을 짜고 프로그램 이름을 test0112.cpp로 저장하기 바랍니다.

// test0112.cpp
// for 문을 이용해 1부터 10까지 더하기

#include

void main(void)
{ int a,b;
for(a=0,b=0;a<10;a++,b=b+a,printf("a=%d b=%d \n",a,b));
}


**그림: test0112.cpp의 소스파일 내용

이 프로그램을 실행시켜도 test011.cpp의 결과와 동일하게 나옵니다. 이 프로그램은 딱 두 줄로 되어 있습니다. 변수의 선언부분과 for문 한 줄입니다. 이 두 문장을 살펴보겠습니다.

int a,b;


이제 이 부분에 대해서는 설명 안해도 잘 아시리라 생각합니다. 정수형 변수 a와 b를 선언했습니다. 다시 한 번 강조하지만 변수는 사용하기 전에 늘 선언해두어야 합니다.

for(a=0,b=0;a<10;a++,b=b+a,printf("a=%d b=%d \n",a,b));


문장이 조금 복잡해보일 뿐 지금까지 배운 for문의 문장 구조와 같습니다. 첫번째 변수 초기화부분에서는 a와 b에 0을 대입해서 변수의 값을 0으로 초기화했습니다.

두번째 조건식 부분에서는 a<10이라는 조건식을 내세웠습니다.

for문의 명령실행문에는 일반적인 명령어는 물론 함수도 여러 개 실행시킬 수 있습니다.

세번째 문장이 중요하므로 잘 보시기 바랍니다. 세번째 명령실행문에서는 세 개의 명령을 사용하고 있습니다. a++을 이용해서 a에 a+1의 값을 대입시킵니다. 그래서 a=1이 됩니다. 두번째 명령문은 b=b+a가 됩니다. 그래서 b도 1이 됩니다. 세번째 명령문은 그동안 별도로 사용해왔던 printf() 함수명령문입니다. printf("a=%d b=%d \n",a,b)라는 함수는 처음 나오는 %d에 a의 값을 대입시키고, 두번째 %d에 b의 값을 대입시켜서 출력하라는 명령문입니다. printf() 함수의 사용법 자체는 그동안 설명했으므로 이 문장 자체는 쉽게 이해할 수 있을 겁니다.

세번째 문장에서 중요한 점은 명령문에 함수를 사용했다는 점입니다. 그러나 사실 알고보면 새로울게 없는 내용입니다. a=0; 이라는 명령문이나 printf() 함수를 사용한 명령문이나 같은 위치를 가지는 하나의 명령문으로 취급하고 있으니까요. a=0이라는 명령문을 for문 안에 쓸 수 있다면 printf() 함수를 이용한 명령문 역시 for문 안에 사용할 수 있습니다. 그러므로 세번째 문장을 통해서 알 수 있는 것은 제어문 안의 괄호 안에는 각종 명령문과 함수가 들어갈 수 있다는 사실입니다. 유추해서 생각해보면 함수의 괄호 안에도 여러 가지 명령어와 함수가 들어갈 수 있다는 말이 됩니다. 즉 함수의 괄호 않에 함수가 들어가고, 내포된 함수의 괄호 안에 또 함수가 들어갈 수 있는 셈입니다. 물론 이렇게 함수를 사용하면 매우 복잡해집니다. 그래서 가능하면 보기 편하게 사용해야 합니다만 함수가 함수를 포함할 수 있다는 사실만은 알아두고 넘어가시기 바랍니다.

**요약: for문의 괄호 안은 세 부분으로 나누는데, 첫번째 부분은 변수의 값을 초기화하는 부분이고, 두번째 부분은 조건식을 적는 부분, 세번째 부분은 조건식이 맞을 경우 수행할 명령문을 적는 부분입니다. 각 부분은 ; 기호로 구분하고, 쉼표 기호를 이용해서 여러
개의 변수를 초기화하거나 여러 개의 명령문을 적을 수 있습니다.


**그림: test0112.exe를 실행 결과는 test011.exe와 같습니다.

컴파일러는 명령어 사이의 빈 칸이나 탭문자를 무시합니다.

그리고 ; 기호로 각 명령문을 구별해주기만 하면 여러 개의 명령어를 한 줄에 쓸 수도 있습니다. 명령어 사이에 들어가는 빈 칸이나 탭문자는 컴파일러가 컴파일할 때 무시하고 컴파일합니다. 물론 문장을 나타내는 "" 기호 안에 든 빈 칸은 무시하지 않습니다. 그러므로 test0112.cpp를 아래와 같이 짜도 같은 컴파일러는 같은 프로그램으로 인식합니다.

// test0113.cpp
// for 문을 이용해 1부터 10까지 더하는데 한 줄로 짜기

#include

void main(void) { int a,b; for(a=0,b=0;a<10;a++,b=b+a,printf("a=%d b=%d \n",a,b)); }


**그림: test0113.cpp의 소스파일 내용

main() 함수 뒤에 {기호를 붙이고, 변수선언문도 붙이고, for문까지 붙인 뒤에 } 기호로 닫았습니다. 그래도 앞서 여러 줄로 만든 프로그램과 내용이나 실행결과는 같습니다. 단지 사람이 알아보기 불편할 뿐입니다. 그래서 프로그램은 보기 편하게 적절하게 줄을 나누고 들여쓰기를 해서 짜야하는 겁니다.

**요약: 문법형식만 맞다면 여러 개의 명령문을 한 줄에 쓸 수 있습니다. 그러나 보기 불편하므로 가능한 적당하게 줄을 나누고 들여쓰기를 해서 소스파일을 짜도록 합니다.



**그림: test0113.exe의 실행결과 역시 test011.exe와 같습니다.

for문의 세 가지 작성방식을 예제로 만들어봅니다.

이제 다음과 같은 프로그램을 만들어 test013.cpp로 만들어 실행시켜 보기 바랍니다.

// test013.cpp
// for문의 세 가지 작성방식

#include
#include

void main(void)
{
int a;

for(a=1;a<=3;) // 복문구조를 이용한 명령 실행
{
cout[[" a= "[[a[[" \n";
a=a+1;
}
for(a=1;a<=3;a+=1) // 명령줄을 for문 뒤에 붙여서 명령 실행
cout[[" a= "[[a[[" \n";
for(a=1;a<=3;printf(" a= %d\n",a),a++); // for문 안에서 명령 실행
}


**그림: test013.cpp의 소스파일 내용

이 프로그램을 실행시키면 아래와 같은 내용이 화면에 출력될 겁니다.

a= 1
a= 2
a= 3
a= 1
a= 2
a= 3
a= 1
a= 2
a= 3


**그림: test013.exe의 실행결과

이 프로그램을 하나씩 분석해봅시다.

int a;


첫번째 명령을 통해 정수형 변수 a를 쓰겠다고 선언했습니다.

for문에서 조건식 부분은 생략이 불가능하지만 다른 부분은 생략 가능합니다.


for(a=1;a<=3;)

{

cout[[" a= "[[a[[" \n";

a=a+1;

}


for문을 통해서 a에 1을 대입시키고 a가 3보다 작거나 같을 때까지 명령문을 실행시킵니다. 명령문은 {} 사이에 들어 있는 두 개의 문장입니다.

여기에서 눈여겨 봐야할 부분이 있습니다. ; 기호가 두 번 나오고 세번째 부분은 생략된 점입니다. for문은 (변수의 초기화부분; 조건식; 명령문)의 세 부분으로 구성되어 있다고 했습니다. 그러나 프로그램을 짜다 보면 실행하지 않고 넘어가야 할 부분이 있습니다. 이럴 때는 ; 기호를 통해서 각 부분을 구별만 해주고 빈부분으로 남겨두어도 됩니다.
그러나 그렇다고 해서 조건식까지 생략하면 안됩니다. 조건식은 생략하면 for문을 써야할 필요가 없기 때문입니다. 물론 조건식을 검사할 때 에러가 나므로 for문이 실행될 일도 없습니다. 그러므로 for(;a<10;)과 같이 쓸 수는 있어도 for(a=1;;)와 같이 써서는 안됩니다.

**요약: for문에서 조건식을 제외한 변수의 초기화부분과 명령문 실행 부분은 생략할 수 있습니다. 명령문 실행을 지시한 후에는 ; 기호를 쓰지 않습니다.


for문에 딸린 명령문이 복문일 때는 복문 끝에 ; 기호를 붙이지 않습니다.

for문을 시작하면서 정수형 변수 a에 1을 대입했습니다. 그리고 cout를 이용해서 a의 값을 화면에 출력합니다. 그리고 a에 a+1을 대입시켜서 a를 2로 만듭니다. 역시 a<=3의 조건을 만족시킵니다. a의 값이 2이므로 2<=3이라는 조건식이 되므로 다시 for문을 실행시킵니다. 그리고 화면에 2를 출력해줍니다. 다음에도 a=3이 되어 3<=3을 만족시키므로 3을 화면에 출력합니다.
그리고 다시 a에 1을 더하면 a는 4가 됩니다. 이렇게 되면 4<=3이라는 조건식이 거짓이 됩니다. 그러므로 for문에 딸린 {} 안의 내용을 실행할 필요가 없습니다. 그래서 다음 명령어로 넘어갑니다.

이 과정을 사람의 행동으로 바꾸어서 생각해봅시다. for문을 통해서 한강물(사실상 프로그램을 짠 사람입니다만)이라는 학생이 이슬비에게 명령을 내립니다. '이슬비야. 내가 지금 너한테 사과 한 개를 줄께. 사과가 세 개보다 작거나 세 개일 때까지는 내가 사과를 넘겨줄 때마다 칠판에 너가 받을 사과 갯수를 적어라.'는 명령문입니다. 처음에는 한 개를 받았으므로 이슬비가 1개라고 칠판에 적습니다. 그리고 나면 한강물이 이슬비(a)에게 한 개를 더한 두 개의 사과를 줍니다.

'이슬비야 너가 가진 사과가 아직도 세 개보다 적거나 세 개니?'하고 물어보는데, 이슬비가 가진 사과가 두 개라면 '아냐 두 개 가지고 있어. 두 개라고 칠판에 쓸께.' 하고 행동을 합니다. 이슬비가 칠판에 두 개라고 쓰면 한강물은 한 개를 더해서 세 개를 넘겨줍니다. 그리고 또 묻습니다.

'이슬비야 너가 가진 사과가 아직도 세 개보다 적거나 세 개니?'

이때 이슬비는 세 개를 가지고 있으므로 '응! 세 개야' 하고 다시 칠판에 '세 개'라고 적습니다. 그러면 이번에는 한강물이 한 개를 더해서 네 개를 넘겨줍니다. 그리고 다시 for조건식에 따라서 또 묻습니다.

'이슬비야 너가 가진 사과가 아직도 세 개보다 적거나 세 개니?'

이때서야 비로소 이슬비는 '아니야. 네 개를 받았으니까 세 개보다 많아'하고 알려줍니다. 이때 '아니야'라고 대답했으므로 이때서야 조건이 거짓이 됩니다. 그래서 이슬비가 칠판에 갯수를 쓰는 일도, 한강물이 이슬비에게 다시 사과를 넘겨주는 일도 할 필요가 없습니다.

그러나 이슬비의 행동을 살펴보면 조금 멍청하다는 사실을 알 수 있습니다. 일단 사과 네 개를 받았기 때문입니다. 그리고 나서는 사과 네 개는 필요 없어 하고 버립니다. 무거운 짐을 네 개씩이나 일단 받은 뒤에 '야 그것 필요 없으니까 도로 내려놓거나 어디다 버려'하고 말해준다면 얼마나 열받겠습니까? 그래서 좀더 힘이 덜 드는 조건문은 세 개보다 적을 때까지만 하나를 더해서 다시 받으라고 주어야 합니다. 아니면 3개일 때까지만 칠판에 적으라고 조건을 주어야 합니다. 따라서 조건식을 잘 주면 쓸 데 없이 한 번 더 하는 일을 줄일 수 있습니다.

for문에 딸린 명령문이 단문일 때는 명령문 끝에 ; 기호를 붙입니다.


for(a=1;a<=3;a+=1)

cout[[" a= "[[a[[" \n";


첫번째 for문은 {}기호를 통해서 복문 안에서 명령문을 실행한 for문입니다. 두번째 for문은 좀더 간단합니다. 역시 내용이나 출력결과는 앞서 사용한 for문과 하나도 다를 것이 없습니다. a에 1을 다시 대입시키고, a가 3보다 작거나 같을 때까지 명령문을 반복하는데, a+=1이라는 명령문을 실행합니다. 그리고 이어서 cout 명령문도 실행합니다. 이때는 이어지는 명령문에 끝을 알리는 ; 기호를 넣었습니다.

for문 한 줄로 명령이 끝날 때는 for문 끝에 ; 기호를 붙입니다.


for(a=1;a<=3;printf(" a= %d\n",a),a++);


세번째 문장은 한 줄로 구현되었지만 좀더 복잡한 형식을 사용했습니다. for문에서는 변수대입부분이나 명령문 실행부분에서 쉼표(,)를 이용해서 여러 개의 변수에 값을 넣을 수도 있고, 여러 개의 명령문을 실행시킬 수도 있습니다.
세번째 부분은 먼저 printf() 함수를 이용해서 a의 값을 화면에 출력합니다. 그리고 a++이라는 명령을 실행해야 합니다. a=1이므로 printf() 함수를 사용하자 마자 a=2가 됩니다. a가 3이 되면 printf() 함수를 실행하고, 이어서 a는 4가 됩니다. 그러면 a<=3이라는 조건식이 거짓이 되므로 for문을 벗어납니다.
이때의 for문은 뒤에 딸린 명령문이 없고 for문 한 문장으로 모든 내용이 끝나기 때문에 끝에 ; 기호를 붙였습니다.

변수 a가 4를 받지 않고 3까지만 받고 끝나도록 소스파일 고치기

지금까지 살펴본 세 개의 for문은 일단 a에 4라는 값이 대입된 후에 for문을 벗어났습니다. 이슬비가 일단 무거운 사과를 네 개씩이나 받은 뒤에 다음 일을 그만둔 셈이니 쓸 데 없이 힘을 낭비한 셈입니다. 아마도 이슬비는 사람 놀리냐고 화를 낼 지도 모릅니다. 세 개까지만 받으라고 하지 왜 네 개까지 받은 뒤에 네 개는 필요없다고 하냐고 따질 지 모릅니다.
그러므로 쓸 데 없이 네 개씩 받게 해서 이슬비를 열받게 하지 말고 세 개까지만 받도록 프로그램을 짜는 것이 좋습니다. 다음과 같이 프로그램을 짠 뒤에 test0132.cpp로 저장하시기 바랍니다.

// test0132.cpp
// 변수 a에 4가 대입되지 않고 출력이 끝남

#include

void main(void)
{
int a;
for(a=0;a<3;a++,printf(" a= %d \n",a));
}


**그림: test0132.cpp의 소스파일 내용

이 프로그램을 실행하면 다음과 같은 결과가 화면에 출력될 겁니다.

a= 1
a= 2
a= 3


**그림: test0132.exe를 실행시켰을 때의 화면

어떻습니까? 앞서의 test013.cpp를 실행한 것과 같은 결과를 얻을 수 있습니다. 그러나 a에 4를 대입하지 않는다는 점에서 차이가 납니다. 이 프로그램을 분석해보겠습니다.

int a;

for(a=0;a<3;a++,printf(" a= %d \n",a));


첫번째 줄은 a라는 변수를 선언한 문장이니 넘어가겠습니다.
두번째 줄에서 a에 0을 대입했습니다. 이점이 중요합니다. test013.cpp에서는 a에 1을 대입했습니다. 그래서 1부터 하다보니 4를 받게 된 겁니다. 두 번째 줄 문장을 이슬비의 경우로 설명하면 이런 명령문이 됩니다.

'이슬비야! 너 바구니는 지금 비어있는데, 세 개보다 작은 갯수를 받을 때까지만 내가 시키는대로 하면 돼.' 그리고 나서 한강물이 이슬비한테 a++을 계산해서 이슬비 바구니에 한 개를 던져줍니다. 그리고는 지금 받은 것이 세 개보다 작으면 칠판에 이슬비가 받을 사과 갯수를 쓰라고 합니다. 이슬비는 '응 지금 한 개 받았어.' 하고 쓸 겁니다.

다시 한강물이 물어봅니다.

'이슬비야! 세 개보다 적으면 말해라.'

이슬비는 현재 한 개를 받았으므로 '응! 아직 세 개보다 적어!' 하고 말합니다. 그러면 한강물이 이번에는 두 개를 던져줍니다. 이슬비는 '응. 이번에는 두 개가 왔네.'하고 칠판에 두 개라고 적습니다.
다시 한강물이 물어봅니다.

'이슬비야! 세 개보다 적으면 말해라.'

이슬비는 현재 두 개를 받았으므로 '응! 아직 세 개보다 적어!' 하고 말합니다. 그러면 한강물이 이번에는 아까 던진 것에 하나를 더해서(a++) 세 개를 던져줍니다. 이슬비는 '응. 이번에는 세 개가 왔네.'하고 칠판에 세 개라고 적습니다.
다시 한강물이 물어봅니다.

'이슬비야! 세 개보다 적으면 말해라.'

이슬비가 조금 전에 한강물로부터 받은 것은 세 개입니다. 그러므로 이 장면에서 이슬비는 '어? 지금 받는 것이 세 개니까, 세 개보다 적지 않는데?'하고 대답할 겁니다. 그러면 한강물은 '그럼 더 던질 필요가 없구나'하고 for문을 끝낼 겁니다. 이렇게 하면 이슬비가 쓸 데 없이 무거운 사과를 네 개나 받을 필요가 없어지는 셈입니다.

그러니까 test013.cpp는 조금 생각 없이 짠 프로그램인 셈입니다. 루프를 한 번 더 돌린 셈이기 때문입니다. test0132.cpp처럼 짜야 좀더 경제적이고 효율적인 프로그램이 됩니다.

**요약: 같은 내용과 같은 결과를 보이는 프로그램이라 하더라도 어떤 방법을 사용할 것이냐에 따라서 프로그램의 효율성이 달라집니다. 가능한 루프를 적게 돌리는 프로그램으로 만드는 것이 경제적이고 효율적입니다.


3.1.4. '만약'이라는 가정을 활용하는 if 제어문


'만약에'라는 가정의 if문은 어떤 선택을 위한 조건문으로 사용하는 제어문입니다.

'만약에 이슬비가 가진 사과가 10개보다 많다면 열 명에게 하나 이상씩 나누어줄 수 있을텐데.' '만약에 이슬비가 가진 돈이 이 만 원이라면 둘이 만 원씩 나누어가지면 딱 알맞을텐데' 하는 생각을 할 수 있습니다. 이처럼 '만약에 ~라면 ~을 해라'는 생각은 프로그램 곳곳에서 사용될 수 있는 생각입니다.

'만약에 사용자가 1번을 누르면 1번 기능인 저장을 실행하고, 2번을 누르면 2번 기능인 출력을 실행하고, 3번을 누르면 3번 기능인 끝내기를 실행하라.' '만약에 사용자가 'y'라고 치면 파일을 지우고, 'n'이라고 치면 지우지 말고 으뜸메뉴으로 돌아가라' '만약에 사용자가 'y'라고 치면 프로그램을 끝내고, 아니면 다시 으뜸메뉴으로 돌아가라'와 같은 식으로 프로그램을 짜게될 겁니다. 프로그램을 짤 때는 '만약에 ~을 선택하면 ~기능을 실행하라'는 구조를 가장 많이 사용하게 됩니다. '만약에'라는 조건문이 없다면 프로그램을 제대로 만들기란 거의 불가능할 지도 모릅니다.

내용상으로는 세 가지로 구분되지만 실제로 사용하는 문장 형식은 다섯 가지로 구분합니다.

이 '만약에'라는 조건문에 해당하는 것이 if문입니다. if문은 어떤 구간의 반복을 제어하기 보다는 어떤 선택을 위한 조건문으로 더 많이 사용하는 제어문입니다. 사용형식은 아래와 같습니다.

가. 조건에 맞으면 활괄호 안의 명령문을 실행

if(조건)

{

함수 또는 명령어

}


나. 조건에 맞으면 바로 뒤에 따르는 명령문 실행

if(조건)

명령문 ;


다. 조건에 맞으면 활괄호 안의 명령문들을 실행

if(조건)

{

명령문;

...

}


라. 조건에 맞으면 바로 뒤의 명령문을 실행하고, 안맞으면 else 다음의 명령문 실행

if(조건식)

명령문;

else

명령문;


마. 조건에 맞으면 바로 뒤의 명령문을 실행하고, 안맞으면 다음번 조건에 맞는가 확인한 다음에 명령문 실행. 그래도 안맞으면 계속해서 다음번 조건식에 맞나 확인한 후 실행. 맞는 조건식이 하나도 없으면 else 뒤의 명령문을 실행

if(조건식)

명령문;

else if

명령문;

else if... -+ 이 구간을 여러번 반복해서 쓸 수 있음.

명령문... -+

else

명령문;


사용형식은 크게 다섯 가지로 구분되지만 실제 내용상의 사용형식은 세 가지 형식으로 구분됩니다. if만 사용된 문장은 '만약에 조건식에 맞다면 다음 명령어를 실행하라'는 뜻입니다.
if와 else를 사용하면 '만약에 조건식에 맞다면 if문 다음의 명령어를 실행하고, 안맞다면 else문 다음의 명령을 실행하라'는 뜻입니다.
if와 else if를 중간에 여러 차례 쓰고 마지막에 else를 사용한 문장은 '만약에 조건식에 맞다면 if문 다음의 명령어를 실행하고, 안맞다면 다음에 나오는 else if의 문장에서 제시하는 조건식을 차례대로 검사한 다음에 맞는 조건식이 있을 경우에는 해당 else if문 다음의 명령을 실행하라. 끝내 조건식에 맞는 경우가 없다면 마지막에 나오는 else문 다음의 명령어를 실행하라'는 뜻입니다.

**요약: if문은 '만약에'라는 내용으로 조건식을 만들고 싶을 때 사용하는 제어문으로 다음에 실행할 명령을 선택할 때 주로 사용하는 선택문입니다. if문은 크게 세 가지 형식으로 구분되는데 if만 사용한 형식, if와 else를 사용한 형식, if와 else if를 사용하고 마지막에
else를 사용한 형식입니다.

if문을 이용한 홀수와 짝수를 구별 프로그램

다음과 같은 내용을 test014.cpp 소스파일로 만들어 실행해보시기 바랍니다. 아래 소스파일은 짝수와 홀수를 구별해서 그 숫자가 짝수인지 홀수인지를 알려주는 프로그램입니다.

// test014.cpp
// 짝수와 홀수를 구별해서 그 숫자의 홀짝여부를 알려주는 프로그램

#include
#include

void main(void)
{
int a; // 정수형 변수 a를 선언

for(a=1;a<=4;a++)
{
if(a%2==0) // 만약 변수 a를 2로 나눈 나머지가 0이라면
cout[[" 숫자 "[[a[[" 는(은) 짝수입니다. \n"; // 짝수라고 출력
if(a%2==1) // 만약 변수 a를 2로 나눈 나머지가 1이라면
printf(" 숫자 %d 는(은) 홀수입니다. \n",a); // 홀수라고 출력
}
}


**그림: test014.cpp의 소스파일 내용

이 프로그램을 실행시키면 아래와 같은 내용이 출력될 겁니다.

1 는(은) 홀수입니다.
2 는(은) 짝수입니다.
3 는(은) 홀수입니다.
4 는(은) 짝수입니다.


**그림: test014.exe의 실행화면

%는 MOD연산자라고 하여 어떤 수를 나눈 나머지를 알려주는 연산자입니다.

어떻게 해서 이런 결과가 나오는지 프로그램을 분석해봅시다.

int a;


for(a=1;a<=4;a++)

{


여기까지는 그동안 배워왔으니 쉽게 알 수 있을 겁니다. 정수형 변수 a에 1을 대입하고 a가 4보다 작거나 같을 때까지 { }안의 명령문을 실행하는데, a를 하나씩 증가시켜간다는 뜻입니다. 그리고 {} 안의 명령문은 다음과 같습니다.

if(a%2==0)

cout[[" 숫자 "[[a[[" 는(은) 짝수입니다. \n";


if(a%2==0)에서 %는 MOD연산자라고 하는데 우리말로는 나머지연산자입니다. 그러니까 왼쪽의 수를 오른쪽의 수로 나누었을 때의 나머지를 알려주는 연산자입니다. 주의할 점은 %d 기호에서 사용했던 대입연산자 %와 모양은 같지만 사용법은 다르다는 점입니다. 둘을 구별하는 방법은 어떤 문장에서 사용되었는가로 구분합니다. "" 안에 %를 썼으면 %d나 %s, %f, %%와 같은 방법으로 썼을 것이고, 나머지연산자로 사용했다면 어떤 수식 안에 %만 달랑 하나 썼을 겁니다.
이 문장에서는 a라는 변수를 2로 나눈 것이 0일 때는 짝수라는 문장을 출력하라는 뜻입니다. 2로 나누었을 때 나머지가 0이라면 짝수라는 것이야 더 이상 설명할 필요가 없겠죠.

if(a%2==1)

printf(" 숫자 %d 는(은) 홀수입니다. \n",a);

}


이번에는 a를 2로 나눈 나머지가 1일 때는 홀수라고 출력하라는 뜻입니다. 이렇게 해서 어떤 숫자의 짝수와 홀수 여부를 알아내 화면에 출력해주는 겁니다.
한강물이 이슬비에게 이렇게 부탁합니다.
'너가 가진 숫자를 2로 나누어서 나머지가 0이면 짝수라고 적고, 2로 나눈 나머지가 1이면 홀수라고 적어라'
이 내용을 if문으로 표현한 것이 바로 위의 보기입니다.

**요약: %기호만 하나 수식에서 사용하면 나머지연산자로 사용하는 것인데, % 기호의 왼쪽에 위치한 수를 오른쪽의 수로 나누었을 때 남는 나머지를 돌려주는 연산자입니다.


if문만 사용하는 것보다는 else문을 함께 쓸 때 더 간결해집니다.

그러나 이 문장을 else문과 함께 쓰면 다음과 같이 좀더 간단하게 고칠 수 있습니다. 다음 파일은 test015.cpp라고 저장하시기 바랍니다.

// test015.cpp
// if와 else문을 이용해 숫자의 홀짝여부를 알려주는 프로그램

#include
#include

void main(void)
{
int a;

for(a=1;a<=4;a++)
if(a%2==0) // 만약 변수 a를 2로 나눈 나머지가 0이라면
cout[[" 숫자 "[[a[[" 는(은) 짝수입니다. \n"; // 짝수라고 출력
else // 짝수가 아니라면
printf(" 숫자 %d 는(은) 홀수입니다. \n",a); // 홀수라고 출력
}


**그림: test015.cpp의 소스파일 내용


이 프로그램을 실행시켜도 결과는 앞서의 test014.cpp와 똑 같이 나올 겁니다. 그러나 test015.cpp가 좀더 간단하고 보기 깔끔해보일 겁니다.

if(a%2==0)

cout[[" 숫자 "[[a[[" 는(은) 짝수입니다. \n";

else

printf(" 숫자 %d 는(은) 홀수입니다. \n",a);


위의 문장은 대충 봐도 무슨 뜻인지 알 수 있을 겁니다. 만약 a를 2로 나눈 나머지가 0이면 짝수라고 화면에 출력하고, 아니면(else) 홀수라고 출력하라는 뜻입니다. a를 2로 나눈 나머지가 0이면 짝수일테고, 짝수가 아니면 홀수인 것은 뻔한 일이죠.

한강물이 이슬비에게 이렇게 부탁합니다.
'너가 가진 숫자를 2로 나누어서 나머지가 0이면 짝수라고 적고, 나머지가 0이 아니면 홀수라고 적어라'
이 내용을 if문으로 표현한 것이 바로 위의 보기입니다. 앞서의 보기에서는 '나머지가 1이면 홀수라고 적어라' 하고 부탁했지만, 이번에는 '나머지가 0이 아니면(else) 홀수라고 적어라'하고 부탁하는 겁니다.


**그림: test015.exe의 실행화면은 test014.exe와 같습니다.

**요약: '만약에 ~이면 ~을 실행하고, 아니면 ~을 실행하라'는 제어문을 작성하고 싶을 때는 if문과 else문을 함께 사용하면 됩니다.


[[연습문제]]
test015.cpp를 고쳐서 ex11.cpp로 저장합니다.
앞서 배운 scanf() 함수를 이용하여 정수형 숫자를 입력받고, 입력받은 숫자가 홀수인지 짝수인지 알려주도록 합니다. 제어문으로는 if else 문을 사용합니다.

[[연습문제 정답]]

// EX11.CPP -- if else문을 이용하여 홀짝 여부 알려주기

#include
#include

void main(void)
{
int a;
printf("INput Number: "); // 숫자를 입력하라는 안내문을 화면에 출력
scanf("%d",&a); // 숫자를 입력받아서 변수 a에 저장
if(a%2==0) // 만약 변수 a를 2로 나눈 나머지가 0이라면
cout[[" 숫자 "[[a[[" 는(은) 짝수입니다. \n"; // 짝수라고 출력
else // 짝수가 아니라면
printf(" 숫자 %d 는(은) 홀수입니다. \n",a); // 홀수라고 출력
}

if와 else if와 else문을 함께 사용하는 제어문의 사용 보기

그러나 '만약에'라는 말이 여러 번 들어가야 한다면 어떻게 해야 할까요? 이런 식으로 부탁을 한다고 합시다.

만약에 이슬비가 가진 숫자를 4로 나눈 나머지가 0이라면 이슬비가 가진 숫자는 4의 배수라고 적는다.
만약에 이슬비가 가진 숫자를 4로 나눈 나머지가 1이라면 4의 배수가 아니라고 적는다.
만약에 이슬비가 가진 숫자를 4로 나눈 나머지가 2라면 4의 배수가 아니라고 적는다.
만약에 이슬비가 가진 숫자를 4로 나눈 나머지가 3이라면 나머지는 3이라고 적는다.

'만약에 이슬비가 가진 숫자를 4로 나눈 나머지가..' 라는 말이 계속 나오니까 아주 지겹습니다. 듣는 사람도 보는 사람도 지겹지만 말하는 사람도 힘들 겁니다. 그래서 이를 좀더 다음과 같이 고치면 좀더 깔끔한 문장이 될 겁니다.

만약에 이슬비가 가진 숫자를 4로 나눈 나머지가 0이라면 이슬비가 가진 숫자는 4의 배수라고 적고,
그게 아니고 나머지가 1이라면 4의 배수가 아니라고 적고,
그게 아니고 나머지가 2라면 4의 배수가 아니라고 적고,
그게 아니고 나머지가 3이라면 나머지는 3이라고 적는다.

어떻습니까? 아무래도 한결 보기가 좋고, 명령문의 내용을 파악하기도 한결 쉽죠? 이렇게 선택해야 할 조건식이 많을 경우에는 else if 문을 많이 사용합니다.

else if문을 이용해 4의 배수와 나머지 알려주기

아래의 문장대로 입력하고 test016.cpp로 실행시켜 보기 바랍니다.

// test016.cpp
// else if문을 이용해 4의 배수와 나머지 알려주기

#include
#include

void main(void)
{
int a;

for(a=1;a<=10;a++)
if(a%4==0) // a를 4로 나눈 나머지가 0이라면
cout[[" 숫자 "[[a[[" 은(는) 4의 배수입니다. \n"; // 4의 배수라고 출력
else if(a%4==1) // a를 4로 나눈 나머지가 1이라면
cout[[" 숫자 "[[a[[" 은(는) 4의 배수가 아닙니다. \n";
else if(a%4==2) // a를 4로 나눈 나머지가 2라면
cout[[" 숫자 "[[a[[" 은(는) 4의 배수가 아닙니다. \n";
else // 그외의 경우라면
printf(" 숫자 %d 의 나머지는 3입니다.\n",a);
}


**그림: test016.cpp의 소스파일 내용

이 프로그램을 실행시키면 화면에 다음과 같은 내용이 출력될 겁니다.

숫자 1 은(는) 4의 배수가 아닙니다.
숫자 2 은(는) 4의 배수가 아닙니다.
숫자 3 의 나머지는 3입니다.
숫자 4 은(는) 4의 배수입니다.
숫자 5 은(는) 4의 배수가 아닙니다.
숫자 6 은(는) 4의 배수가 아닙니다.
숫자 7 의 나머지는 3입니다.
숫자 8 은(는) 4의 배수입니다.
숫자 9 은(는) 4의 배수가 아닙니다.
숫자 10 은(는) 4의 배수가 아닙니다.


**그림: test016.exe를 실행시켰을 때의 화면

어떻게 해서 이런 문장이 나왔는지 살펴봅시다.

int a;


for(a=1;a<=10;a++)


정수형 변수 a에 1을 대입해서 a가 10이 될 때까지 다음 문장을 반복하라는 명령문입니다. 루프를 한 번 돌 때마다 a는 하나씩 증가합니다.

이슬비에게 처음에 숫자 1이 적힌 종이를 주고, 다음에는 1이 증가한 숫자를 적어서 줍니다. 그렇게 해서 숫자에 적힌 종이가 10보다 작거나 같을 때까지 for문에 딸린 명령문을 반복한다는 뜻입니다.

if(a%4==0)

cout[[" 숫자 "[[a[[" 은(는) 4의 배수입니다. \n";


만약 a를 4로 나눈 나머지가 0이라면 4의 배수라고 화면에 출력하라는 뜻입니다.

else if(a%4==1)

cout[[" 숫자 "[[a[[" 은(는) 4의 배수가 아닙니다. \n";


else if라는 문장은 else(~이 아니라면)와 if(만약에~라면)라는 문장이 합쳐진 것이므로 '~이 아니고 만약에 ~라면'의 뜻을 지니고 있습니다.

그러니까 첫번째 if문에서 'a를 4로 나눈 나머지가 0이 아니라면'의 조건이 먼저 만족되어야 합니다. 그리고 나서 만약에 a를 4로 나눈 나머지가 1이라면 4의 배수가 아니라고 출력하라는 명령문입니다. 만약에 앞의 if문에서 조건을 만족해서 나머지가 0이었다면 그 이후의 else문이나 else if문은 실행할 필요가 없는 셈입니다. else가 지닌 뜻은 '~이 아니라면'의 뜻을 지니고 있으니까요.

else if(a%4==2)

cout[[" 숫자 "[[a[[" 은(는) 4의 배수가 아닙니다. \n";


만약에 a를 4로 나눈 나머지가 2라면 역시 4의 배수가 아니라고 출력하라는 명령문입니다.

else

printf(" 숫자 %d 의 나머지는 3입니다.\n",a);


앞서의 세 개 조건도 맞지 않는다면 즉, 4를 나눈 나머지가 0도 아니고, 1도 아니고, 2도 아니라면 나머지는 3만 남습니다. 이때는 나머지가 3이라고 화면에 출력하라는 뜻입니다.

그래서 1과 2는 4의 배수가 아니라는 말이 출력되었고, 3은 나머지가 3이라고 나왔고, 4는 4의 배수라고 출력된 겁니다. 이제 if문의 사용법은 대충 익히신 셈입니다.

좀더 짜임새 있는 else if 문의 사용법

사실 test016.cpp의 보기는 매우 엉성한 프로그램입니다. 실제로는 if문을 test016.cpp처럼 사용하면 안됩니다. a%4==1이라는 수식을 else if문의 괄호 안에 넣는 것은 좋지 않습니다. if문 안에는 연산과정이 들어가지 않는 것이 좋습니다. 즉 a%4나 a-4와 같은 연산식이 들어가는 방식으로 짜는 것은 문제가 발생할 수 있습니다.
그래서 test016.cpp처럼 else if문을 사용하는 경우는 없습니다. if문은 보통 등식이나 부등식으로 비교할 때 주로 사용합니다. 따라서 아래와 같이 프로그램을 짜는 것이 if문을 올바르게 사용하는 프로그램입니다. 아래의 프로그램을 test0162.cpp로 저장해서 실행시키기 바랍니다.

// test0162.cpp
// else if문을 이용해 4의 배수와 나머지 알려주기

#include
#include

void main(void)
{
int a,b; // 변수를 2개 선언합니다

for(a=1,b=1;a<=10;a++,b=a%4) // a에 1을 더하고, a를 4로 나눈 나머지를 b에 대입
{
if(b==0) // 변수 b가 0이라면
cout[[" 숫자 "[[a[[" 은(는) 4의 배수입니다. \n"; // 4의 배수라고 출력
else if(b==1) // 변수 b가 1이라면
cout[[" 숫자 "[[a[[" 은(는) 4의 배수가 아닙니다. \n";
else if(b==2) // 변수 b가 2라면
cout[[" 숫자 "[[a[[" 은(는) 4의 배수가 아닙니다. \n";
else // 변수 b가 0도 1도 2도 아니라면
printf(" 숫자 %d 의 나머지는 3입니다.\n",a);

}
}


**그림: test0162.cpp의 소스파일 내용


프로그램을 실행시킨 결과는 test016.cpp를 실행시켰을 때와 같습니다. 그러나 이렇게 바꾸면 문장이 자연스럽습니다. 변수 b에 a를 4로 나눈 나머지를 대입시킨 후에, b가 0이면 4의 배수라고 출력하고, b가 1이면 4의 배수가 아니라고 출력하고, b가 2면 4의 배수가 아니라고 출력하고, 그외의 경우에는 나머지가 3이라고 출력하라는 뜻입니다. test016.cpp보다 훨씬 자연스럽고 부드럽습니다.

같은 if문이라 하더라도 이렇게 뭔가 말이 되는 것이 있고 말이 안되는 문장을 짤 수 있습니다. 비록 결과는 같지만 과정은 분명히 다릅니다. 그리고 이런 과정이 뭔가 자연스럽지 않으면 어디선가 문제를 일으킵니다. 그래서 결과가 같다고 해서 두 개의 프로그램을 같은 프로그램으로 생각하지 않습니다. 안의 프로그램 내용이 얼마나 합리적으로 구조적이고, 논리적으로 이상이 없는가를 판단해서 좋은 프로그램과 나쁜 프로그램을 구별하는 겁니다.


**그림: test0162.exe의 실행결과는 test016.exe와 같습니다.

**요약: if문을 이용한 조건식이 여러 개일 때는 if문과 else if문을 반복해서 사용하면 됩니다. if문안에는 참거짓만 판별하는 조건식만 사용하는 것이 좋으며, 연산과정이 들어가는 조건식은 가능한 피하는 것이 좋습니다.


[[연습문제]]
다음의 내용대로 실행되도록 소스파일을 만들고 ex12.cpp로 저장합니다.
이번에는 입력객체인 cin 명령어를 이용하여 정수형 정수형 숫자를 입력받습니다. 입력받은 숫자가 3의 배수라면 3의 배수라고 알려주고, 3의 배수가 아니라면 나머지가 몇 인지 알려주도록 합니다. 변수로는 a, b 두 개를 사용하고 제어문으로는 else if문을 사용합니다.

[[연습문제 정답]]

// EX12.CPP -- else if문을 이용하여 3의 배수와 나머지 여부 알려주기

#include
#include

void main(void)
{
int a, b;
cout[["INput Number: "; // 숫자를 입력하라고 안내문을 보여줌
cin]]a; // 입력객체인 cin을 사용하여 숫자를 입력받아 a에 저장
b=a%3; //a를 3으로 나눈 나머지를 b에 저장
if(b==0) // 변수 b가 0이라면
cout[[" 숫자 "[[a[[" 은(는) 3의 배수입니다. \n"; // 3의 배수라고 출력
else if(b==1) // 변수 b가 1이라면
cout[[" 숫자 "[[a[[" 을 3으로 나눈 나머지는 1입니다. \n";
else // 변수 b가 0도 1도 아니라면
cout[[" 숫자 "[[a[[" 을 3으로 나눈 나머지는 2입니다. \n";
}
}


3.1.5. 일단 한 번은 실행하는 do while 제어문


do while문은 일단 한 번은 실행된다는 점에서 while문과 다릅니다.

do while 제어문은 while문과 사실상 거의 차이가 없습니다. 그러나 단지 한 가지 차이가 있다면 while문은 조건식을 만족하지 않을 경우 한 번도 실행하지 못하고 끝나는 반면, do while문은 적어도 한 번은 일단 실행한다는 점입니다. 왜냐하면 조건식이 명령문의 뒤에 있기 때문입니다. 그래서 일단 한 번은 명령문을 실행한 다음에 조건식이 맞으면 루프를 벗어나는 제어문입니다.

예를 들어서 while(a<10)이라는 식으로 사용하므로 조건을 앞에 겁니다. 그래서 이슬비에게 사과를 20개 주고 이슬비가 가진 사과가 20개보다 작으면 칠판에 갯수를 쓰라고 명령했다고 합시다. 이 경우 이슬비는 20개의 사과를 가지고 있으므로 while문 뒤에 딸린 명령문을 아예 실행하지 않습니다. 칠판에 갯수를 쓸 일이 없는 셈이죠. 그러나 do while문은 조건식이 뒤에 옵니다.

사용형식은 다음과 같습니다.

do {

명령문;

...

} while(조건식);


또는 다음과 같습니다.

do 명령문;

while (조건식);


예제파일을 아래와 같이 작성해서 test017.cpp로 저장해서 실행시키기 바랍니다.

// test017.cpp
// do while문의 사용 예제

#include
#include

void main(void)
{
int a=10; // 변수 a의 내용을 10으로 초기화시킴

do{
cout[[" a="[[a[[" \n"; // a의 값이 10을 출력해줌
}while(a<3); // a가 3보다 크므로 do while문을 벗어남

a=1; // a를 다시 1로 초기화시킴

do printf(" a=%d \n",a),a++; // a를 출력해주고 a에 1씩 더함
while(a<3); // a가 3보다 작을 동안 반복함
}


**그림: test017.cpp 소스파일의 내용

이제는 대충 출력결과를 짐작하실 수 있을리라 생각합니다. 프로그램의 실행결과는 아래와 같을 겁니다.

a=10
a=1
a=2


**그림: test017.exe를 실행시켰을 때 나오는 화면

예제 프로그램을 살펴보도록 하겠습니다.

int a=10;


정수형 변수 a를 선언하고 10을 대입시켰습니다.

do{


do while문의 시작을 알리는 문장입니다. { 기호로 명령문이 든 do while 제어문의 본체가 시작됩니다.

cout[[" a="[[a[[" \n";


a의 값을 화면에 출력합니다. 아직 조건식이 나오지 않았으므로 a의 값인 10을 화면에 출력합니다.

}while(a<3);


이제서야 조건식이 나옵니다. a가 3보다 작을 때만 do while문의 내용을 실행하라는 뜻입니다. 현재 a의 값이 10이므로 do while문을 다시 실행할 필요가 없습니다. 그러나 조건식이 나오기 전에 일단 printf() 함수를 한 번 실행시켰습니다. 이 점이 while문과 do while문의 차이입니다. while문은 조건이 거짓이면 한 번도 실행되지 않지만, do while문은 적어도 한 번은 실행한다는 점이 다릅니다.
첫번째 do while문은 {} 기호 안에 명령문을 넣었습니다. 두번째 do while문은 복문기호 안에 명령문을 넣지 않고 한 줄 짜리 명령문으로 처리한 보기입니다.

a=1;


a라는 변수에 이번에는 1이라는 값을 대입했습니다. 따라서 a는 10에서 1의 값을 가지게 됩니다.

do printf(" a=%d \n",a),a++;


화면으로 a의 값을 출력하라는 명령과 a++이라는 명령을 함께 주었습니다. 두 명령문 사이는 쉼표(,)로 구별했습니다. 이때 do 다음의 명령문 끝에 ; 기호를 넣어서 do 명령어의 끝임을 알려주어야 합니다.

while(a<3);


a가 3보다 작을 때까지 하라는 뜻이죠. 따라서 a++ 연산에 의해서 a가 3이 되면 do while문을 빠져나옵니다. 그래서 3은 화면에 출력 안하고 1과 2만 화면에 출력된 것입니다.

**요약: do while문은 일단 while이라는 조건식을 만나기 전에 do 다음의 명령문을 한 번은 무조건 실행한다는 점에서 먼저 조건식을 따져보고 실행 여부를 결정하는 while문과 다릅니다. 따라서 한 번은 먼저 실행해야 하는 경우에 do while문을 사용합니다.


[[연습문제]]
다음의 내용대로 실행되도록 소스파일을 만들고 ex13.cpp로 저장합니다.
1의 2제곱부터 10의 2제곱까지 계산하여 보여줍니다. 제어문으로는 do while 문을 사용하고 정수형 변수 a만 사용합니다.

[[연습문제 정답]]

// EX13.CPP -- do while문을 이용하여 1부터 10까지의 2제곱 알려주기

#include
#include

void main(void)
{
int a=1; // 변수 a의 내용을 1로 초기화시킴
do printf(" %d의 2제곱은 %d \n",a,a*a),a++; // a와 a*a를 출력해주고 a에 1씩 더함
while(a<11); // a가 11보다 작을 동안 반복함
}

3.1.6. 여러 개 중에서 하나를 고르는 switch문


switch문은 여러 개의 조건 중에서 참인 조건식의 명령문만 실행

switch문은 여러 개의 조건 중에서 만족하는 하나를 택해서 명령문을 실행하는 제어문입니다. if else문과 비슷하다고 할 수 있습니다. 다만 if else문은 첫번째 if 문부터 차례대로 검사를 해가면서 조건식에 맞는 것이 나올 때마다 실행하는데 비해서 switch문은 여러 개의 case 중에서 하나의 case만 사용한다는 점이 다릅니다.

그러니까 이슬비가 가진 사과의 갯수가 한 개면 무엇을 실행하고, 2개면 무엇을 실행하고, 3개면 무슨 기능을 수행하라고 할 때 switch문을 사용합니다.

사용형식은 다음과 같습니다.

swhitch(선택변수){

case 변수값1:

명령문;

...

case 변수값2:

명령문;

...

default:

명령문;

...

}


switch문을 사용한 프로그램을 만들어봅니다.

다음과 같은 내용을 test018.cpp로 저장한 뒤에 실행시켜 보기 바랍니다.

// test018.cpp
// switch문의 사용 예제

#include
#include

void main(void)
{ int a=2;
switch(a){ // switch문의 변수로 a를 지정
case 1: // 변수 a의 값이 1인 경우에만
cout[[" a is 1 \n";
break; // switch문을 빠져나감
case 2: // 변수 a의 값이 2인 경우에만
cout[[" a is 2 \n";
break;
default: // 변수 a의 값이 1도 아니고 2도 아닌 모든 경우에
printf(" a is ?\n");
break;
}
}


**그림: test018.cpp의 소스파일 내용

test018.exe를 실행하면 다음과 같은 글씨가 화면에 출력될 겁니다.

a is 2


**그림: test018.exe를 실행시켰을 때 나오는 화면

그럼 test018.cpp를 하나씩 다시 살펴봅시다.

{ int a=2;


정수형 변수 a를 선언하면서 2라는 값을 대입했습니다. 이제 변수의 선언부분은 지겨울 정도로 했으니 보기만 해도 이해가 될 것으로 생각합니다.

switch문에서는 변수 자체가 조건식이 됩니다.


switch(a){



switch문의 시작입니다. 스위치문의 선택변수로 a를 대입했습니다. 즉 a의 값 자체가 switch문의 조건을 판단하는 조건식으로 사용되는 것입니다.

: 기호는 라벨 기호로 case문의 개별 이름을 표시합니다.


case 1:

cout[[" a is 1 \n";

break;


switch문에 대입한 변수 a의 값이 1일 경우에는 'a is 1'이라는 문장을 보여주고 switch문을 벗어나라는 명령문입니다. case 1이라는 문장 뒤에 : 기호가 붙어 있음을 눈여겨 보셔야 합니다. : 기호를 통해서 case 1이라는 조건식이 끝났음을 알리기 때문입니다. : 기호는 라벨명이라고 하므로, case 1: 은 case 1이라는 이름을 가진 라벨이 되는 겁니다. a의 값이 2이므로 case 1 이라는 조건식에 해당하지 않습니다. 그래서 case 1: 라벨 밑에 적힌 명령문은 실행되지 않습니다.

break 명령문은 제어문의 루프를 탈출하라는 명령어입니다.


case 2:

cout[[" a is 2 \n";

break;


switch문에 대입한 변수 a의 값이 2일 경우에는 'a is 2'이라는 문장을 보여주고 switch문을 벗어나라는 명령문입니다. 현재 a의 값이 2이므로 case 2: 라벨 밑의 문장이 실행됩니다.

break; 명령문은 현재의 제어문을 벗어나라는 말입니다. 즉 case 2: 를 포함하고 있는 제어문인 switch문을 벗어나라는 뜻입니다.

default:

printf(" a is ?\n");

break;


switch문에 대입한 변수 a의 값이 위에서 내건 case문에 해당되지 않을 경우에는 default문 다음의 명령어를 실행합니다. 다시 말해 a의 값이 1도 2도 아닐 경우 즉, 아무 case에도 해당하지 않을 경우에는 default문을 실행합니다. 만약 default문도 없다면 switch문은 아무 것도 실행하지 않을 겁니다. case 2: 가 실행되었으므로 여기서는 default문이 실행되지 않습니다.

}


switch문의 끝을 알리는 닫기 괄호입니다. test018.cpp에서 새롭게 등장한 문법은 break라는 명령문입니다. break라는 명령문은 현재 진행중인 제어문의 루프를 탈출하라는 명령문입니다. switch문까지 배웠으니 기본적인 제어문의 사용법을 대충 다 배운 셈입니다.

이를 다시 이슬비의 학습내용으로 비교하겠습니다. 이슬비가 가진 돈이 만 원이라고 합시다. 그러면 a=10000이 될 겁니다. 엄마는 switch문을 통해서 이렇게 명령을 내릴 수 있습니다.
이슬비가 가진 돈(a)이 천 원이면 두부를 사오고, 오천원이면 돼지고기를 한 근 사오고, 만원이면 햄을 사오고, 이상의 조건에 해당되지 않으면 그냥 집으로 돌아오라고 명령을 내릴 수 있습니다.
case 1000: 이라고 쓰면 'a의 값이 1000일 때'라는 조건식이 됩니다. case 2000:이라고 하면 a의 값이 2000이라는 조건식이 됩니다.

이제 지금까지의 과정을 통해서 기본적인 제어문의 종류는 다 배우셨습니다. 물론 이들 제어문의 사용법은 이보다 더욱 복잡합니다. 제어문 안에 제어문을 내포해서 사용할 수도 있습니다. 제어문의 중첩사용법이라는 것이 제어문 안에 제어문을 넣어서 사용하는 방법을 말합니다. 좀더 복잡한 사용법은 다음에 낼 책에서 다시 세세하게 설명드리도록 하겠습니다.

**요약: switch문은 여러 개의 조건 중에서 하나만을 선택할 때 주로 사용하는 제어문으로 'case 변수:'의 형식을 가진 case 라벨이름을 이용합니다. switch문 중에서 조건식이 맞는 case가 있어 명령이 실행되면 나머지 case문 부분은 실행되지 않습니다. 여러 개의
case 중에서 조건식에 맞는 것이 없을 경우에는 default 문 다음의 명령문이 실행되는데 default조차 없을 경우에는 아무 것도 실행되지 않고 switch문을 끝냅니다. 그리고 switch문을 중간에 탈출할 때는 break라는 명령어를 이용합니다.

[[연습문제]]
다음의 내용대로 실행되도록 소스파일을 만들고 ex14.cpp로 저장합니다.
정수형 변수를 입력받은 뒤에 3의 배수인지 알려줍니다. 3의 배수가 아니라면 나머지를 알려줍니다. 제어문으로는 switch 문을 사용하고 정수형 변수 a, b를 이용합니다.

[[연습문제 정답]]

// EX14.CPP -- switch문을 이용하여 3의 배수 알려주기

#include
#include

void main(void)
{
int a, b;
cout[["INput Number: "; // 숫자를 입력하라고 안내문을 보여줌
cin]]a; // 입력객체인 cin을 사용하여 숫자를 입력받아 a에 저장
b=a%3; //a를 3으로 나눈 나머지를 b에 저장
switch(b){ // switch문의 변수로 b를 지정
case 0: // 변수 b의 값이 0인 경우
cout[[" 숫자 "[[a[[" 은(는) 3의 배수입니다. \n"; // 3의 배수라고 출력
break; // switch문을 빠져나감
case 1: // 변수 b의 값이 1인 경우에
cout[[" 숫자 "[[a[[" 을 3으로 나눈 나머지는 1입니다. \n";
break;
default: // 나머지가 0도 1도 아닌 경우
cout[[" 숫자 "[[a[[" 을 3으로 나눈 나머지는 2입니다. \n";
break;
}
}


3.1.7. 무한루프와 루프를 탈출하는 방법


제어문의 무한루프에서 중간에 벗어나기 위해서 탈출문을 사용합니다.

제어문을 잘못 사용하면 평생 같은 동작을 반복하다가 빠져나오지 못하는 경우가 있는데 이를 무한루프에 빠졌다고 합니다. 프로그램의 논리적 오류에 의해서 이런 일이 생깁니다. 쉽게 말해서 프로그램을 잘못 짰다는 이야기입니다. 어떤 경우에 무한루프에 빠지는지 한 번 검토해보도록 하겠습니다.

다음과 같은 문장이 있다고 합시다.

int a=1;

while(a<5) printf(" a=%d \n", a);


이럴 경우 이 프로그램은 무한루프에 빠집니다. 먼저 a=1이라고 대입했습니다. 그리고 a가 5보다 작으면 while 뒤의 명령문을 계속해서 반복하게 되어 있습니다. while 뒤의 명령문은 변수 a의 내용을 출력하라는 뜻입니다. 그런데 a의 값을 변화시키는 내용이 없습니다. 그래서 여전히 a=1입니다. 그러니 또 다시 while문의 루프를 반복해야 합니다. 결국 이 프로그램은 누군가 컴퓨터를 끄거나 특별한 조치를 통해서 제어문을 벗어나게 하기 전까지는 'a=1'이라는 문장만 계속해서 보여주는 프로그램이 되고 맙니다.

물론 이렇게 프로그램을 짜는 것은 프로그램을 짜는 사람의 실수나 잘못이므로 프로그램을 제대로 짜면 이를 방지할 수 있지만, 경우에 따라서는 무한루프를 이용해야 하는 경우도 있습니다. 그러나 무한루프에 빠져서는 안되고.

시계 프로그램의 경우 대표적입니다. 예를 들어서 컴퓨터 시간을 계속 검사해서 시간을 표시하는 프로그램을 무한 루프로 돌립니다. 별일이 없는 이상 이 프로그램은 무한루프를 돌면서 계속 시간을 표시해주는 것이 일입니다. 그러다가 프로그램을 끝내라거나 지정된 알람시간이 되어 다른 일을 해야할 경우에는 무한루프를 벗어나야 합니다. 이럴 때 사용하는 명령문이 탈출문이라 할 수 있는 명령문들입니다.

'이슬비야. 너가 가진 숫자가 1이면 칠판에 1이라고 써라.'
이렇게 명령을 해놓고는 이슬비에게 계속 1을 준다고 합시다. 그럼 이슬비는 하염 없이 칠판에 1만 쓰느라고 팔이 아플 겁니다. 이럴 때는 그만 써도 된다는 명령을 줘야 합니다.
'1을 가지고 있어도 팔 아프다고 생각되면 그만 써라.'하는 명령을 주어야 합니다. 이런 명령문이 바로 루프로부터 탈출하는 탈출문입니다.

탈출문에는 break, continue, goto 문등이 사용됩니다.

탈출문으로 사용할 수 있는 명령문은 다음과 같은 것이 있습니다.

break 명령문


앞서 switch문을 탈출할 때 한 번 사용했기 때문에 쉽게 이해할 수 있을 겁니다. 프로그램이 이 문장을 만나면 현재의 제어문을 벗어나는 동작을 합니다. 이때 break는 현재의 제어문만 벗어날 뿐 그보다 한 단 계 위의 제어문은 벗어나지 않습니다. 즉 제어문 안에 제어문이 내포되어 있을 경우에 현재 단계의 제어문만 벗어난다는 뜻입니다. 가장 많이 사용하는 탈출명령문입니다.

continue 명령문


프로그램이 이 명령을 만나면 현재 진행중인 루프 제어문의 나머지 명령문을 진행하지 않고 다시 처음으로 돌아가 반복하도록 해줍니다. 그러니까 만약 while제어문에 포함된 명령문을 1, 2, 3번 줄까지 실행하다가 continue를 만나면 4, 5번 줄의 명령문은 실행하지 않고 다시 1번 줄로 돌아가도록 해줍니다. break 문처럼 현재의 루프를 빠져나가지 않는다는 점이 특징입니다. 주로 if else문을 사용할 때 많이 사용하는 제어문입니다.

goto 명령문


goto 명령문은 갑자기 어디로 펄쩍 뛰어 이동할 때 사용합니다. goto 명령을 사용하면 goto 명령 뒤에 적는 라벨이름이 있는 곳으로 이동하는데 라벨이름은 프로그램 중에서 원하는 장소 아무 곳에나 배치시킬 수 있습니다. 따라서 가장 사용하기 편한 이동명령어입니다. 그러나 C++언어의 구조적인 프로그램을 망치는 명령문이기 때문에 C++언어에서는 아주 특수한 상황이 아니라면 쓰는 것을 금지시키고 있습니다. 그러나 BASIC 등의 다른 언어를 사용하던 습관이 붙은 사람을 위해서 마련한 명령문일 뿐입니다. 가능하면 goto 명령문을 쓰지 않도록 하는 것이 좋습니다. 이동할 라벨은 라벨이름 뒤에 : 기호가 붙어 있으면 됩니다.
예를 들면 다음과 같이 사용할 수 있습니다.

if(a==3) // 만약 a의 값이 3이면
goto game; // game:이라는 라벨 부분으로 이동하라
else // 아니면
cout[[" a="[[a[[" \n"; // a의 값을 출력하라

game : printf("This is game label. \n"); // game 라벨문 부분

**요약: 제어문을 중간에 벗어날 때 사용하는 명령문을 탈출문이라고 부르는데 break, continue, goto 명령어가 주로 사용됩니다. break문은 현재의 루프만 벗어나 한 단계 위로 벗어나며, continue문은 뒤의 명령을 실행 안하고 다시 처음으로 이동하며, goto문은 가고
싶은 라벨로 바로 이동할 수 있습니다. goto문은 구조적인 프로그램을 짜는 C++언어의 특성에 적합하지 않으므로 가능하면 사용을 자제해야 합니다.




첫줄로(go top, go first line) 문화원첫화면으로(go dal site home) 강좌차림으로(go Chair) 사이트맵으로(go sitemap)




total chairpost