今日はちょっと趣向を変えてプログラミング講座。
自分で作ったので、他サイトより複雑かもしれません。
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;iprintf(" ");
}
for(i=zeller(seireki,1+m,1);i<7;i++){
printf("%2d " , hiduke);
hiduke++;
}
printf(" ");
/* 真ん中カレンダー */
for(i=0;iprintf(" ");
}
for(i=zeller(seireki,2+m,1);i<7;i++){
printf("%2d " , hiduke2);
hiduke2++;
}
printf(" ");
/* 右カレンダー */
for(i=0;iprintf(" ");
}
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;hidukeprintf("%2d " , hiduke);
hiduke++;
}
for(;i<7;i++){
printf(" ");
}
printf(" ");
/* 真ん中カレンダー */
for(i=0;hiduke2printf("%2d " , hiduke2);
hiduke2++;
}
for(;i<7;i++){
printf(" ");
}
printf(" ");
/* 右カレンダー */
for(i=0;hiduke3printf("%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;iprintf(" ");
}
for(i=zeller(seireki,tuki,1);i<7;i++){
printf("%2d " , hiduke);
hiduke++;
}
printf("\n");
for(j=1;j<7;j++){
for(i=0;hidukeprintf("%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
}
}
