ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [알고리즘/C언어] 수열의 합 알고리즘(2) / for문, while문, do-while문, goto문 (정보처리기사, 실기)
    Algorithm 2019. 5. 19. 22:50

    지난 번 포스팅 때 다루지 않았던 while문이나 do-while문, goto문을 이용한

    기초적인 수열의 합 알고리즘을 정리해보려고 한다.

     

     

    1. Sum = 1+2+3+4+...+NUM(10)까지의 합

    [for문]

    #include <stdio.h>
    #define NUM 10
    int main() {
    	int  cnt, sum = 0, i = 0;
    	for (cnt = 1; cnt <= NUM; cnt++) {
    		i = i + 1;
    		sum = sum + i;
    		printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    	}
    	printf("----------반복문 종료-------------\n");
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    
    	system("pause");
    	return 0;
    }

     

    먼저 아주 기초적인 1부터 n항까지의 합을 for문으로 구하는 코드이다.

    cnt는 카운트 변수, sum은 누적해서 더할 값을 담을 변수, i는 1씩 증가하는 값을 담는 변수이다.

     

    (물론 cnt와 i를 나누지 않고 써도 된다.)

     

    for문을 사용하면 선처리 후증가가 이루어진다. (앞으로 이 방식을 type B라고 부를 것이다.)

    무슨 말이냐하면 cnt변수의 증가가 sum 연산이 다 끝난 이후에 이루어진다는 뜻이다.

    그러므로 for문이 끝나고 난 후 cnt의 값은 10이 아닌 11이 된다.

     

     

     

    2. Sum = 1+2+3+4+...+NUM(10)까지의 합

    [while문]

    #include <stdio.h>
    #define NUM 10
    int main() {
    	int  cnt = 1, sum = 0, i = 0;
    	while (cnt <= NUM) {
    		i = i + 1;
    		sum = sum + i;
    		
    		printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    		cnt++;
    	}
    	
    	printf("----------반복문 종료-------------\n");
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    
    	system("pause");
    	return 0;
    }

     

    위와 같은 내용의 코드를 이번엔 while문으로 표현해보았다.

    while문은 ()안에 쓰여진 조건식이 true인 경우 아래 실행문을 처리하고

    false이면 실행하지 않고 반복을 빠져나가는 코드이다.

     

    위의 코드 역시 cnt변수 값의 증가가 sum 연산이 끝난 이후에 이루어지고 있다.

    그러므로 역시나 반복문이 끝난 이후 cnt의 값은 11이 된다.

     

     

    #include <stdio.h>
    #define NUM 10
    int main() {
    	int  cnt = 0, sum = 0, i = 0;
    	while (cnt < NUM) {
    		cnt++;
    		i++;
    		sum = sum + i;
    
    		printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    	}
    
    	printf("----------반복문 종료-------------\n");
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    
    	system("pause");
    	return 0;
    }

     

    위와 완벽하게 동일한 결과를 내는 코드이지만

    이번엔 cnt 변수의 초기값이 1이 아닌 0이다.

    숫자를 10번 더해야하는 데, 0부터 세고 있으니

    cnt가 9가 될 때까지 반복되어야 10번 실행되는 셈이다.

    그러므로 while문의 조건식은 cnt < NUM이 된다.

     

    그리고 이번엔 cnt값의 증가가 sum 연산 전에 이루어지고 있다.

    즉, 선증가 후처리 방식이다. 앞으로 이 방식을 type A 방식이라고 부르겠다.

    cnt의 값이 먼저 증가하고 sum 연산이 실행되므로 반복문이 종료하고 난 후

    cnt 변수의 값은 이제 11이 아닌 10이 출력된다.

     

     

     

    3. sum = 1 + 3 + 5 + 7 + ... + NUM(10)까지의 합

    [while문]

    #include <stdio.h>
    #define NUM 10
    int main() {
    	int  cnt = 0, sum = 0, i = -1;
    	while (cnt < NUM) {
    		cnt = cnt++;
    		i = i + 2;
    		sum = sum + i;
    		printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    	}
    	printf("----------반복문 종료-------------\n");
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    
    	system("pause");
    	return 0;
    }

     

    이제 1 + 3 + 5 + 7 + ... + 10 을 해야한다고 생각해보자.

    위 수열은 1부터 시작하여 2씩 증가하는 숫자의 합이다. (즉, 홀수들의 합이다.)

     

    while문(+ type A 방식)으로 표현한다면 일단 cnt 변수 0 부터 NUM-1까지 반복해야하므로

    cnt의 초기값은 0 이고 while의 조건식은 cnt < NUM이다.

    2씩 증가하는 수열이므로 i = i + 2; 이다.

     

    중요한건 sum의 초기값이 0이고 수열은 1부터 시작하는 데,

    i = i + 2;를 sum 연산 전에 해준다는 점이다.

    그러면 i의 초기값이 -1이 되어야 1부터 연산이 시작된다.

     

     

     

    4. sum = 1 + 3 + 5 + 7 + ... + NUM(10)까지의 합

    [do-while문]

    #include <stdio.h>
    #define NUM 10
    int main() {
    	int  cnt = 1, sum = 0, i = -1;
    	do {
    		i = i + 2;
    		sum = sum + i;
    		printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    		cnt = cnt + 1;
    	} while (cnt <= NUM);
    	
    
    	printf("----------반복문 종료-------------\n");
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    
    	system("pause");
    	return 0;
    }

     

    위 코드를 do-while문으로 고쳐보았는데,

    이번엔 cnt의 초기값을 1로 바꿔보았다.

    이 경우에는 NUM까지 반복을 돌아야하므로

    조건문은 cnt <= NUM가 되어야 한다.

     

     

     

    5. sum = 1 + 3 + 5 + 7 + ... + NUM(10)까지의 합

    [goto문 (type A: 선증가 후처리)]

    #include <stdio.h>
    #define NUM 10
    int main() {
    	int  cnt = 0, sum = 0, i = -1;
    AA:	cnt = cnt + 1;
    	i = i + 2;
    	sum = sum + i; 
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    
    	if (cnt < NUM) {
        		goto AA;
        	}
    	else {
        		goto BB;	// else절 생략 가능
        	}
    	
    BB:	printf("----------반복문 종료-------------\n");
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    
    	system("pause");
    	return 0;
    }

     

    goto문이라는 걸 난생 처음봐서 매우 생소하게 느껴졌는데,

    뜯어보면 for문이랑 별 다를 바가 없다.

     

    먼저 cnt의 초기값은 0이고 그 값에 1을 미리 증가시킨다.

    i도 2를 증가시키고 시작하므로 i의 초기값은 -1이어야 한다.

    그리고 sum에 i를 더하는 연산을 끝낸 후

    cnt의 값이 NUM보다 작으면 AA로 돌아간다.

     

    반복해서 작업하다가 cnt의 값이 NUM보다 크거나 같아지면

    BB로 내려가서 반복문을 종료하는 데,

    else절의 문장은 생략 가능하다.

     

    i의 값이 먼저 증가되고 sum 연산이 이루어졌으므로 

    반복이 다 끝난 후 cnt의 값은 10이 된다.

     

    이 연산을 Flow Chart로 표현해보면 왼쪽 그림과 같다.

     

     

     

     

     

     

     

    6. sum = 1 + 3 + 5 + 7 + ... + NUM(10)까지의 합

    [goto문 (type B: 선처리 후증가)]

    #include <stdio.h>
    #define NUM 10
    int main() {
    	int  cnt, sum = 0, i = -1;
    	cnt = 1;
    
    AA:	if (cnt <= NUM) {
    		i = i + 2;
    		sum = sum + i;
    		printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    		cnt = cnt + 1;
    		goto AA;
    	}
    
    	printf("----------반복문 종료-------------\n");
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    
    	system("pause");
    	return 0;
    }

     

    이제 cnt 카운트를 sum 연산 뒤에 하는 type B 방식으로 코드를 작성해보자.

     

    먼저 cnt의 초기값은 이번엔 1로 설정해보았다.

    그렇다면 자연스럽게 조건문은 cnt <= NUM이 된다.

     

    이제 i의 값을 2증가시키고 sum에 더한다.

    sum 연산을 먼저 처리하고 후에 cnt값을 증가한다.

     

    그 상태에서 다시 조건문으로 goto하여 조건을 판별한다.

     

    조건을 쭉 반복하다가 cnt의 값이 10이 되면

    i = i + 2; sum = sum + 1; cnt = cnt + 1; 연산을 수행한 후

    다시 조건을 판별하여 cnt <= NUM 조건이 false이므로

    반복문을 빠져나간다.

     

    여기서 중요한 것은 반복문이 빠져나간 후 

    cnt의 값은 11이라는 점이다.

     

    Flow Chart로 표현해보면 왼쪽 그림과 같다.

     

     

     

     

     

     

    7. sum = a + (a+1) + (a+2) + (a+3) + ... + (a+9)

    #include <stdio.h>
    #define NUM 10
    int main() {
    	int  cnt, sum = 0;
    	cnt = a - 1;
    AA:	cnt = cnt + 1;
    	sum = sum + cnt;
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, sum);
    
    	if (cnt < b) goto AA;  //if (cnt <= b-1) goto AA;
    
    BB:	printf("----------반복문 종료-------------\n");
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    
    	system("pause");
    	return 0;
    }

     

    그러니까 위 표현식을 확실하게 이해해두면 된다.

    cnt라는 카운트 변수의 값을 먼저 1 증가시키고 sum 연산을 하는 경우

    sum에 cnt를 더하는 데, (a + 0) 을 먼저 더해야하므로 cnt의 초기값은 a - 1이다.

     

    또한 a - 1번부터 카운트하므로 조건문은 cnt < b가 되어야 한다. (b는 카운트하면 안됨.)

     

     

     

    8. 역순으로 카운트하기 (10 - 9 - 8 - 7 - ...  순서로 카운트하기)

    [type B (선처리 후증감)]

    #include <stdio.h>
    #define NUM 10
    int main() {
    	int  cnt, sum = 0, i = -1;
    	cnt = NUM;
    
    AA:	i = i + 2;
    	sum = sum + i;
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    	cnt = cnt - 1;
    
    	if (cnt > 0) goto AA;
    
     	printf("----------반복문 종료-------------\n");
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    
    	system("pause");
    	return 0;
    }

     

    그러니까 쉽게 말하면 지금까지는 count를 1부터 순차대로 했다.

    1, 2, 3, 4, 5, ... , NUM까지.

     

    근데 이제 거꾸로 카운트하는 코드를 작성해보았다.

    NUM이 10이라면 10, 9, 8, 7, ... , 1 순서대로 카운트하는 것이다.

     

    그러니까 cnt 초기 변수NUM을 할당한다.

    이제 cnt변수에 1을 더해주는 것이 아니라 빼준다.

     

    조건문은 cnt > 0이 된다.

    cnt >= 0이 아닌 이유는 10부터 세기 시작했으므로

    10~1까지 카운트해야하기 때문이다. 0은 포함하면 안된다..

     

    이 코드는 잘 보면 cnt = cnt - 1을 sum 연산이 끝난 이후에 하고 있다.

    그러므로 이 코드는 for (cnt = NUM; cnt > 0; cnt--) {  } 이렇게 for문을 사용한 것과 같다.

     

    반복문이 종료된 후 cnt의 값은 0이 된다.

     

     

     

    9. 역순으로 카운트하기 (10 - 9 - 8 - 7 - ...  순서로 카운트하기)

    [type A (선증감 후처리)]

    #include <stdio.h>
    #define NUM 10
    int main() {
    	int  cnt, sum = 0, i = -1;
    	cnt = NUM + 1;
    	
    AA:	cnt = cnt - 1;
    	i = i + 2;
    	sum = sum + i;
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);
    	
    
    	if (cnt > 1) goto AA;
    
    	printf("----------반복문 종료-------------\n");
    	printf("cnt=%2d, i=%2d, sum=%5d\n", cnt, i, sum);	// i = 11
    
    	system("pause");
    	return 0;
    }

     

    위 경우에는 cnt의 증감을 먼저 하고 sum 연산을 수행한다.

    그러면 당연히 cnt의 초기 변수는 NUM이 아닌 NUM + 1이 되어야 할 것이다.

     

    그리고 조건문은 cnt >= 1이 아닌 cnt > 1이 된다.

    이 부분이 좀 헷갈리는 데, 그림을 그려보면 좀 더 쉽게 이해가 된다.

     

     

    cnt = 11 (초기값: NUM + 1)

    cnt--; cnt --; cnt --; cnt --; cnt --; cnt --; cnt --; cnt --; cnt --; cnt --;
    10 9 8 7 6 5 4 3 2 1
    연산 수행 연산수행 연산수행 연산수행 연산수행 연산수행 연산수행 연산수행 연산수행 연산수행
    조건 참 조건 참 조건 참 조건 참 조건 참 조건 참 조건 참 조건 참 조건 참 조건 거짓

     

    초기값이 11인데 cnt--; 연산을 바로 수행하여 10이 되고 연산을 수행한다.

    cnt > 1을 만족하므로 다음 연산을 수행하러 AA문으로 가면 다시 cnt--;을 진행하여 9가 된다.

    계속 반복하다가 마지막에 값이 2가 됐을 때, 조건이 참이므로 

    다시 AA로 가서 cnt--; 연산을 하므로 값이 1이 된다. 바로 이 때가 10번째 연산을 진행했을 때다.

    이미 10번의 연산이 모두 끝났으므로 조건은 거짓이 되어야 한다.

     

    그러므로 cnt는 1보다 클 때만 연산을 수행해야 한다는 조건을 세워야 한다.

     

    반복문이 종료된 후 cnt의 값은 1이 된다.

    반응형

    COMMENT