컴퓨터가 발명된 이유를 이전에 바로 계산하기 위해서 라고 했었다. 하지만 계산 말고도 컴퓨터가 발명된 또 다른 이유가 하나 더 있다. 바로 노가다 즉, 반복 연산 때문이다.
만약 누군가 우리에게 1부터 20까지 더하는 프로그램을 만들어 달라고 하면 우리는 단순히 printf("%d ", 1 + 2 + 3...+ 20)
하면 된다. 그러나 만약에 1부터 100000까지를 더하는 프로그램을 만들어달라고 하면 어떻게 할까? 일일이 1 + 2 +....1000000를 할까?? 이럴 때 사용하는 것이 반복문이다.
다음의 예시는 0부터 19까지를 나타내는 반복문이다.
#include<stdio.h>
int main(){
int a;
for (a = 0; a < 20; a++){
printf("숫자 : %d \n", a);
}
return 0;
}
숫자 : 0
숫자 : 1
숫자 : 2
숫자 : 3
숫자 : 4
숫자 : 5
숫자 : 6
숫자 : 7
숫자 : 8
숫자 : 9
숫자 : 10
숫자 : 11
숫자 : 12
숫자 : 13
숫자 : 14
숫자 : 15
숫자 : 16
숫자 : 17
숫자 : 18
숫자 : 19
for
반복문은 다음과 같은 기본 구조를 가지고 있다.
for (/* 초기식 */; /* 조건식 */; /* 증감식 */) {
// 명령1;
// 명령2;
// ....
}
위 구조를 자세히 한번 살펴보자 먼저 초기식에서는 제어변수를 초기화한다.
여기서 제어변수라는 것이 조금 생소할 것이다. 예를들어서 만약에 컴퓨터가 반복문을 실행하는데 반복문이 끝나지 않는다면 어떨까? 컴퓨터는 CPU 사용률을 100% 활용하여 전력낭비가 되고 코드 뒷부분은 실행도 되지 않아 결국엔 오류가 발생할 것이다. 그렇기 때문에 반복문이 얼마나 반복되어야 할지 알기 위해서 제어변수 라는 것을 도입했다.
그리고 이러한 제어변수가 특정 조건에 만족 하는한 계속 반복문이 진행되게 하는 것이다. 그러다가 제어변수가 특정 조건에 만족하지 않으면 그때 반복문을 멈추고 다음 코드가 진행되는 것이다.
앞서 초기식에서는 제어변수를 초기화한다고 하였는데 초기식에서 제어변수의 '초기값'이 저장이 되는 것이다. 예를들어서 내가 제어변수를 i
로 결정하고 초기식에 i = 4
를 했다면 초기값 4가 제어변수 i
에 저장이 되는 것이다.
이제 조건식을 보자. 조건식에서는 제어변수가 조건에 맞는지 확인한다. 그리고 조건에 맞으면 반복문이 실행이 된다. 그리고 만약에 조건에 맞기 않게 되면 그냥 반복문을 끝내게 된다. 예를 들어서 조건식에 i < 20
이라고 되어 있으면 i
가 20 미만인 경우면 계속해서 반복문의 중괄호가 실행이 된다.
마지막으로 증감식은 반복문을 실행하고 나서 제어변수의 값을 증가하거나 감소시켜주는 식이다. 예를들어서
i++
되어 있다면 반복문이 실행되고 나서 i 에 +1 을 해준다.(++i
를 하여도 반복문이 실행되고 난 다음에 1을 더한다. 따라서 둘의 차이는 없다.)
전체적으로 한 번 예시를 보면 이해하는데 큰 어려움이 없을 것이다. 아래예시를 가지고 컴퓨터가 진행되는 순서대로 설명을 해보겠다.
for (i = 0; i < 20; i++) {
printf("숫자 : %d \n", i);
}
printf("숫자 : %d \n", i);
실행.i++
이네 그러면 i에 1을 더해야겠다. 이런식으로 반복문이 진행이 되고 i 가 20이 되는 순간에 조건식에 맞지 않아 반복문이 종료가 되고 그 뒤에 코드가 실행이 된다.
그렇다면 이제 앞서 주어진 문제인 1부터 100000까지를 더하는 프로그램을 만들어보자.
#include<stdio.h>
int main(){
int i , sum = 0;
for (i=1; i<=100000; i++){
sum = sum + i;
}
printf("%d \n", sum);
return 0;
}
위와 같이 만들면 된다.
지금까지 배운 내용들을 활용하여 1부터 몇 까지의 숫자를 구할지 입력을 하면 그 숫자까지의 합을 구하는 프로그램을 만들 수 있다.
#include<stdio.h>
int main(){
int i;
int time, sum = 0;
printf("몇 까지의 숫자의 합을 구할건가요? : ");
scanf("%d", &time);
for (i=1; i<=time; i++){
sum = sum + i;
}
printf("%d \n", sum);
return 0;
}
몇 까지의 숫자의 합을 구할건가요? : 10
55
예시로 10을 넣으면 1부터 10까지의 합인 55가 나오는 것을 알 수 있다.
#include <stdio.h>
int main() {
int usranswer;
printf("컴퓨터가 생각한 숫자를 맞추어 보세요! \n");
for (;;) {
scanf("%d", &usranswer);
if (usranswer == 3) {
printf("맞추셨군요! \n");
break;
} else {
printf("틀렸어요! \n");
}
}
return 0;
}
컴퓨터가 생각한 숫자를 맞추어 보세요!
5
틀렸어요!
6
틀렸어요!
7
틀렸어요!
8
틀렸어요!
3
맞추셨군요!
위의 예제를 살펴보자 생소한 것들이 조금 보인다.
for (;;)
먼저 위의 for 구문 안에 초기식, 조건식, 증감식 등이 없는 것을 확인할 수 있다.
만약의 조건식이 없다면 for구문은 항상 참이 되기 때문에 무한적으로 반복문이 진행이 된다. 그렇다면 프로그램이 끝나지 않고 계속 실행이 되는 것인가??
여기서 중간에 반복문을 끝내주는 것이 있는데 바로 break
이다.
**break
문이 실행이 되면 반복문은 즉각 종료되고 중괄호 밖으로 나가게 된다.**
for (;;) {
scanf("%d", &usranswer);
if (usranswer == 3) {
printf("맞추셨군요! \n");
break;
} else {
printf("틀렸어요! \n");
}
}
위 예시에서 만약에 usranswer
의 값이 3이 입력이 되지 않는한 반복문은 계속해서 실행이 될 것이다.
그러다가 만약 3을 입력하게 되면 "맞추셨군요!" 라는 print문이 실행되고 break
문이 실행되어 for 문이 바로 종료가 된다 즉, for 구문 중괄호 안에 있는 break
밑에 부분은 실행이 되지 않고 for 반복문 다음의 코드로 진행이 되어 종료(return 0
)가 된다.
break
를 반복문안에서 탈출시켜주는 도구라고 생각하면 이해하기가 좀 더 편할 수 있다.
break
와 비슷하지만 좀 다른 continue
에 대해서 살펴보자.
먼저 예제를 살펴보자
#include <stdio.h>
int main() {
int i;
for (i = 0; i < 100; i++) {
if (i % 10 == 0) continue;
printf("%d ", i);
}
return 0;
}
1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19 21 22 23 24 25 26 27 28 29 31
32 33 34 35 36 37 38 39 41 42 43 44 45 46 47 48 49 51 52 53 54 55 56 57 58
59 61 62 63 64 65 66 67 68 69 71 72 73 74 75 76 77 78 79 81 82 83 84 85 86
87 88 89 91 92 93 94 95 96 97 98 99
여기서 핵심적인 부분은 다음과 같다.
for (i = 0; i < 100; i++) {
if (i % 10 == 0) continue;
printf("%d ", i);
}
if 문에서 i 를 10으로 나누었을 때 0으로 나누어 떨어지는, 즉 10의 배수값일 경우 continue
가 실행되고 다음으로 넘어가 printf("%d ", i);
가 실행되고 만약 10의 배수값이 아닐경우 그냥 printf("%d ", i);
만 실행이 된다.
그런데 결과를 보면 10의 배수인 경우 뒤에 print문(printf("%d ", i);
) 이 실행이 안된 것을 볼 수 있다.
그 이유는 continue
가 실행이 되면 그 뒤에 있는 문장들은 실행되지 않고 바로 다음 반복문이 실행이 된다.
그래서 i 가 10의 배수인 경우 뒤에 print문이 실행이 되지 않고 바로 다음 수로 넘어간다.
문득 이런 생각이 든다. 만약에 for 안에 for을 넣을 수 있을까? 결론부터 말하자면 물론 가능하다.
#include<stdio.h>
int main(){
int i, j ;
for (i = 1; i < 10; i++){
for (j = 1 ; j<10; j++){
printf("%d * %d = %d \n", i,j, i*j);
}
}
return 0;
}
1 * 1 = 1
1 * 2 = 2
1 * 3 = 3
1 * 4 = 4
1 * 5 = 5
.
.
.
9 * 6 = 54
9 * 7 = 63
9 * 8 = 72
9 * 9 = 81
for 안에 for을 이용하여 구구단을 만들었다.
지금까지 for 구문에 대해서 잘 이해를 했다면 위 예제를 이해하는데 큰 무리가 없을 것이다.
이번에는 for 구문과 비슷하지만 다른 while
문에 대해서 살펴보자
#include <stdio.h>
int main() {
int i = 1, sum = 0;
while (i <= 100) {
sum += i;
i++;
}
printf("1 부터 100 까지의 합 : %d \n", sum);
return 0;
}
1 부터 100 까지의 합 : 5050
위의 예제에서 알 수 있듯이 while
문은 for에 비해 사뭇 단순하다.
while (/* 조건식 */) {
// 명령1;
// 명령2;
// ...
}
while
문의 기본적인 구조는 위와 같다. for 과 마찬가지로 while
에도 조건식이 들어가고 조건이 맞는 한 계속해서 while
반복문 중괄호 내용들이 반복이 된다.
while (i <= 100) {
sum += i;
i++;
}
위의 경우 조건식인 i 가 100 이하인지 확인하고 중괄호 내용들이 실행이 된다. sum에 i 를 더하고 그 다음에 i에 1을 더한다. 그리고 다시 반복문이 실행이 된다.
while
문이 for과 다른점은 처음부터 조건식을 확인한다는 것이다.
#include <stdio.h>
int main() {
int i = 1, sum = 0;
do {
sum += i;
i++;
} while (i < 1);
printf(" sum : %d \n", sum);
return 0;
}
sum : 1
위의 예제를 보면 while
앞에 do
가 있는 것을 볼 수 있다. do- while
문은 우선 반복문이 실행된 이후에 조건을 확인하게 한다. 그래서 위의 예시처럼 처음부터 조건에 맞지 않아도 무조건 1번은 반복문이 실행이 된다.
그렇기 때문에 1이 실행이 된 것을 볼 수 있다.
문제 1 (난이도 : 中)
N 줄인 삼각형을 출력한다. 단, 사용자로 부터 임의의 N 을 입력 받는다. 아래는 N = 3 일 때의 출력 예시 이다.
*
***
*****
문제 2 (난이도 : 中上)
위와 동일한 형태를 취하되, 역 삼각형을 출력한다. 아래는 N = 3 일 때의 출력 예시 이다.
*****
***
*
문제 3 (난이도 : 下)
1000 이하의 3 또는 5 의 배수인 자연수들의 합을 구한다.
문제 4 (난이도 : 中)
1000000 이하의 피보나치 수열 ( N 번째 항이 N - 1 번째 항과 N - 2 번째 항으로 표현되는 수열, 시작은 1,1,2,3,5,8,...) 의 짝수 항들의 합을 구한다
문제 5 (난이도 : 下)
사용자로 부터 N 값을 입력 받고 1 부터 N 까지의 곱을 출력한다.
문제 6 (난이도 : 中)
다음 식을 만족하는 자연수 a,b,c 의 개수를 구하여라
i) a + b + c = 2000
ii) a > b > c, a,b,c 는 모두 자연수
문제 7 (난이도 : 中上)
임의의 자연수 N 을 입력 받아 N 을 소인수 분해 한 결과를 출력하여라. 예를 들어서 N = 18 일 경우
N = 18 18 = 2 3 3
문제 8 (난이도 : 上)
문제 7 에서 만든 프로그램의 속도를 향상 시킬 수 있는 방법은 없을까? 큰 수를 빠르게 소인수분해 할 수 있는 방법들을 찾아 프로그램에 적용시켜 보아라. 예를 들어서 N 의 제곱근 이하의 정수들만 처리한다던지, Lucas- Lehmer 판정법을 이용해 소수인지 아닌지 판정한다던지 등등..