明解C言語 中級の6章の自由課題解いてみた 前編

やっとできたー、だいぶ期間が開いてしまったのでとりあえず前編で、課題6-1から課題6-4までです。

んで、6-1から6-4までは全部6章のList6-12のプログラムを編集する問題なので、1個のプログラムに全部やりました。

とりあえず問題。

6-1 横に3個並べる3か月分のカレンダーの間に、3個の空白文字があるが、右端にはいらないので70桁のコンソールに入りきらない。入るようにしんさい。

6-2 開始年月と終了年月のチェックをしてないので、チェックを入れんさい。

6-3 各月を6週間分とっているが、必要なとこだけに合わせんさい。

6-4 カレンダーがずれないように、月の最終日以降に空白文字で埋めている。表示幅を指定して整形すればその部分は必要なくなるので、そうしんさい。

てな感じです。詰まったのが6-3で、ポインタで比較してた部分を*bufにして中身を比較するようにしたらやっといけた。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int mday[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

int dayofweek(int year, int month, int day);

int is_leap(int year);

int monthdays(int year, int month);

void make_calendar(int y, int m, char s[7][22]);

void print(char sbuf[3][7][22], int n);

void put_calendar(int y1, int m1, int y2, int m2);

int main(void)
{
   int y1, m1, y2, m2;
   int retry=0;

   do{
   if(retry==1){
     puts("再入力してください。");
     retry=0;
   }else
     printf("カレンダーを表示します。\n");

   printf("開始年月日は?\n");
   printf("年:");         scanf("%d", &y1);
   printf("月:");         scanf("%d", &m1);

   printf("終了年月は?\n");
   printf("年:");         scanf("%d", &y2);
   printf("月:");         scanf("%d", &m2);

   if(y1 > y2){
     puts("開始年の方が大きいよ");
     retry=1;
   }
   if(m1 < 1 || m1 > 12){
     puts("開始の月がおかしいよ");
     retry=1;
   }
   if(m2 < 1 || m2 > 12){
     puts("終了の月がおかしいよ");
     retry=1;
   }
   }while(retry==1);

   putchar('\n');

   put_calendar(y1, m1, y2, m2);

   return 0;
}

int dayofweek(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);
}

int is_leap(int year)
{
  return(year % 4 == 0 && year % 100 != 0 || year % 400 == 0);
}

int monthdays(int year, int month)
{
  if(month-- != 2)
   return (mday[month]);
  return(mday[month] + is_leap(year));
}

void make_calendar(int y, int m, char s[7][22])
{
  int i, k;
  int wd = dayofweek(y, m, 1);
  int mdays = monthdays(y, m);
  char tmp[4];

  sprintf(s[0], "%10d / %02d      ", y, m);

  for(k=1; k<7; k++)
   s[k][0]='\0';

  k=1;
  sprintf(s[k], "%*s", 3 * wd, "");

  for(i = 1; i <= mdays; i++){
     sprintf(tmp, "%3d", i);
     strcat(s[k], tmp);
     if(++wd % 7 ==0)
       if(s[k])
       k++;
  }

//    if(wd % 7 == 0)
//        k--;
//    else{
//        for(wd %= 7; wd < 7; wd++)
//            strcat(s[k], "   ");
//   }
   while(++k < 7 )
     sprintf(s[k], "");
}

void print(char sbuf[3][7][22], int n)
{
  int i, j;

   if(n==3){
  for(i=0; i<2; i++)
   printf("%21s   ", sbuf[i][0]);
     printf("%21s", sbuf[2][0]);
  putchar('\n');

  for(i=0; i<2; i++)
   printf("  日 月 火 水 木 金 土  ");
     printf(" 日 月 火 水 木 金 土 ");
  putchar('\n');

  for(i=0; i<2; i++)
   printf("----------------------  ");
     printf("---------------------");
  putchar('\n');

   for(i=1; i<7; i++){
       for(j=0; j<2; j++)
     printf("%-22s  ", sbuf[j][i]);
         printf("%-22s", sbuf[2][i]);
     if(i==5)
       if(*sbuf[0][6]==*sbuf[1][6] && *sbuf[1][6]==*sbuf[2][6])
         i+=2;

     putchar('\n');
     }

   putchar('\n');

   }else{
  for(i=0; i<n; i++)
   printf("%22s   ", sbuf[i][0]);
  putchar('\n');

  for(i=0; i<n; i++)
   printf("  日 月 火 水 木 金 土  ");
  putchar('\n');

  for(i=0; i<n; i++)
   printf("----------------------  ");
  putchar('\n');

   for(i=1; i<7; i++){
     for(j=0; j<n; j++)
      printf("%-22s  ", sbuf[j][i]);
   putchar('\n');
   }

   putchar('\n');
   }
}

