[Tmax 연수] C - 만년달력

#include <stdio.h>
#include <windows.h>
#include <wincon.h>
#include <conio.h>

#define DEFAULT_YEAR 2008
#define DEFAULT_MONTH 3
#define ESC   0x1b
#define UP    0x48
#define DOWN  0x50
#define LEFT  0x4b
#define RIGHT 0x4d

// 0     : 평년
// 그 외  : 윤년
int isLeapYear(int year) {
    return ((year % 4 == 0 && year % 100) || year % 400 == 0);
}

void gotoxy(int x, int y) {
    OORD Pos = { x - 1, y - 1 };
     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);
}

void blue() {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);
}

void red() {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
}

void white() {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}

int calculateDays(int year, int month) {
    int month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int i, days = 1;
    // 인자로 받은 전년도까지 일수 구하고

    for (i = 1; i < year; i++) {
        days += 365;
        if (isLeapYear(i))
            days++;
    }

    // 인자로 받은 전달까지 일수를 구한 후에
    for (i = 1; i < month; i++) {
        days += month_days[i - 1];
        if (i == 2 && isLeapYear(year))
            days++;
    }

    // 구한 일수를 리턴
    return days;
}

void printCalendar(int year, int month) {
    int i, j;
    int month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int days = calculateDays(year, month);
    if (!days) {
        printf("달력을 출력할 수 없습니다!");
        return;
    }

    // 윤년인 경우 달력 출력시 1일 추가
    if (isLeapYear(year))
        month_days[1] += 1;

    white();

    printf("          [ %4d.%02d ]\n", year, month);
    printf("-----------------------------------\n");
    printf("SUN  MON  TUE  WED  THU  FRI  SAT  \n");
    printf("-----------------------------------\n");

    // 첫날 시작 요일 전까지 공백 찍어줌
    for (i = 0, j = (days) % 7; i < j; i++) {
        printf("     ");
    }
    
    // 요일 출력
    for (i = 1; i <= month_days[month - 1]; i++) {
        switch ((days + i - 1) % 7) {
            case 0 : 
                red();
                printf("%3d  ", i);
                break; // 일요일은 빨간색으로
            case 6 : 
                blue();
                printf("%3d\n", i);
                break; // 토요일에 줄바꿈
            default : 
                white();
                printf("%3d  ", i);
                break; // 평일
        }
    }

    // 전월에 출력된 부분 삭제
    for (white(); i <= 50; i++) {
        switch ((days + i - 1) % 7) {
            case 6 : 
                blue();
                printf("   \n");
                break; // 토요일에 줄바꿈
            default :
                white();
                printf("     ");
                break; // 평일
        }
    }
    printf("\n");
}

int main() {
    int year  = DEFAULT_YEAR;
    int month = DEFAULT_MONTH;
    char inp;

    do {
        gotoxy(1, 1);
        printCalendar(year, month);

        inp = getch();

        if (inp == 0 || inp == -32) { // 특수문자 시작 코드
            inp = getch();
            switch (inp) {
                case UP : // 전년도
                    if (year - 1 > 1)   year -= 1;
                    break; 
                case DOWN : // 다음 연도
                    year += 1;
                    break;
                case LEFT : // 전월
                    if (month - 1 > 0)
                        month -= 1;
                    else {
                        month = 12;

                        if (year - 1 > 1)
                            year -= 1;
                    }
                    break; 
                case RIGHT : // 다음 월
                    if (month + 1 < 13)
                        month += 1;
                    else
                        month = 1, year += 1;
                    break;
            }
        }
        white(); 
    } while (inp != ESC);
}
Back