• 締切済み

カレンダーがうまく表示されない

開始月と終了月を指定して、3か月ごとにカレンダーを改行する プログラムを作ってみました。 ところが、動作をさせてみたところ7月が配列tuki[12]において31日 と指定しているのにも関わらず25日分しか表示されません。 それと、たまに4月分が24日分しか表示されません。(試した限りでは、 4月を終了月に指定するとそうなりました。) なにがおかしいためにこうなってしまうのでしょうか。 よろしくお願いいたします。 #include<stdio.h> #include<string.h> /*月の最初の日をメインプログラムに返す*/ int getyoubi(int year,int month,int day) { if(month==1 || month==2 ) { year--; month +=12; } return ((year+year/4-year/100+year/400+(13*month+8)/5 + day)%7); } /*カレンダーを3か月分表示させる*/ void print(char s[3][7][22],int n) { int i,j; for(i=0;i<n;i++) { printf("%s ",s[i][0]); } printf("\n"); for(i=0;i<n;i++) { printf(" 日 月 火 水 木 金 土 "); } printf("\n"); for(i=0;i<n;i++) { printf("---------------------- "); } printf("\n"); for(i=1;i<7;i++) { for(j=0;j<n;j++) { printf("%s ",s[j][i]); } printf("\n"); } printf("\n"); } int main(void) { int nen1,tuki1,nen2,tuki2,tukiho,nenho,tukih,w,j; char sbuf[3][7][22]; int tuki[12]={31,28,31,30,31,30,31,31,30,31,30,31}; int k; char tmp[4]; int count=0; printf("カレンダーを表示します。\n"); printf("開始年月を入力せよ。\n"); printf("年:"); scanf("%d",&nen1); printf("月:"); scanf("%d",&tuki1); printf("終了年月を入力せよ。\n"); printf("年:"); scanf("%d",&nen2); printf("月:"); scanf("%d",&tuki2); /*最大3カ月分のカレンダーを格納する。*/ do{ w=getyoubi(nen1,tuki1,1); sprintf(sbuf[count][0],"%10d / %02d ",nen1,tuki1); for(k=1;k<7;k++) { sbuf[count][k][0]='\0'; } sprintf(sbuf[count][1],"%*s",3*w,""); k=1; for(j=1;j<=tuki[tuki1-1];j++) { sprintf(tmp,"%3d",j); strcat(sbuf[count][k],tmp); if((j+w-1)%7==6) { k++; } } do{ if((j+w-1)%7==6) { sprintf(sbuf[count][k],"%21s",""); } else { do{ strcat(sbuf[count][k]," "); j++; }while((j+w-1)%7!=0); } k++; }while(k!=7); count++; if(count==3) { print(sbuf,count); count=0; } tuki1++; if(tuki1==13) { tuki1=1; nen1++; } }while(nen1<nen2 || nen1==nen2 && tuki1<=tuki2); if(count) { print(sbuf,count); } return 0; }

みんなの回答

