C言語でカレンダー表示

昔似たモノを作ったはずなのに見つかりません。

なので作りなおしました。

f:id:a-san:20210320204225p:plain

引数なしで今月のカレンダー、年月を指定すればその月のカレンダーを表示します。


まずは、Zellerの公式が必要。年月日から曜日を求めるやつ。

それと、閏年かどうかを判定する関数。

当時は2000年より前だったから、2000年に正しく動くかどうか何度もテストしました。

今は各種ライブラリが用意されているけれど、昔はみんな手作りしていました。

VisualStudioで開発したのだけれど、localtimeで警告されるので、#pragmaで無効にしてます。

 

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#pragma warning(disable: 4996)    // 'localtime': This function or variable may be unsafe. Consider using localtime_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

// ツェラーの公式
// 1:月 2:火 3:水 4:木 5:金 6:土 7:日
int getZeller(int yyyy, int mm, int dd)
{
    int c, y, gamma, d;
    if (mm <= 2) {
        yyyy -= 1;
        mm += 12;
    }
    c = yyyy / 100;
    y = yyyy % 100;
    gamma = 5 * c + (c / 4);
    d = (dd + (26 * (mm + 1) / 10) + y + y / 4 + gamma + 5) % 7 + 1;
    return d;
}

// 閏年か?
// 1:閏年     0:閏年ではない
int isLeapYear(int yyyy)
{
    return yyyy % 4 == 0 && yyyy % 100 != 0 || yyyy % 400 == 0;
}

// 指定した年月の日数を返す
// ex. (2000, 2) => 29
int getDays(int yyyy, int mm)
{
    switch (mm) {
        case 2:
            return isLeapYear(yyyy) ? 29 : 28;
        case 4: 
        case 6:
        case 9:
        case 11:
            return 30;
        default:
            return 31;
    }
}

void dispCalendar(int yyyy, int mm)
{
    int dd, days, youbi, i;

    printf(" *** %4d%2d月 ***\n", yyyy, mm);
    printf("日 月 火 水 木 金 土\n");
    days = getDays(yyyy, mm);
    youbi = getZeller(yyyy, mm, 1);
    if (youbi != 7) {
        for (i = 0; i < youbi; i++) {
            printf("   ");
        }
    }
    for (dd = 1; dd <= days; dd++) {
        printf("%2d ", dd);
        if ((dd + youbi) % 7 == 0) printf("\n");
    }
}

int main(int argc, char* argv[])
{
    int yyyy, mm;

    fprintf(stderr, "calen version 0.0\n");
    fprintf(stderr, "Copyright (C) Yoshinori Watanabe 2021. All Rights Reserved.\n");
    fprintf(stderr, "\n");
    
    if (argc == 3) {
        // 引数より年月を取得
        yyyy = atoi(argv[1]);
        mm = atoi(argv[2]);
    }
    else if (argc == 1) {
        // 現在日時より年月を取得
        time_t timer;
        struct tm* local;

        timer = time(NULL);
        local = localtime(&timer);
        yyyy = local->tm_year + 1900;
        mm = local->tm_mon + 1;
    }
    else {
        // 使い方を説明
        printf("usage: calen <yyyy> <mm>\n");
        return 1;
    }

    dispCalendar(yyyy, mm);

    return 0;
}