前回は、カレンダーを表示するプログラムをご紹介した。
ところで、一般的なコンソール画面なら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クリエイティブ
コメント