본문 바로가기

컴퓨터/언어,프로그래밍

[C 언어] 달력만들기


/****************************************************************
 >> 달력만들기 프로그램
  - 년도, 월을 입력 받음
  - 월의 일수를 구해야 함
  - 월의 첫째 날(예: 5월 1일, 3월 1일)의 요일을 구해야 함

   => getWeekDay()함수 사용하세요
   - 달력을 화면에 표시해주어야 함

  >> 출력 예  
        <2007년 5월>
  ==========================
     일    월    화    수   목    금    토
  ==========================
          1     2     3     4     5
      6     7     8     9    10    11   12
     13   14    15    16    17   18   19
     20   21    22    23    24   25   26
     27   28    29    30    31   
  ==========================
****************************************************************/
#include <stdio.h>

#define ARR_SIZE_R 6  // 배열의 행의 크기
#define ARR_SIZE_C 7  // 배열의 열의 크기

int display(void);          // 초기화면 출력 함수
int input_num(void);        // 입력 함수
int getWeekDay(int, int);       // 각 월의 첫 요일을 구해주는 함수
int intercalary_year(int);        // 윤년 구하는 함수
int calendar(int, int, int, int [][ARR_SIZE_C]);  // 달력 만드는 함수
int print_cal(int, int, int, int [][ARR_SIZE_C]);   // 달력 출력 함수

// 메인 함수
int main(void)
{
 int arrCalendar[ARR_SIZE_R][ARR_SIZE_C]={0};  // 달력 배열 선언 (0으로 초기화)
 int nYear, nMonth, nDay, intercalary, nMaxrow;    // 년도, 월, 요일, 윤달, 달력의 줄 수

 display();   // 초기화면 출력 함수 호출
 
 nYear = input_num();   // 년도 입력 (입력 함수 호출)
 nMonth = input_num();  // 월 입력  (입력 함수 호출)

 if(nYear < 1)    // 년도가 1보다 작을 경우
  nYear = 1;   // 년도를 1로 변경
 
 if(nMonth > 12)   // 월의 값이 12보다 클경우
  nMonth = 12;  // 월의 값을 12로 변경
 else if(nMonth < 1)  // 월의 값이 1보다 작을 경우
  nMonth = 1;   // 월의 값을 1로 변경

 nDay = getWeekDay(nYear, nMonth);   // 각 월의 첫 요일을 구해주는 함수 호출 (매개변수: 년, 월)
 
 intercalary = intercalary_year(nYear);    // 윤년을 구하는 함수 호출 (매개변수: 년)

 nMaxrow = calendar(nDay, nMonth, intercalary, arrCalendar);   // 달력 만드는 함수(매개변수: 첫요일, 월, 윤년여부, 달력배열)
                      // - 사용되는 달력(달)의 최대 줄(행)의 값 받음
 print_cal(nYear, nMonth, nMaxrow, arrCalendar);   // 달력 출력 함수 (매개변수: 년, 월, 달력의 줄 수, 달력배열)

 return 0;
}

// 초기화면 출력 함수
int display(void)
{
 puts("달력(해당 월) 출력 프로그램");
 puts("===========================");

 printf("년도와 월을 입력하시오(예. 2007 5) : ");
 
 return 0;
}

// 입력 함수
int input_num(void)
{
 int nNum;

 scanf("%d", &nNum);  // 년도나 월을 입력 받음

 return nNum;
}