void put_calendar(int y1, int m1, int y2, int m2)
{
  int y = y1;
  int m = m1;
  int n = 0;
  char sbuf[3][7][22];

  while(y <= y2){
   if(y == y2 && m > m2) break;
   make_calendar(y, m, sbuf[n++]);
   if(n==3){
    print(sbuf, n);
    n = 0;
   }
   m++;
   if(m==13 && y < y2){
    y++;
    m = 1;
   }
  }
  if(n)
   print(sbuf, n);
}

実行結果

カレンダーを表示します。
開始年月日は?
年:2014
月:1
終了年月は?
年:2014
月:12

   2014 / 01               2014 / 02               2014 / 03
  日 月 火 水 木 金 土      日 月 火 水 木 金 土    日 月 火 水 木 金 土
----------------------  ----------------------  ---------------------
    1  2  3  4                       1                       1
  5  6  7  8  9 10 11     2  3  4  5  6  7  8     2  3  4  5  6  7  8
 12 13 14 15 16 17 18     9 10 11 12 13 14 15     9 10 11 12 13 14 15
 19 20 21 22 23 24 25    16 17 18 19 20 21 22    16 17 18 19 20 21 22
 26 27 28 29 30 31       23 24 25 26 27 28       23 24 25 26 27 28 29
             30 31

   2014 / 04               2014 / 05               2014 / 06
  日 月 火 水 木 金 土      日 月 火 水 木 金 土    日 月 火 水 木 金 土
----------------------  ----------------------  ---------------------
   1  2  3  4  5                 1  2  3     1  2  3  4  5  6  7
  6  7  8  9 10 11 12     4  5  6  7  8  9 10     8  9 10 11 12 13 14
 13 14 15 16 17 18 19    11 12 13 14 15 16 17    15 16 17 18 19 20 21
 20 21 22 23 24 25 26    18 19 20 21 22 23 24    22 23 24 25 26 27 28
 27 28 29 30             25 26 27 28 29 30 31    29 30

   2014 / 07               2014 / 08               2014 / 09
  日 月 火 水 木 金 土      日 月 火 水 木 金 土    日 月 火 水 木 金 土
----------------------  ----------------------  ---------------------
   1  2  3  4  5                    1  2        1  2  3  4  5  6
  6  7  8  9 10 11 12     3  4  5  6  7  8  9     7  8  9 10 11 12 13
 13 14 15 16 17 18 19    10 11 12 13 14 15 16    14 15 16 17 18 19 20
 20 21 22 23 24 25 26    17 18 19 20 21 22 23    21 22 23 24 25 26 27
 27 28 29 30 31          24 25 26 27 28 29 30    28 29 30
       31

   2014 / 10               2014 / 11               2014 / 12
  日 月 火 水 木 金 土      日 月 火 水 木 金 土    日 月 火 水 木 金 土
----------------------  ----------------------  ---------------------
    1  2  3  4                       1        1  2  3  4  5  6
  5  6  7  8  9 10 11     2  3  4  5  6  7  8     7  8  9 10 11 12 13
 12 13 14 15 16 17 18     9 10 11 12 13 14 15    14 15 16 17 18 19 20
 19 20 21 22 23 24 25    16 17 18 19 20 21 22    21 22 23 24 25 26 27
 26 27 28 29 30 31       23 24 25 26 27 28 29    28 29 30 31
       30