Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++로 특정 연도의 달력 출력하기 (전체 코드 및 실행 결과)


이 문제에서는 하나의 연도가 입력으로 주어지며, 해당 연도의 전체 달력(1월~12월)을 콘솔에 출력하는 것이 목표입니다.

연간 달력은 매달의 날짜와 요일을 모두 보여줍니다. 이 글에서는 주어진 연도의 달력을 화면에 출력하는 C++ 프로그램을 단계별로 만들어 보겠습니다.

달력을 만들기 위해서는 크게 두 가지 정보를 계산해야 합니다.

1. 특정 월의 일수 구하기

각 월마다 날짜 수가 다르므로 이를 정확히 반영해야 합니다.

  • 1월, 3월, 5월, 7월, 8월, 10월, 12월은 31일입니다.
  • 2월은 평년에는 28일, 윤년에는 29일입니다.
  • 4월, 6월, 9월, 11월은 30일입니다.

윤년 판별 조건은 다음과 같습니다. 연도가 400으로 나누어 떨어지거나, 4로 나누어 떨어지면서 100으로는 나누어 떨어지지 않으면 윤년입니다.

2. 각 월의 시작 요일 구하기

연도와 월 정보를 바탕으로 그 달 1일이 무슨 요일(일요일~토요일)인지 계산합니다. 이 값에 따라 달력 첫 줄에서 숫자 1이 출력될 위치가 결정됩니다.

요일 계산에는 널리 알려진 사카모토(Sakamoto) 알고리즘을 활용합니다. 이 방법은 미리 정의된 오프셋 배열과 연도 보정값을 사용해 복잡한 조건문 없이 한 번의 수식으로 요일을 구할 수 있습니다.

C++ 구현 예제

다음은 2019년 달력을 출력하는 완전한 프로그램입니다.

#include<iostream>
using namespace std;
int dayNumber(int day, int month, int year){
    static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
    year -= month < 3;
    return ( year + year/4 - year/100 + year/400 + t[month-1] + day) % 7;
}
string getMonthName(int monthNumber){
    string months[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
    return (months[monthNumber]);
}
int numberOfDays (int monthNumber, int year){
    switch(monthNumber){
       case 0 :
       case 2 :
       case 4 :
       case 6 :
       case 7 :
       case 9 :
       case 11: return(31);
        break;
       case 1 :
           if (year % 400 == 0 || (year % 4 == 0 && year %100 != 0))
             return (29);
          else
             return (28);
        break;
       case 3 :
       case 5 :
       case 8 :
       case 10 : return(30);
        break;
    }
}
void printCalendar(int year){
    cout<<"\t\t\t Calendar - Year "<<year;
    int days;
    int current = dayNumber (1, 1, year);
    for (int i = 0; i < 12; i++){
        days = numberOfDays (i, year);
        cout<<endl<<"\t\t ----X----"<<getMonthName (i).c_str()<<"----X---- \t\t"<<endl;
        cout<<" Sun Mon Tue Wed Thu Fri Sat \n";
        int k;
        for (k = 0; k < current; k++)
            cout<<"\t";
        for (int j = 1; j <= days; j++){
            printf("%5d", j);
            if (++k > 6){
                k = 0;
                cout<<endl;
            }
        }
        if (k)
            cout<<endl;
            current = k;
        }
    return;
}
int main(){
    int year = 2019;
    printCalendar(year);
    return (0);
}

코드 설명

  • dayNumber(): 특정 날짜의 요일을 0(일요일)~6(토요일) 범위의 값으로 반환합니다.
  • getMonthName(): 월 번호(0~11)에 해당하는 영문 월 이름을 반환합니다.
  • numberOfDays(): 해당 월의 일수를 반환하며, 2월은 윤년 여부를 검사해 28일 또는 29일을 결정합니다.
  • printCalendar(): 1월부터 12월까지 순회하며 각 달의 제목과 요일 헤더를 출력한 뒤, 1일이 시작되는 요일만큼 공백을 두고 날짜를 정렬해 출력합니다. 또한 지난 달의 마지막 요일 위치를 다음 달의 시작 위치로 이어받아 자연스럽게 연결합니다.

출력 결과

Calendar - Year 2019
----X----January----X----
Sun Mon Tue Wed Thu Fri Sat
         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
----X----February----X----
Sun Mon Tue Wed Thu Fri Sat
                        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
----X----March----X----
Sun Mon Tue Wed Thu Fri Sat
                        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
----X----April----X----
Sun Mon Tue Wed Thu Fri Sat
      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
----X----May----X----
Sun Mon Tue Wed Thu Fri Sat
              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
----X----June----X----
Sun Mon Tue Wed Thu Fri Sat
                           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
----X----July----X----
Sun Mon Tue Wed Thu Fri Sat
      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
----X----August----X----
Sun Mon Tue Wed Thu Fri Sat
                  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
----X----September----X----
Sun Mon Tue Wed Thu Fri Sat
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
----X----October----X----
Sun Mon Tue Wed Thu Fri Sat
        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
----X----November----X----
Sun Mon Tue Wed Thu Fri Sat
                        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
----X----December----X----
Sun Mon Tue Wed Thu Fri Sat
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