달력 프로그램 설명

☆C언어/소스 2011. 10. 14. 09:27

특정 년, 월을 입력받아서 그 달의 달력을 출력해 주는 프로그램을 작성하다면

 

가장 중요한 것은 그 달의 1일이 무슨 요일인지를 알아내는 것입니다.

 

이것이 달력 프로그램의 99%를 차지합니다.

 

그달의 1일이 무슨 요일인지 알면 1부터 그달의 끝 날짜까지 차례대로 출력하면

 

그것이 바로 그달의 달력이 됩니다.

 

 

제가 생각하기에는 달력은 특정 날짜부터 시작해서 몇일이나 지났는지 세는 방식입니다.

 

지금 현재 우리가 사용하고 있는 달력은 그레고리력으로 1582년 10월 15일 금요일부터

 

사용하기 시작했습니다.

 

달력이 특정날짜부터 시작해서 몇 일이나 지났는지 세는 방식이므로

 

1582년 10월 15일 부터 출력하려는 날까지 몇일지나 지났는지 계산하면 됩니다.

 

그런데 1582년 10월 15일 부터 세는 것은 계산하기 번거롭기 때문에,

 

저는 서기 0년 12월 31일부터 세는 것으로 하겠습니다.

 

그레고리력의 서기 0년 12월 31일은 일요일입니다. (그레고리력의 서기 1년 1월 1일의 앞 날짜)

 

(그레고리력은 1582년 10월 15일 이전의 날짜는 나타내지 못합니다.

그 전의 날짜는 율리우스력으로 나타냅니다. 서기 0년도 실제로는 없습니다.

기원전 1년 다음해는 서기 0년이 아니고 서기 1년입니다. 계산의 편의를 위해서

그레고리력으로 환산한 것입니다.

책의 예제를 보면 그레고리력의 서기 1년 1월 1일이 월요일이라는

조건으로 달력 프로그램을 작성하는 경우가 많습니다.)

 

그레고리력의 1년은 365.2425일 입니다. (천문학자들의 관측에 의한 1년은 365.2422....일입니다.)

 

0.2425 일을 표현하기 위해서 윤년을 두는데, 윤년을 두는 규칙은

 

400으로 나누어 떨어지는 해는 윤년입니다.    --- 1번

 

1번 이외의 해에서, 100으로 나누어 떨어지는 해는 평년입니다.   --- 2번

 

1, 2번 이외의 해에서 4로 나누어 떨어지는 해는 윤년입니다.  --- 3번

 

1, 2, 3번에 속하지 않는 해는 평년입니다.

 

윤년은 2월달의 날수가 29일입니다.

(나머지 달의 날수는 알고 계시겠죠?)

 

(우리나라 천문연구원에서는 그레고리력의 날짜가 1년에 0.0003일 정도 틀린것을 보정하기 위해서

3600년은 윤년이 아닌걸로 하는 규칙을 추가할 것을 제안하고 있습니다. 

달력의 규칙에 이 조항이 포함될지 안될지 아직 결정이 안됐습니다. 

참고로... 천문연구원에서 우리나라의 음력을 결정하고있습니다.)

 

요일은 0년 12월 31일 부터 몇일이나 지났는지 계산해서 7로 나누어서 나머지를 보면 알 수 있습니다.

 

나머지가 0이면 일요일, 1이면 월요일, ..., 6이면 토요일이 됩니다.

 

 

위의 규칙으로  달력을 어떻게 출력할지 큰 흐름을 생각해보죠.

 

 

1. 우선 출력할 달력의 year년과 month월을 입력 받습니다.

2. 0년 12월 31일부터 year년 month월 1일 까지 몇일이나 지났는지 계산합니다.

3. 계산한날을 7로 나눈 나머지를 요일로 합니다.

4. 1부터 요일에 맞추어서 그달의 끝날까지 차례대로 출력합니다.

 

 

1번은 쉽죠?

 

int year, month;

printf("달력을 출력할 년도와 월을 입력하세요.\n");

scanf("%d%d", &year, &month);

 

2번도 그렇게 어렵지 않습니다.

 

우선 총 날수를 저장할 변수를 선언해 두죠.

 

int totalday;

 

totalday  =

 (0년12월31일부터 year-1 년 12월 31일까지의 날수)                                           ----- 1)

+ ( year-1 년 12월 31일부터 year년 month-1월 끝날 까지의 날수)                       ----- 2)

+ 1                                                                                                                    --- ( 그 달의 1일 이므로)

이 됩니다. 

 

1) 은

(year-1) * 365 + (year-1년 까지 윤년의 날수)      

로 계산할수 있습니다.

 

윤년의 날수는 윤년의 정의에 따라서    (year-1)/400 - (year-1)/100 + (year-1)/4 가 됩니다.

(400으로 나누어 떨어지는 해의 수는 400으로 나눈 몫과 같습니다. 100과 4도 마찬가지입니다. )

 

int year_1;

 

year_1 = year-1;  이라고 두면 1)은

 

totalday = year_1*365 + year_1/4 - year_1/100 + year_1/400; 입니다.

 

 

 

2)를 계산하기 위해서는 각 달의 날수가 필요합니다.

 

int daysofmonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

 

그런데 year가 윤년이면 2월달이 29일이 되어야 하므로 윤년인지 검사를 해봐야됩니다.

 

if( !(year%4) && (year%100) || !(year%400) )        /* 윤년의 정의를 논리식으로 적으면 이렇게 됩니다. */
     daysofmonth[1] = 29;

 

이제 for문을 사용하면 2)번을 쉽게 계산할 수 있습니다.

 

for(i=0; i<month-1; i++)

      totalday += daysofmonth[i];

 

 

3)은 너무간단하죠?

totalday++;

 

 

3. 이제 총 날수를 구했으므로 요일을 구할수 있습니다.

 

int adayofweek;

adayofweek = totalday % 7;

 

 

4. 출력합니다.

 

 printf("\n\n     %4d년 %2d월\n\n", year, month);     
 printf(" 일 월 화 수 목 금 토\n");
 for(i=0;i<adayofweek; i++)                     /* 요일에 맞도록 공백을 출력합니다. */
  printf("   ");
 for(i=1;i<=daysofmonth[month-1]; i++)       /* 1부터 그 달의 끝날까지 차례대로 출력합니다 */
 {
      printf("%3d", i);
      if( !((i+adayofweek)%7) )                        /* 한주가 바뀌면 다음줄에 출력해 줍니다. */
         printf("\n");
 }

 printf("\n\n");

 

 

어렵지 않죠?

출처 네버 지식인

'☆C언어 > 소스' 카테고리의 다른 글

3n+1  (0) 2013.06.27
3n+1 재귀함수  (0) 2013.06.27
최소의 동전수 (재귀)  (0) 2013.06.23
c언어 숫자 변수에 문자입력시 출력  (0) 2012.10.10
사다리  (0) 2012.09.12