Thinkers'Studio
JavaとC言語の自習ツール
有効な日付かチェックする関数例

 年月日指定を行うプログラムでは、指定された日付が妥当かどうかを判断する必要があります。
 今回は、自前処理で日付の有効性をチェックする関数の例です。
 この関数は、たとえば以前の Tips 曜日を調べるプログラム などで、部品として活用できます。  

 どこまでを妥当とするかは、年月日の用途によっても異なります。
 ここでは、次のような判断とします。
  • 指定された月が 1〜12 の範囲内になければ、エラー(-1)
  • 指定された日が、1〜(指定月)末日の範囲内になければ、エラー(-2)
  • 上記に該当しなければ、OKとする
【 用意する関数 】
 int checkYmd( int y, int m, int d )
 機 能)  引数で渡されたy,m,dが年月日として妥当か調べる
 戻り値)  OK:0, 月が妥当でない:-1, 日が妥当でない:-2

有効な日付かチェックする関数を使うプログラム例 】
#include <stdio.h>

int checkYmd( int y, int m, int d )
{
    int lastd;
    int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

    // 月の範囲チェック
    if( m < 1 || m > 12 ) return -1;
    // 日の範囲チェック
    lastd = days[m-1];
    if( m == 2 ) {
        if( y % 4 == 0 && y % 100 != 0 || y % 400 == 0 )
            lastd = 29;  // うるう年なら末日は29
    }
    if( d < 1 || d > lastd ) return -2;
    return 0;
}

// ---------------------------------------
main()
{
    int year, month, day, retc;

    while( 1 ) {
        printf( "年月日は?(yyyy/mm/dd)> " );
        if( scanf("%d/%d/%d", &year, &month, &day) != 3 ) break;
        if( (retc = checkYmd( year, month, day )) == 0 )
            printf( "有効な日付です\n" );
        else { 
            if( retc == -1 ) printf( "月指定が正しくありません\n" );
            if( retc == -2 ) printf( "日指定が正しくありません\n" );
        }
    }
}
実行結果例
年月日は?(yyyy/mm/dd)> 2013/9/31
日指定が正しくありません
年月日は?(yyyy/mm/dd)> 2014/13/1
月指定が正しくありません
年月日は?(yyyy/mm/dd)> 2014/2/29
日指定が正しくありません
年月日は?(yyyy/mm/dd)> 2016/2/29
有効な日付です
年月日は?(yyyy/mm/dd)> q
 各月の末日日付は、int型の配列で定義します。 2月はうるう年でないときの末日日付(28)としておきます。
    int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 指定月の末日日付 を lastd に入れます。
    lastd = days[m-1];
 うるう年の 2月なら lastd を 29 に置き換えてから、日付の範囲チェックを行います(参考:うるう年判定のプログラム例 )。

 (今週のクイズはありません)

前回の答え:(前回の問題を見る
 cmp の戻り値は int です。 int型の比較なら、引き算の結果がそのまま2つの引数の大小を表わしますが、浮動小数点数の場合はそれではだめです。1 未満の差が 0 で返されてしまいます。
 次のように比較演算子で大小を判定し、その結果に応じて 正/負/0 いずれかの戻り値を返す必要があります。
//正しいコーディング例
int cmp( const void *p, const void *q ) {
    if( *(double*)p > *(double*)q ) return 1;
    if( *(double*)p < *(double*)q ) return -1;
    return 0;
}