Chapter 09 반복문
printf("1에서 10까지의 합은 %d 입니다.\n", sum); 일정한 문장의 반복 여러 줄의 동일한 패턴의 출력 출력문 printf()를 이용하여 문자 *(asterrisk)를 다음과 같이 출력하는 프로그램을 작성한다면 여러 줄의 printf()가 필요 ****** 만일 100줄의 출력이 필요하다면 이 보다 더 길게 100줄에 걸쳐 계속해서 printf()를 써야 할 것인가? 1부터 n까지의 합 1부터 10까지 더하는 프로그램을 작성한다면 만일 1에서 100까지 합이라면, 아니 10000까지의 합이라면 어떻게 처리할 것인가? printf("*****\n"); sum = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10; printf("1에서 10까지의 합은 %d 입니다.\n", sum);
반복문 제어문 반복문 프로그램의 실행 순서는 “위에서 아래로 한 문장씩” 순차적으로 실행 이러한 순차적 실행을 변형한 구문을 제어문(control statement) 제어문에는 조건문(if 문, switch 문) , 반복문, break, continue, goto, return 문 등 반복문 프로그램에서는 일정한 규칙의 처리를 반복적으로 처리하는 모듈이 자주 필요, 이를 위한 구문이 반복문 일정한 규칙을 잘 찾아내 반복문 문법에 적절히 이용하면 간단한 프로그램 작성 가능 제어문의 한 종류가 반복문 반복 구문은 일정한 규칙을 반복하는 과정을 처리할 때 적절히 이용할 수 있는 문장 C 언어에서는 다음 세 가지의 반복문을 제공 for while do while문
반복 몸체를 1번은 실행하며, 검사부분이 뒤에 있음. 반복문 종류 3가지 구문 반복문의 종류 구문 특징 for for(초기화; 조건검사; 증감연산) { for문 몸체(body); }; 일정한 반복 횟수를 이용하는 반복문에 적합. while while(조건검사) while문 몸체(body); 구문이 간단하며, 검사부분이 처음에 있음. do while do do while문 몸체(body); } while(조검검사); 반복 몸체를 1번은 실행하며, 검사부분이 뒤에 있음.
for 문 반복문 for 구조 for 다음에 괄호() 부분이 초기화(Initilization), 조건검사(conditional expression), 증감연산(increment)의 세 부분으로 구성되고 이를 세미콜론(;) 으로 구분 for 문 내의 괄호와 괄호 내의 세미콜론은 반드시 필요하다. for 문의 괄호 내의 세 부분은 어떠한 문장이 나오지 않아도 문법 오류는 발생하지 않음 이 부분을 for 반복문의 몸체(body)라 하며 한 문장인 경우, 블록을 구성하지 않을 수 있다. for (초기화; 조건검사; 증감연산) { statement1; statement2; …. } for (초기화; 조건검사; 증감연산) statement1;
for 문 이해 for 문의 실행순서 초기화 부분은 무조건 한 번만 실행되고, 반복되는 구문은 2, 3, 4번 초기화 문장을 실행한다. 조건검사 문장이 참(0이 아닌 결과 값)이면 반복문의 몸체에 해당하는 문장을 실행한다. 그러나 조건검사 문장이 거짓이면 for 문을 종료한다. 몸체를 실행하면 증감연산 문장을 실행하고 검사한다. 다시 2번으로 돌아가 조건검사를 실행한다. 초기화 부분은 무조건 한 번만 실행되고, 반복되는 구문은 2, 3, 4번 1. 초기화 -> 2. 조건검사 -> 3. 몸체 -> 4. 증감연산
문자 *를 한 줄에 5개씩 5줄 출력 정수형 변수 i의 초기값을 0으로 지정해서 5보다 작을 때까지, 증감연산 부분에 증가자(i++)를 이용하여 출력문을 출력 증감연산 부분에는 반드시 증감연산자 만이 올 수 있는 것은 아니고, 원하는 어떠한 문장도 가능 printf("*****\n"); for (i = 0; i < 5; i++) { printf("*****\n"); } 실행순서 1 초기화 i=0 2 3 4 변수 i 값 검사 (i<5) 검사 결과 몸체실행 증감연산(i++) 0 < 5 1(참) printf("*****\n"); 0+1 1 < 5 1+1 2 < 5 2+1 3 < 5 3+1 4 < 5 4+1 5 5 < 5 0(거짓)
증감 부분의 이해 for 문의 증간연산 부분 그렇다면 아래 예문은 어떠한가? 물론이다. 증감연산 부분에서 i++를 i=i+1로 한 것은 프로그램 기능에 차이가 없다. 연산식 i++는 i=i+1을 의미하기 때문 그렇다면 아래 예문은 어떠한가? 위 예문도 같은 결과를 처리한다. 연산식 i++와 ++i는 연산식의 결과 값이 차이가 있을 뿐이고, 이 구문에서는 결과 값을 이용한 구문이 없이, i=i+1만을 이용하므로 위 프로그램의 증감연산 부분에 ++i, i++, i=i+1중에서 어느 것을 사용해도 같은 의미 for (i = 0; i < 5; i = i +1) { printf("*****\n"); } for (i = 0; i < 5; ++i) { printf("*****\n"); }
n까지의 합 1에서 10까지의 합을 구하는 for 문을 작성 이를 for 문으로 바꿔보자. 처음에 합이 저장될 변수 sum에 0을 대입하고, 반복 횟수에 대한 제한에 이용될 i를 1로 초기화한다. 조건검사는 10번을 반복해야 하므로 i<=10이고 증감연산은 i 값을 하나씩 증가하도록 i++로 구성 sum = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10; sum = 1; for (i = 0; i <= 10; i++) { sum += i; }
for 문이 반복되는 과정 sum = 0; for (i = 1; i <= 10; i++) { sum += i; } 실행순서 1 2 3 변수 i 값 검사 (i<=10) 검사 결과 몸체실행(sum+=i) (sum = sum + i) 증감연산(i++) (i = i+1) 1(초기 값) 1 <= 10 참 sum = 0+1 1+1 2 <= 10 sum = 0+1+2 2+1 3 <= 10 sum = 0+1+2+3 3+1 4 4 <= 10 sum = 0+ … +4 4+1 5 5 <= 10 sum = 0+ … +5 5+1 6 6 <= 10 sum = 0+ … +6 6+1 7 7 <= 10 sum = 0+ … +7 7+1 8 8 <= 10 sum = 0+ … +8 8+1 9 9 <= 10 sum = 0+ … +9 9+1 10 10 <= 10 sum = 0+ … +10 10+1 11 11 <= 10 거짓
예제 소스 multiprint.c 구현 한 줄에 별표(*) 다섯 개를 다섯 줄에 출력하는 프로그램 반복문을 이용하지 않고 결과를 출력해보고, 다음에는 for 문을 이용하여 출력 for 문의 초기화, 조건검사, 증감연산, 몸체 부분에 해당하는 코드 주의
예제 소스 add.c 1에서 10까지의 합을 구하는 과정을 반복문을 사용하지 않고 구하고, 또한 for 문을 이용하여 구현
반복문 while 문 while 문 구조 while 문 실행순서 for 문보다 구조가 간단한 반복문이 while 문으로 다음과 같이 조건검사 부분인 (expression)을 while 다음에 괄호로 구성 while 문 실행순서 조건문인 expression 을 검사하여 0이 아니면(참) 반복문의 몸체에 해당하는 문장이나 블록을 실행한다. 몸체를 실행하면 다시 조건검사를 조사하여 1의 과정을 다시 실행한다. 조건검사가 거짓이면 while 문장을 종료한다. 이 부분을 while 반복문의 몸체(body)라 하며 한 문장인 경우, 블록을 구성하지 않을 수 있다. while (expression) { statement1; statement2; …. }
n까지의 곱 1에서 10까지의 곱을 구하는 while 문을 작성 이를 while 문으로 바꿔보자. 곱한 결과를 저장할 변수 mult에 초기값 1을 대입하고, while 문의 조건식으로 (i <= 10)을 지정 while 문 몸체에 곱할 축약 대입연산자를 이용하고 조건검사에 이용할 i 값을 하나 증가 mult = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10; mult = 1; i = 1; while (i <= 10) { mult *= i; i++; }
while 문이 반복되는 과정 mult = 1; i = 1; while (i <= 10) { mult *= i; i++; } 실행순서 1 2 3 변수 i 값 검사 (i<=10) 검사 결과 몸체실행 1 (mult = mult * i) 몸체실행 2 (i++) 1 <= 10 참 mult = 1*1 1+1 2 <= 10 mult = 1*1*2 2+1 3 <= 10 mult = 1*1*2*3 3+1 4 4 <= 10 mult = 1* … *4 4+1 5 5 <= 10 mult = 1* … *5 5+1 6 6 <= 10 mult = 1* … *6 6+1 7 7 <= 10 mult = 1* … *7 7+1 8 8 <= 10 mult = 1* … *8 8+1 9 9 <= 10 mult = 1* … *9 9+1 10 10 <= 10 mult = 1* … *10 10+1 11 11 <= 10 거짓
예제 소스 whilemult.c 1부터 10까지의 곱을 구하는 과정을 다음 결과와 같이 반복문을 이용하지 않고 구현하고, 또한 반복문 for와 while 문을 이용하여 구현
무한 반복 for 문에서 조건검사 부분이 없다면? while() 문에서의 조건검사 부분 아래 구문은 반복문이 종료되지 않는 무한반복(indefinite loop)을 실행 while() 문에서의 조건검사 부분 옆 while 구문은 컴파일 시간에 에러가 발생 while 구문에서 조건검사 부분은 생략할 수 없다. 위 while 구문으로 무한반복문을 만들려면 다음과 같이 할 수 있다. 조건 부문을 참으로 지정 for ( ; ; ) { printf("*****\n"); } while ( ) { printf("*****\n"); } while ( 1 ) { printf("*****\n"); }
do while 문장 구조 do while 문은 while 문과 유사하나 검사부분이 몸체의 마지막에 있는 것이 차이 statement1; ... } while (condition) ; do while 문의 종료를 의미하는 세미콜론(;)이 반드시 나와야 한다.
10진수 자릿수 반대로 정수 125에서 각각의 자릿수 1, 2, 5를 그 순서를 반대로 분리해 내는 방법을 생각해 보자. do { r_digit = value % 10; printf("%d", r_digit); value = value / 10; } while( value != 0 ); 가장 오른쪽의 수를 저장할 변수이다. 값을 구할 원 값은 변수 value에 저장한다. 이 값을 10으로 % 연산하면 가장 오른쪽의 수를 알아낼 수 있다. 구한 가장 오른쪽 값을 출력한다. 변수 value 가 0이면 모든 자릿수를 구한 것이므로 반복을 종료한다. 구한 가장 오른쪽 값의 다음 값을 구하기 위하여 value를 10으로 나누어 정수만 다시 value에 저장한다. 정수 125에서 각각의 자릿수 1, 2, 5를 그 순서를 반대로 분리해 내는 방법을 생각해 보자. 나머지 연산자 %를 이용하면 항상 단 단위 자릿수의 수를 알 수 있다. 나누기 / 연산자는 정수와 정수로 연산하면 정수 값만을 결과로 갖는다. 그러므로 다음과 같이 나누기 결과를 다시 나머지 연산에 이용하면 그 다음의 자릿수의 값을 알아낼 수 있다 실행순서 1 2 수 수 % 10 결과 수 / 10 125 125 % 10 5 125 / 10 12 12 % 10 12 / 10 1 % 10 1 / 10
예제 소스 dowhilereverse.c 입력한 정수를 반대로 출력하는 프로그램을 작성
break와 continue break continue 세 종류 반복문(for, while, do while)에서 무조건 반복문을 종료하려면 break 문을 이용 반복문에서 break의 역할은 반복을 종료하고 반복문 다음 문장으로 실행 흐름을 바꾸는 역할 Break 문은 반복문과 switch 문에서만 이용이 가능 continue continue 문은 반복문을 완전히 종료하는 것이 아니라, continue 문이 있는 몸체의 continue 문 아래 부분은 실행되지 않고, 다음 반복을 계속하는 문장 continue 문은 for, while, do-while 의 반복문에 이용되나, switch 문과는 같이 쓸 수 없다. while( expression ) { … if ( something ) break; } next statement; 반복문에서 break를 만나면 무조건 반복문을 종료하고 반복문 다음 문장을 실행한다. for ( i = 1; i <= 10; i++ ) { if ( i % 10 == 0 ) continue; printf(“%d ”, i); } if 조건문이 참이면 이 출력문을 실행하지 않고 반복문의 실행을 계속한다.
예제 소스 break.c 정수를 계속해서 입력 받는 무한 반복문에서 10을 입력 받으면 무한 반복을 종료하는 프로그램을 작성
예제 소스 continue.c 정수 1과 n사이의 수를 하나 입력 받아, 입력 받은 수를 제외한 1에서 n까지의 합을 구하는 프로그램을 작성 1에서 n까지의 합을 구하는 for 문에서 입력한 수에서는 continue 문을 실행하여 더하기를 제외
goto 문 goto 문은 레이블(label)이 위치한 다음 문장으로 제어를 옮기는 문장 레이블은 식별자와 콜론(:) 을 이용하여 지정 식별자와 콜론 사이에는 공백이 올 수도, 안 올 수도 있음 레이블의 위치는 goto 문의 위치와 상관없이 이용이 가능 즉 레이블이 goto 문 이전에 위치 가능 goto 문은 프로그램의 이해도를 낮출 수 있으므로 현재 많이 사용되지 않는 문장 가능하면 goto 문은 사용하지 않는 것이 원칙 goto lable; … lable : next statement;
예제 소스 goto.c 1부터 30까지의 정수를 한 줄에 5개씩 출력하는 프로그램
프로그램 연습 프로그램 목적 구현 1부터 n까지의 소수(prime number)를 출력하는 프로그램을 작성 하나의 정수 number가 소수임을 알려면 2부터 number-1까지의 모든 정수에 대하여 나누어 떨어지지 않음을 보이면 된다. 즉 5가 소수임을 보이는 방법은 다음과 같이 2부터 4까지 5를 나누어 봄 다음 반복문이 종료되는 것은 반복 조건검사 부분의 연산식인 (number % divisor)가 0인 경우 즉 자기 자신보다 작은 수로 나누어지거나, 나누어지지 않고 자기 자신의 수로 나누어지면 이 반복문은 종료 나누는 수(i) 수 % i 결과 2 5 % 2 == 1 !=0 3 5 % 3 == 2 4 5 % 4 == 1 for (divisor = 2; number % divisor; divisor++) ;
프로그램 연습 구현 이 반복문은 몸체가 없는 for 문으로, for 문을 빠져 나오는 경우는 두 가지 경우이다. 하나는 중간의 수로 나누어져 나오는 경우이고, 나머지는 계속 반복문을 반복하여 자기 자신으로 나누어진 경우 이 두 가지 중, 후자가 소수임을 나타냄 변수 number가 소수인지를 조사할 수가 저장된 변수이다. for (divisor = 2; number % divisor; divisor++) ; 이 연산이 0이면 조건식이 거짓이 되어 반복문을 종료한다. 즉 number 보다 작은 정수로 나누어지거나, 나누어지지 않으면, 마지막으로 자기자신으로 나누어지면 반복문이 종료된다. 자기 자신보다 작은 중간의 정수로 나누어지지 않은 수이므로, 바로 소수이다. for (divisor = 2; number % divisor; divisor++) ; if ( divisor == number ) { printf("%5d ", number ); }
소스와 결과