2권을 보면서 느낀점…일까?
(2020-01-19) 나프잘 프로그래밍 2권은 1권에서 배운 내용을 다시 한번 복습하는 개념으로 쓰여진 책인 거 같다. 문제를 이해하고 설계, 순서도, 나씨 슈나이더만 다이어그램, 구현까지 문제 하나에 대한 저자의 생각을 따라가면서 ‘감’이란걸 느낄 수 있었다. 이렇게 한 장, 한 장씩 넘기다보면 제일 마지막에는 문제를 내주면서 끝이 난다. 총 8 문제로 어떻게 보면 간단한 문제들을 이 책의 내용에서 소개해준 과정을 하기 위해서는 시간이 많이 걸렸다. 문제 이해가 빨리되었다 해도 기술서 작성, 순서도, 나씨-슈나이더만 다이어그램….을 그리다보면 ‘내가 꼭 이걸 해야되나?’하기도 한다. 금요일에서 주말까지(주말은 간간히 시간내면서) 차근차근 생각하면서 과정을 살펴보았다.
(2020-01-20) 구현은 이제 해야된다.
문제
- 1+3+5+7+…+99까지 홀수의 합을 구하시오.
- 1에서 100까지 수 중 홀수의 합과 짝수의 합을 구하시오.
- 1+(1+2)+(1+2+3)+…+(1+2+3+4+…+100)까지의 합을 구하시오.
- 1-2+3-4+5…+99-100에서 합을 구하시오.
- 1에서 100까지 수 중에서 3의 배수와 5의 배수를 제외한 합을 구하시오.
- 1-(1/2)+(1/3)-…+(1/99)-(1/100) 합을 구하시오.
- 1-(2/3!)+(3/5!)-…-(10/19!
- 다음과 같은 수열을 피보나치(Fibonacci) 수열이라고 합니다. 1,1,2,3,5,8,13,21 … 즉 앞의 두 항을 합하면 다음 항이 됩니다. 50번째 피보나치 수를 구하시오.
모듈 기술서, 순서도, NS-Charts
아래는 각 문제 번호에 따른 모듈 기술서, 순서도, NS-Chart이다.
문제 1
(2020-01-20)
이전에 올린 모듈 기술서가 디버깅해본 결과 잘못 작성되었다. 홀수를 판단하는 분기점에서 짝수이면 합을 더하기로 되있다..;;
모듈 기술서 변경 후
코드는 아래와 같이 작성하였다.
//1_oddAdder.c
/**************************************************************************
* 파일 명칭 : oddAdder.c
* 기 능 : 1부터 100까지의 홀수 합 계산
* 함수 명칭 : main
* 출 력 : 홀수합
* 입 력 : 없음
* 작 성 자 : 채 종 홍
* 작성 일자 : 2020/01/20
**************************************************************************/
#include <stdio.h>
#define MAX 10
#define DIVIDER 2
int main(int argc, char* argv[]) {
unsigned long oddSum = 0;
unsigned long number = 1;
unsigned long remainder = 0;
//2. 수가 MAX보다 작거나 같을 때까지 반복한다.
while (number <= MAX) {
//2.1. 수가 홀수인지 판단한다.
remainder = number % DIVIDER;
if (remainder != 0) {
//2.1.1. 홀수이면 홀수 합을 구한다.
oddSum += number;
}
//1. 수를 증가한다.
number++;
}
//3. 홀수 합을 출력한다.
printf("oddSum : %d\n", oddSum);
//4. 끝낸다.
return 0;
}
문제 2
(2020-01-20)
‘1부터 100까지의 수 중의 합’이라는 말이 헷갈린다. 저자의 이런 말이 들어간 문제는 값을 입력받아 처리하는 문제가 있었기 때문이다. 그래서 위의 그림 또한 변경이 되어야한다.
모듈 기술서 변경 후
코드는 아래와 같이 작성하였다.
//2_oddEvenAdder.c
/**************************************************************************
* 파일 명칭 : 2_oddEvenAdder.c
* 기 능 : 1부터 100까지의 수 중의 홀수 합과 짝수 합을 구한다.
* 함수 명칭 : main
* 출 력 : 홀수합, 짝수합
* 입 력 : 없음
* 작 성 자 : 채 종 홍
* 작성 일자 : 2020/01/20
**************************************************************************/
#include <stdio.h>
#define MAX 100
#define DIVIDER 2
int main(int argc, char *argv[]){
unsigned long oddSum = 0;
unsigned long evenSum = 0;
unsigned long number = 1;
unsigned long remainder = 0;
//2. 수가 작거나 같을 때까지 반복한다.
while(number <= MAX){
//2.1. 수가 홀수인지 짝수인지 판별한다.
remainder=number%DIVIDER;
if(remainder != 0){
//2.1.1. 홀수이면 홀수합을 구한다.
oddSum+=number;
}else{
//2.1.2. 짝수이면 짝수합을 구한다.
evenSum+=number;
}
//1. 수를 증가한다.
number++;
}
//3. 홀수 합과 짝수 합을 출력한다.
printf("oddSum : %d, evenSum : %d\n", oddSum, evenSum);
//4. 끝낸다.
return 0;
}
문제 3
(2020-01-20)
이중 반복문을 안쓰고 설계를 해보았지만 해결하지 못하였다. 그래서 이중 반복문을 사용하는 것으로 설계를 바꾸었다.
모듈 기술서 변경 후
코드는 아래와 같이 작성하였다.
//3_sequenceAdder.c
/**************************************************************************
* 파일 명칭 : 3_sequenceAdder.c
* 기 능 : 1+(1+2)+(1+2+3)+...+(1+2+3+4+...+100)까지의 합을 구한다.
* 함수 명칭 : main
* 출 력 : 총합
* 입 력 : 없음
* 작 성 자 : 채 종 홍
* 작성 일자 : 2020/01/20
**************************************************************************/
#include <stdio.h>
#define MAX 100
int main(int argc, char* argv[]) {
unsigned long sum = 0;
unsigned long temp = 0;
unsigned long number = 1;
//2. 수가 MAX보다 작거나 같을 때까지 반복한다.
while (number <= MAX) {
//2.2. 이전까지의 합을 구한다.
for (temp = 1; temp < number; temp++) {
sum += temp;
}
//2.1. 총합을 구한다.
sum += number;
//1. 수를 증가한다.
number++;
}
//3. 총합을 출력한다.
printf("1부터 %d까지의 순차합 : %d\n", MAX, sum);
//4. 끝낸다.
return 0;
}
문제 4
(2020-01-20)
일단 모듈 기술서만으로 디버깅을 했을 때 잘 수행되어 바로 구현으로 들어갔다. 코드는 아래와 같이 작성하였다.
//4_onlyminusEven.c
/**************************************************************************
* 파일 명칭 : 4_onlyminusEven.c
* 기 능 : 1-2+3-4+...+99-100를 계산한다.
* 함수 명칭 : main
* 출 력 : 총합
* 입 력 : 없음
* 작 성 자 : 채 종 홍
* 작성 일자 : 2020/01/20
**************************************************************************/
#include <stdio.h>
#define MAX 100
#define DIVIDER 2
int main(int argc, char* argv[]) {
unsigned long sum = 0;
unsigned long remainder = 0;
unsigned long number = 1;
//2. 수가 MAX보다 작거나 같을 때까지 반복한다.
while(number <= MAX){
//2.1. 짝수를 판별한다.
remainder=number%DIVIDER;
if(remainder==0){
//2.1.1. 짝수이면 합을 뺀다.
sum-=number;
}else{
//2.1.2. 짝수가 아니면 합을 더한다.
sum+=number;
}
//1. 수를 증가한다.
number++;
}
//3. 합을 출력한다.
printf("1부터 %d까지의 합 : %d", sum);
//4. 끝낸다.
return 0;
}
문제 5
(2020-01-20)
처리 과정에 대해서 부분적으로 고쳤다. 조금 더 코드적인 처리 사고를 가져야 겠다.
- 수를 증가한다.
- 수가 최댓값보다 작거나 같을 때까지 반복한다. 2.1. 3의 배수를 판별한다. 2.1.1. 3의 배수가 아니면 5의 배수를 판별한다. 2.1.2. 5의 배수가 아니면 합을 구한다.
- 합을 출력한다.
- 끝낸다.
코드는 아래와 같이 작성하였다.
//5_exclusionAdder.c
/**************************************************************************
* 파일 명칭 : 5_exclusionAdder.c
* 기 능 : 1에서 100까지 수 중에서 3의 배수와 5의 배수를 제외한
* 합을 계산한다.
* 함수 명칭 : main
* 출 력 : 총합
* 입 력 : 없음
* 작 성 자 : 채 종 홍
* 작성 일자 : 2020/01/20
**************************************************************************/
#include <stdio.h>
#define MAX 100
#define DIVIDER3 3
#define DIVIDER5 5
int main(int argc, char* argv[]) {
unsigned long sum = 0;
unsigned long remainder = 0;
unsigned long number = 1;
//2. 수가 최댓값보다 작거나 같을 때9까지 반복한다.
while(number <= MAX){
//2.1. 3의 배수를 판별한다.
remainder = number%DIVIDER3;
if(remainder != 0){
//2.1.1. 3의 배수가 아니면 5의 배수를 판별한다.
remainder=number%DIVIDER5;
if(remainder != 0){
//2.1.2. 5의 배수가 아니면 합을 더한다.
sum+=number;
}
}
printf("sum : %d\n",sum);
//1.수를 증가한다.
number++;
}
//3. 합을 출력한다.
printf("last sum : %d\n",sum);
//4. 끝낸다.
return 0;
}
문제 6
(2020-01-20)
여기서는 자료 명세서 작성 시 출력에 대한 생각을 좀 더 신중하게 해야될 것 같다. 글에서는 분수 형태로 표기되었지만 출력 시에는 결국 소수로 표현해야되지 않을까 생각이 들었다.
이 때문에 자료 명세서에서 ‘합’, ‘정수’의 자료유형을 ‘정수’가 아닌 ‘실수’로 변경했다.
코드는 아래와 같이 작성하였다.
//6_denominatorSum.c
/**************************************************************************
* 파일 명칭 : 6_denominatorSum.c
* 기 능 : 1-(1/2)+(1/3)-...+(1/99)-(1/100)을 계산한다.
* 함수 명칭 : main
* 출 력 : 총합
* 입 력 : 없음
* 작 성 자 : 채 종 홍
* 작성 일자 : 2020/01/20
**************************************************************************/
#include <stdio.h>
#define MAX 100
#define NUMERATOR 1
#define DIVIDER 2
int main(int argc, char* argv[]) {
float sum = 0;
float temp = 0;
unsigned long remainder = 0;
unsigned long number = 1;
//2.분모가 최댓값보다 작거나 같을 때까지 반복한다.
for(number=1; number<=MAX; number++){
//2.1. 분수 형태를 만든다.
temp = (float)NUMERATOR/number;
//2.2. 분모가 짝수인지 판별한다.
remainder=number%DIVIDER;
if(remainder == 0){
//2.2.1. 분모가 짝수이면 합에서 분수를 뺀다.
sum-=temp;
}else{
//2.2.2. 짝수가 아니면 합에서 분수를 더한다.
sum+=temp;
}
//1.분모를 증가한다.
}
//3.합을 출력한다.
printf("1-(1/2)+(1/3)-...+(1/%d)-(1/%d) : %f", MAX-1, MAX, sum);
//4.끝낸다.
return 0;
}
문제 7
여기서도 ‘문제 6’과 동일하게 결과값을 실수로 표현해야했다.(분수니깐??)
코드는 아래와 같이 작성하였다.
//7_factorialSum.c
/**************************************************************************
* 파일 명칭 : 7_factorialSum.c
* 기 능 : 1-(2/3!)+(3/5!)-...-(10/19!)을 계산한다.
* 함수 명칭 : main
* 출 력 : 총합
* 입 력 : 없음
* 작 성 자 : 채 종 홍
* 작성 일자 : 2020/01/20
**************************************************************************/
#include <stdio.h>
#define MAX 10
#define DIVIDER 2
int main(int argc, char* argv[]) {
float sum = 0;
float fraction = 0;
unsigned long numerator = 0;
unsigned long number = 1;
unsigned long factorial = 1;
unsigned long remainder = 0;
unsigned long temp = 0;
//1. 분자를 증가한다.
//2. 분자가 MAX보다 작거나 같을 때까지 반복한다.
for(numerator=1; numerator<=MAX; numerator++){
//2.1.1. 분모를 구한다.
number=numerator+temp;
while(number > 0){
printf("number: %d\n", number);
factorial=factorial*number;
number--;
}
//2.1. 분수 형태를 만든다.
fraction=(float)numerator/factorial;
//2.2. 분자가 짝수인지 판별한다.
remainder=numerator%DIVIDER;
if(remainder == 0){
//2.2.1. 짝수이면 합을 뺀다.
sum-=fraction;
}else{
//2.2.2. 짝수가 아니면 합을 더한다.
sum+=fraction;
}
temp=numerator;
factorial=1;
}
//3. 합을 출력한다.
printf("factorialSum : %f\n", sum);
//4. 끝낸다.
return 0;
}
문제 8
(2020-01-21)
하다보니깐 벌써 새벽 2시가 넘어갔다. 문제 8번을 하면서 이상하게 음수값이 출력이 된다. 내가 자체적으로 생각한 문제는 이러했다.
- 선언한 자료형 범위를 넘겨버려서?
- 피보나치 수열을 이상하게 만듦
1번, 2번 둘 다 생각해서 수정하고 다시 했어도 결과는 똑같았다. 마지막 방법인 인터넷에서 다른 분들이 짠 코드를 실행해보는 것이였는데……
-298632863이라는 값이 동일하게 출력되었다. 하지만 이상했던게 에서 만들어 놓은 피보나치 수열을 보면 내가 원하는 값이 나온다는 걸 확인할 수 있었다.
코드는 아래와 같이 작성하였다.(자료형값이 달라졌다.)
//8_fibonacci.c
/**************************************************************************
* 파일 명칭 : 8_fibonacci.c
* 기 능 : 피보나치 수열의 50번째 값을 출력
* 함수 명칭 : main
* 출 력 : 50번째값
* 입 력 : 없음
* 작 성 자 : 채 종 홍
* 작성 일자 : 2020/01/21
**************************************************************************/
#include <stdio.h>
#define MAX 50
int main(int argc, char* argv[]) {
int iteration = 0;
int last = 0;
int temp = 0;
int longLast = 0;
//1. 숫자를 증가한다.
//2. 숫자가 MAX보다 작거나 같으면 종료한다.
for(iteration=0; iteration<=MAX; iteration++){
//2.1. 피보나치 수열을 수행한다.
if(iteration < 2){
temp=last;
last+=iteration;
}else{
longLast=last+temp;
temp=last;
last=longLast;
}
}
//3. 합을 출력한다.
printf("fibonacci result : %d\n", last);
//4. 끝낸다.
return 0;
}
2권을 마무리하면서…
뭐…마무리가 아닐 것이다. 이제 3권을 하면서 해야되는 것은 위의 문제들에 대한 최적화가 아닐까 싶다. 보기 좋게 변수를 고쳐본다랄지 좀 더 간결하게 혹은 효율적으로 해본다랄지 등… 생각을 해볼 부분이 많다.
제대로 하고 있는지는 모르겠지만 그래도 이렇게 블로그에 기록도 하고 가이드가 되는 책도 있으니 뭔가를 한다는 기분은 확실히 있는거 같다.