シミュレーションラブ

ニートはニートの悩みがあることを知らない一般人は、幸せだね。

C言語で万年カレンダーを作成してみた。

 今日はちょっと趣向を変えてプログラミング講座。
 自分で作ったので、他サイトより複雑かもしれません。

 LinuxやUnixの「cal」コマンドでは、引数に西暦を入力するだけで、その西暦のグレゴリオ暦が表示されます。実際、プログラマーになりたての頃には、練習として万年カレンダーを作成して下さいと上司から言われることが多々あるはず。
 つうこって、当方もいまさらながら万年カレンダーをC言語で作ってみた。まぁ、作ったのはWindowsのVC++2008の最新環境なので、他環境で動くかどうかは不明。

 Linuxで表示されるする時、西暦は横に「1・2・3」月、改行して「4・5・6」月・・・といった風に表示されるのでちょっと長くなってしまった。もう少しサブルーチン化できそうだけど、めんどいのでここまで。

 プロトタイプのzellerは、「ツェラーの公式」を使ったもの。これ、すごいんですよ。知ってる人はかなりお得。この計算をするだけで、年、月、日にちを入力するだけで、その日が何曜日なのか計算で求めることが出来るんですね。

 urutoshi(int a);は、そのままうるう年計算。戻り値が、1ならうるう年ってことですね。

 万年カレンダーでおもしろいのは、Linuxなどの環境で、1752年の9月を表示することです。それはここで触れないでおきますので、見てのお楽しみ。最近まで知りませんでした(ちなみに下のプログラムには実装されてないよ)。

#include "stdafx.h" #include #include         //exit

int zeller(int seirekiz, int tukiz, int hidukez);  /* ツェラーの公式 … 西暦の年、月、日からその日が何曜日かを算出する公式 */
int urutoshi(int a);                  /* 閏年                    */

int _tmain(int argc, char *argv[]){
    int seireki,tuki,i,j,k,hiduke,hiduke2,hiduke3,m=0;   /* 変数初期化                 */
    int owarituki[13]={-1,31,28,31,30,31,30,31,31,30,31,30,31};  /* 各月、何日まであるか(最初の配列は0)     */
    printf("\n 例: 200904\n 西暦と月を入力してください->");

    /*
    scanf("%4d%d", &seireki, &tuki);                    // 最初の4つをseirekiへ、残りをtukiへ
    上の例だと、入力が「2009」のみの場合、seirekiに入力され、
    その後変数tukiの入力待ち状態となる。
    その入力待ちを回避して、「2009」の入力だけで2009年度カレンダーを全て表示されるようにする。
    */
    //----入力待ち回避 ここから----
    char a[20];
    scanf("%19[^\n]%*[^\n]", a);
    getchar();
    if(sscanf(a, "%4d %d", &seireki, &tuki) != 2 ){
        printf("\n");
    }
    //----入力待ち回避 ここまで----

    if (urutoshi(seireki)==1){
        owarituki[2]+=1;                        /* 閏年なら2月の28を29日にする             */
    }
    printf("--------------------------------------------------------------------\n");

    if (seireki<=1751){
        printf("1751年前は表示しないよ!!");    
        exit(0);
    }

    if (!(tuki>=1 && tuki<=12)){                                    /* tukiが1月-12月ではなかったら全表示     */
        for(k=1;k<5;k++){                                    /* 5行全て表示する                 */
            /* header */
            hiduke=1;                                    /* 左カレンダー 日付初期化             */
            hiduke2=1;                                    /* 真ん中カレンダー 日付初期化             */
            hiduke3=1;                                    /* 右カレンダー 日付初期化             */
            for(j=1;j<=3;j++){
                printf("%4d年%2d月のカレンダー ", seireki, j+m);
            }
            printf("\n");
            for(j=1;j<=3;j++){
                printf("日 月 火 水 木 金 土 ");
            }
            printf("\n");

            /* 1行目 */
            /* 左カレンダー */
            for(i=0;i                 printf(" ");
            }
            for(i=zeller(seireki,1+m,1);i<7;i++){
                printf("%2d " , hiduke);
                hiduke++;
            }
            printf(" ");
            /* 真ん中カレンダー */
            for(i=0;i                 printf(" ");
            }
            for(i=zeller(seireki,2+m,1);i<7;i++){
                printf("%2d " , hiduke2);
                hiduke2++;
            }
            printf(" ");
            /* 右カレンダー */
            for(i=0;i                 printf(" ");
            }
            for(i=zeller(seireki,3+m,1);i<7;i++){
                printf("%2d " , hiduke3);
                hiduke3++;
            }
            printf("\n");

            /* footer */
            for(j=1;j<7;j++){
                /* 左カレンダー */
                for(i=0;hiduke                     printf("%2d " , hiduke);
                    hiduke++;
                }
                for(;i<7;i++){
                    printf(" ");
                }
                printf(" ");
                /* 真ん中カレンダー */
                for(i=0;hiduke2                     printf("%2d " , hiduke2);
                    hiduke2++;
                }
                for(;i<7;i++){
                    printf(" ");
                }
                printf(" ");
                /* 右カレンダー */
                for(i=0;hiduke3                     printf("%2d " , hiduke3);
                    hiduke3++;
                }
                for(;i<7;i++){
                    printf(" ");
                }
                printf("\n");
            }
            m+=3;    
        }
    }else{
        /* 1月(ひとつき)だけ表示 */
        hiduke=1;
        printf("%d年%2d月のカレンダー\n日 月 火 水 木 金 土\n", seireki, tuki);
        for(i=0;i             printf(" ");
        }
        for(i=zeller(seireki,tuki,1);i<7;i++){
            printf("%2d " , hiduke);
            hiduke++;
        }
        printf("\n");
        for(j=1;j<7;j++){
            for(i=0;hiduke                 printf("%2d " , hiduke);
                hiduke++;
            }
            printf("\n");
        }
    }
    return 0;
}

/* ツェラーの公式 */
int zeller(int seirekiz, int tukiz, int hidukez){
        int z=0;
        if ( tukiz==1 || tukiz==2 ){
            tukiz+=12;                                     /* 1月と2月の時は13月、14月にしないとうまく計算できない */
            seirekiz--;
        }
        //z=(seirekiz+(seirekiz/4)-(seirekiz/100)+(seirekiz/400)+(2.6*tukiz+1.6)+hidukez);
        z=seirekiz+seirekiz/4-seirekiz/100+seirekiz/400+(13*tukiz+8)/5+hidukez;
        z%=7;
        return z;
}

/* 4で割り切れる年は閏年。ただし、西暦年が100で割り切れる年は平年。ただし、西暦年が400で割り切れる年は閏年。 */
int urutoshi(int a){
    if((a%4 == 0 && a%100!=0) || a%400 ==0){
        return 1;                                        // 閏年だったら1を返す
    }else{
        return 0;                                        // そうじゃなかったら0
    }
}


Posted by iamweak - 2009年05月18日 20:24 | トラックバック (0)

この記事のトラックバックURL


※TBは、当サイトへリンクが無いと自動拒否されます(承認制)。記事に関係ないTBはご遠慮願います。

この記事に対するトラックバック

この記事に対するトラックバックはまだありません。



Powered by Movable Type 3.33-ja and Wandering Wind
Copyright : (C) iamweak All Rights Reserved.