C言語のきほん「カレンダー(横に並べる)」

スポンサーリンク
C言語

前回は、カレンダーを表示するプログラムをご紹介した。

ところで、一般的なコンソール画面なら3カ月分のカレンダーを表示できる。

そこで、今回は、表示する年月の範囲を読み込んで、横方向に3カ月分のカレンダーを並べて表示するプログラムをご紹介しよう。

なお、本プログラムは、
 Windows 11 Home(23H2)上で、Visual Studio Code(1.95.3)を使用して作成し、gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0で コンパイルしている。

//カレンダー表示(最大3カ月分を横に並べる)

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

//各月の日数
int mday[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

//year年month月day日の曜日を求める
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;
}

//year年はうるう年か
int is_leap(int year)
{
    return year % 4 == 0 && year % 100 != 0 || year % 4 == 0;
}

//year年month月の日数
int monthdays(int year,int month)
{
    if (month-- != 2)
        return mday[month];
    return mday[month] + is_leap(year);
}

//y年m月のカレンダーを2次元配列sに格納
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)
        k++;
    }

    
	if (wd % 7 == 0)
		k--;
	else {
		for (wd %= 7; wd < 7; wd++)		// 最終日の右側に空白文字を追加
			strcat(s[k], "   ");
	}
	while (++k < 7)						// 未使用行を空白文字で埋めつくす
		sprintf(s[k], "%21s", "");
    
    
}

//3次元配列sbufに格納されたカレンダーを横にn個並べて表示
void print(char sbuf[3][7][22],int n)
{
    int i,j;

    for ( i = 0; i < n; i++)
        printf("%s   ", 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("%s   ", sbuf[j][i]);
        putchar('\n');
        
    }
    putchar('\n');
    
}

//y1年m1月からy2年m2月までのカレンダーを表示
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);
}

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

    printf("カレンダーを表示します\n");

    printf("開始する年月を入力してください。\n");
    printf("年:");  scanf("%d",&y1);
    printf("月:");  scanf("%d",&m1);

    printf("終了する年月を入力してください。\n");
    printf("年:");  scanf("%d",&y2);
    printf("月:");  scanf("%d",&m2);

    putchar('\n');

    put_calendar(y1,m1,y2,m2);

    return 0;
}

実行結果

カレンダーを表示します
開始する年月を入力してください。
年:2024
月:12
終了する年月を入力してください。
年:2025
月:5

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

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

文字列s2をs1にコピーするには、strcpy(s1,s2)とする。

文字列s1の後ろにs2を連結するには、strcat(s1,s2)とする。

書式化を伴う文字列の作成には、sprintf関数を利用する。

参考)新・明解C言語 中級編 柴田 望洋(著)SBクリエイティブ

コメント

タイトルとURLをコピーしました