// 달력 만드는 함수
int calendar(int nDay, int nMonth, int intercalary, int arrCalendar[][ARR_SIZE_C])
{
 int nIdx_r, nIdx_c, nCntmax, nMaxrow, nCnt=0;
 
 if(nMonth == 2 && intercalary == 1)   // 2월이고 윤년일 경우
  nCntmax = 29;         // 달력(월)의 최대 날짜를 29일로 지정
 else if(nMonth == 2 && intercalary == 0)  // 2월이고 윤년이 아닐 경우
  nCntmax = 28;         // 달력(월)의 최대 날짜를 28일로 지정
 else if(nMonth < 8 && nMonth%2 == 1)  // 2월이 아니고 8월 보다 작고 홀수 달일 경우
  nCntmax = 31;         // 달력(월)의 최대 날짜를 31일로 지정
 else if(nMonth < 8 && nMonth%2 == 0)  // 2월이 아니고 8월 보다 작고 짝수 달일 경우
  nCntmax = 30;         // 달력(월)의 최대 날짜를 30일로 지정
 else if(nMonth >= 8 && nMonth%2 == 0)  // 2월이 아니고 8월 보다 크거나 같고 짝수 달일 경우
  nCntmax = 31;         // 달력(월)의 최대 날짜를 31일로 지정
 else if(nMonth >= 8 && nMonth%2 == 1)  // 2월이 아니고 8월 보다 크거나 같고 홀수 달일 경우
  nCntmax = 30;         // 달력(월)의 최대 날짜를 30으로 지정 

 // 사용되지 않는 빈줄(행)을 반복문에서 사용하지 않게 하기 위해
 if(nDay+nCntmax > 35)     // 첫요일의 값과 해당 월의 최대 날짜를 더한 값이 35보다 크면
  nMaxrow = 6;      // 달력의 줄(행)의 수를 6으로 함
 else if(nDay+nCntmax <= 28)   // 첫요일의 값과 해당 월의 최대 날짜를 더한 값이 28보다 작거나 같으면(28이면)
  nMaxrow = 4;      // 달력의 줄(행)의 수를 4로 함
 else          // 그 외의 경우
  nMaxrow = 5;      // 달력의 줄(행)의 수를 5로 함

 for(nIdx_r=0; nIdx_r<nMaxrow; nIdx_r++)  // 달력의 사용되는 줄(행) 만큼 반복
 {
  for(nIdx_c=nDay; nIdx_c<ARR_SIZE_C; nIdx_c++)  // 달력의 칸의 수 만큼 반복 [처음 초기값은 첫요일의 값으로 줌(처음 저장될 위치 조정 위해)]
  {
   if(nCnt < nCntmax)    // 위에서 구한 해당 달의 최대 날짜 만큼만 값을 저장
   {
    arrCalendar[nIdx_r][nIdx_c] = ++nCnt;  // 증가하면서 값 배열에 저장
   }   
  }

  nDay=0;  // 배열 칸(열)이 초기값을 다시 0으로 변경 (배열의 첫 칸부터 저장할 수 있게 함)
 }

 return nMaxrow;  // 해당월의 달력 줄 수의 값을 돌려줌
}

// 달력 출력 함수
int print_cal(int nYear, int nMonth, int nMaxrow, int arrCalendar[][ARR_SIZE_C] )
{
 int nIdx_r, nIdx_c;

 printf("\n\t <%d년 %d월>\n", nYear, nMonth);   // 해당 년도와 달(월)을 출력
 puts(" ============================");
 puts("  일  월  화  수  목  금  토 ");
 puts(" ============================");

 for(nIdx_r=0; nIdx_r<nMaxrow; nIdx_r++)   // 인자로 받은 달력(월)에 사용된 줄(행) 만큼 반복
 {
  for(nIdx_c=0; nIdx_c<ARR_SIZE_C; nIdx_c++)  // 배열의 칸(열)의 수 만큼 반복
  {
   if(arrCalendar[nIdx_r][nIdx_c] != 0)     // 배열에 저장된 값이 0이 아니면
    printf("%4d", arrCalendar[nIdx_r][nIdx_c]);  // 각 배열 인덱스의 값 출력
   else       // 배열에 저장된 값이 0일 경우
    printf("    ");    // 공백을 출력
  }

  puts("");   // 줄바꿈
 }

 puts(" ============================");

 return 0;
}

// 각 월의 첫 요일을 구해주는 함수 [현재 달력에 사용 중인 '그레고리 력' 공식]
int getWeekDay(int nYear, int nMonth)
{
 int nCentury, nWDay;

 if((nMonth == 1) || (nMonth == 2))
 {
  nYear--;
  nMonth += 12;
 }
 
    // 년도를 앞의 두자리와 뒤의 두자리로 나눈다
    nCentury = nYear / 100;
    nYear = nYear % 100;
         
    // 해당 월 1일의 요일 구하는 공식
    nWDay = ((21 * nCentury / 4) + (5 * nYear / 4) + (26 * (nMonth + 1)) / 10) % 7;

 return nWDay;    // << 리턴값 >>
         // 0 : 일요일        1 : 월요일           2 : 화요일             3 : 수요일
         // 4 : 목요일        5 : 금요일           6 : 토요일
}

// 윤년 구하는 함수
int intercalary_year(int nYear)

 int intercalary;

 if(nYear%4 == 0)
 {
  if(nYear%100 == 0)
  {
   if(nYear%400 == 0)
    intercalary = 1;
   else
    intercalary = 0;
  }
  else
   intercalary = 1;
 }
 else
  intercalary = 0;

 return intercalary;  // 1 : 윤년, 0 : 평년
}

제주삼다수, 2L,... 오뚜기 진라면 매운... 상하목장 유기농 흰... 남양 프렌치카페 카... 고려인삼유통 홍삼 ... 종근당건강 오메가3... 요이치 카링 유무선...