【C言語】日付が有効かどうかを判定するプログラムの書き方
本記事では、年・月・日を整数として受け取り、その日付が実際に存在しうるものかどうかを判定するC言語のプログラムを解説します。
ここで「有効な日付」とは、1800年1月1日〜9999年12月31日の範囲に含まれ、カレンダー上のあらゆる制約(月ごとの日数や閏年のルールなど)を満たす日付のことを指します。この範囲外の日付はすべて無効として扱います。
有効な日付の条件
日付が有効であるためには、以下の制約をすべて満たす必要があります。
- 日は1以上31以下であること
- 月は1以上12以下であること
- 年は1800以上9999以下であること
- 4月・6月・9月・11月の場合、日は30以下であること
- 2月の場合は、次のように閏年かどうかで判定が変わる
- 閏年であれば、日は29以下であること
- 平年であれば、日は28以下であること
これらの条件がすべて成立すれば有効な日付、一つでも満たさなければ無効な日付と判断します。
実行例
入力:y = 2002, d = 29, m = 11
出力:Date is valid(日付は有効)
入力:y = 2001, d = 29, m = 2
出力:date is not valid(日付は無効)
1つ目の例では、11月は30日まである月のため、29日は有効です。2つ目の例では、2001年は閏年ではないため、2月29日は存在せず無効になります。
アルゴリズム
処理の流れは以下の通りです。
- isleap関数: 西暦年yを受け取り、閏年であれば1、そうでなければ0を返す。
閏年の判定は「4で割り切れ、かつ100で割り切れない年」または「400で割り切れる年」です。 - datevalid関数: 日(d)、月(m)、年(y)を受け取り、以下の順で検証する。
- 年が min_yr(1800)〜max_yr(9999) の範囲外なら0を返す
- 月が1〜12の範囲外なら0を返す
- 日が1〜31の範囲外なら0を返す
- 月が2月の場合、isleap(y)の結果に応じて日が29以下(閏年)または28以下(平年)かを確認し、条件を満たせば1、満たさなければ0を返す
- 月が4・6・9・11の場合、日が30以下なら1、そうでなければ0を返す
- いずれの条件にも該当しなければ、その月は31日まである月なので1を返す
- main関数: 年・月・日の値を設定し、datevalid関数の戻り値に応じて結果を出力する。
C言語による実装例
#include <stdio.h>
#define max_yr 9999
#define min_yr 1800
// 閏年かどうかを判定する(閏年なら1を返す)
int isleap(int y) {
if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0))
return 1;
else
return 0;
}
// 日付の妥当性をチェックする関数
int datevalid(int d, int m, int y) {
// 年の範囲チェック
if (y < min_yr || y > max_yr)
return 0;
// 月の範囲チェック
if (m < 1 || m > 12)
return 0;
// 日の範囲チェック
if (d < 1 || d > 31)
return 0;
// 月ごとの日数をチェック
if (m == 2) {
if (isleap(y)) {
if (d <= 29)
return 1;
else
return 0;
} else {
if (d <= 28)
return 1;
else
return 0;
}
}
// 4月・6月・9月・11月は30日まで
if (m == 4 || m == 6 || m == 9 || m == 11) {
if (d <= 30)
return 1;
else
return 0;
}
// 残りの月は31日まで
return 1;
}
int main(void) {
int y = 2002;
int d = 29;
int m = 11;
if (datevalid(d, m, y))
printf("Date is valid\n");
else
printf("Date is not valid\n");
return 0;
}
出力結果
上記のコードを実行すると、次の出力が得られます。
Date is valid
補足:閏年の判定ルールについて
グレゴリオ暦における閏年の正確なルールは以下の3段階です。
- 4で割り切れる年は閏年候補
- ただし100で割り切れる年は平年
- さらに400で割り切れる年は閏年(例:2000年は閏年、1900年は平年)
このルールを論理式で表すと (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0) となります。単純に「4で割り切れる年をすべて閏年とする」実装では、1900年のような世紀の境目で誤判定が発生するため注意が必要です。また、2月の判定では閏年でない場合に28日以下かどうかのチェックを行う分岐を必ず入れることで、平年の2月29日などを確実に弾けるようになります。
-
【C言語】再帰を使って配列が回文かどうかを判定するプログラム
配列 arr[n](n は配列のサイズ)が与えられたとき、再帰を用いてその配列が回文かどうかを判定するのが本記事のテーマです。回文とは、前から読んでも後ろから読んでも同じになる並びのことで、「MADAM」や「NAMAN」などが代表的な例です。配列が回文かどうかを調べるには、先頭と末尾から順に要素を比較していきます。再帰的なアプローチでも同様に、start と end の値を更新しながら比較を続けます。start と end が交差(すれ違う)すれば回文と判定でき、途中で要素が一致しなかった場合はそこで処理を打ち切り、false を返します。入力例と出力例入力: arr[] = { 2, 3,
-
C言語で配列が回文かどうかを判定するプログラム
回文とは任意のサイズ n の配列 arr[] が与えられたとき、その配列が回文(パリンドローム)かどうかを判定するのが本記事の目的です。回文とは、前から読んでも後ろから読んでも同じになる並びのことで、MADAM や NAMAN といった文字列が代表的な例として挙げられます。配列が回文かどうかを確認するには、配列を先頭からと末尾から同時に走査し、対応する要素同士を比較していきます。入力例と出力例Input: arr[] = {1, 0, 0, 1} Output: 配列は回文です Input: arr[] = {1, 2, 3, 4, 5} Output: 配列は回文ではありません考え方(アプ