回答No.3

 ↓のプログラムは、参照URLから完動することを確認し、printf() を sprintf() に換え、3ヶ月分確保して処理しています。おそらく、出力にバグがあるのではないでしょうか。 /* Calender program by Mac OSX * file name: rin.c * compile: gcc rin.c * execution: ./a.out */ #include <stdio.h> #define LINE_NUM 9 #define BUFF_SIZE 24 #define LESS_ 0 #define MIDDLE 1 #define GREATE 2 #define input(comment, value) {printf(comment); scanf("%d", value);} struct set1 { char line[LINE_NUM][BUFF_SIZE]; } month[3]; void get_calen(int, int, int); int main(void) { int y, m, /* 年 月 */ i, j; /* 年月を入力 */ input("year=", &y); input("manth=", &m); get_calen(MIDDLE, y, m); // 当月 m == 1 ? get_calen(LESS_, y - 1, 12) : get_calen(LESS_, y, m - 1); m == 12 ? get_calen(GREATE, y + 1, 1) : get_calen(GREATE, y, m + 1); printf("\n"); for (j = 0; j < 9; j++) { // 各行 for (i = 0; i < 3; i++) // 3ヶ月分を printf("%-21s ", month[i].line[j]); // 左詰めで出力 printf("\n"); } return 0; } void get_calen(int n, int y, int m) { int d, /* 日 */ wd, /* 曜日 */ dm, /* 月の日数 */ i, /* 繰り返し用のカウンタ */ c; /* line[添字] */ char *j; /* 表示年月 */ c = 0; sprintf(month[n].line[c], "%4s[%d年 %d月]", " ", y, m); /* y年m月が何日あるか */ switch(m) { case 2: if ( y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) dm = 29 ; /* 閏年 */ else dm = 28 ; break ; case 4: case 6: case 9: case 11: dm = 30 ; break ; default: dm = 31 ; break ; } /* y年m月1日の曜日を求める */ if (m == 1 || m == 2) { y-- ; m += 12 ; } wd = (y + y/4 - y/100 + y/400 + (13*m+8)/5 +1) % 7 ; /* 曜日欄 */ sprintf(month[n].line[++c], " 日 月 火 水 木 金 土"); sprintf(month[n].line[++c], " --------------------"); /* 空白の表示 */ j = month[n].line[++c]; for (i = 0; i < wd; i++) j += sprintf(j, " %2s", " "); /* 日付の表示 */ for (i = 1; i <= dm; i++) { j += sprintf(j, " %2d", i); wd ++ ; if (wd % 7 == 0) j = month[n].line[++c]; } }

参考URL:
http://www.asahi-net.or.jp/~qb3k-kwsk/rpg/program/tutorial/t02s.html
rinnshan
質問者

お礼

URLまで張っていただき誠にありがとうございました。 参考にさせていただきたいと思います。

回答No.2

追記: 7月の方は良く考えてないけど、手元の環境では治っちゃってる #ログとらないもんだから無意識に直しちゃって、後でどう修正したのかわからなくなることがたまにあるorz #月がずれてたのも同時に治っているなあ> 2010-01-01/2010-03-01 #まだ、3つ「まで」表示という部分には至ってない。頑張って直すべし。 #この公式って紀元前とかには通用しないのでは?西暦0年とか入力された時の扱いも含めて考える。 #2番目の日付に1番目の日付よりも前の日付を指定したらどうなるか試していない。 #ところで、2012年って4で割れて100で割れないけど…いいの?2月。

rinnshan
質問者

お礼

回答ありがとうございます。 そのあたりの細かいところはあまり気にせずにやっているので 機会があれば修正したいと思います。

回答No.1

いくつか質問。 その1: > }while((j+w-1)%7!=0); は > }while((j+w-1)%7!=6); じゃないの? その2: tukiho,nenho,tukih はこれから使うのかな? その3(本題): 4月の処理をしているときに、 if((j+w-1)%7==6) で分岐されるよね?一回目にはどっちを通るのかな?この時のjの値は何かな? #「構造体」とか調べられるとコードが多少見やすくなる。 #あと、main関数にやることを殆どそのまま書こうとしていて少し長くなっている気がするので、うまい具合に関数を分割できたら見やすくなるんじゃないかな?

rinnshan
質問者

お礼

>その1: 自分でもよくわからないのですが、どうやら変数jは最終日の次の日になってるので、 6あまったら改行するのではなく0の時に改行をするようです。 実際に、それで私の環境ではうまく動作しました。 >その2: tukiho,nenho,tukih はこれから使うのかな? いえ、前に修正した時の残り火です。すっかり忘れておりました。 混乱をさせてしまって申し訳ございません。 >4月の処理をしているときに、 if((j+w-1)%7==6) で分岐されるよね?一回目にはどっちを通るのかな?この時のjの値は何かな? 申し訳ございません。おっしゃっている意味がよくわからないです。 回答ありがとうございました。

関連するQ&A

専門家に質問してみよう