【C言語】文字列が日付の書式かどうかチェックする方法

C言語で文字列が日付の書式かどうかをチェックする方法について学びたいですか?この記事では、正規表現を使った方法と手動での解析方法を詳しく解説します。

また、複数の書式に対応する方法や日付の変換とフォーマットについても紹介します。

初心者の方でも理解しやすいように、サンプルコードと実行結果を交えて説明しますので、ぜひ参考にしてください。

目次から探す

日付書式のチェック方法

C言語で文字列が日付の書式かどうかをチェックする方法には、主に「正規表現を使った方法」と「手動での解析方法」の2つがあります。

それぞれの方法について詳しく解説します。

正規表現を使った方法

正規表現を使うことで、特定のパターンに一致するかどうかを簡単にチェックすることができます。

C言語では、正規表現を扱うためにregex.hライブラリを使用します。

以下に、正規表現を使って日付の書式をチェックするサンプルコードを示します。

#include <stdio.h>
#include <regex.h>
int is_valid_date(const char *date) {
    regex_t regex;
    int ret;
    // 正規表現パターン: YYYY-MM-DD
    const char *pattern = "^[0-9]{4}-[0-9]{2}-[0-9]{2}$";
    // 正規表現のコンパイル
    ret = regcomp(®ex, pattern, REG_EXTENDED);
    if (ret) {
        fprintf(stderr, "Could not compile regex\n");
        return 0;
    }
    // 正規表現によるマッチング
    ret = regexec(®ex, date, 0, NULL, 0);
    regfree(®ex);
    if (!ret) {
        return 1; // マッチした場合
    } else if (ret == REG_NOMATCH) {
        return 0; // マッチしなかった場合
    } else {
        fprintf(stderr, "Regex match failed\n");
        return 0;
    }
}
int main() {
    const char *date = "2023-10-05";
    if (is_valid_date(date)) {
        printf("Valid date format\n");
    } else {
        printf("Invalid date format\n");
    }
    return 0;
}

このコードでは、is_valid_date関数が文字列が日付の書式(YYYY-MM-DD)に一致するかどうかをチェックします。

正規表現パターンを^[0-9]{4}-[0-9]{2}-[0-9]{2}$とし、年、月、日がそれぞれ4桁、2桁、2桁の数字であることを確認します。

手動での解析方法

正規表現を使わずに、手動で文字列を解析して日付の書式をチェックする方法もあります。

この方法では、文字列の各部分を分割して、それぞれが適切な範囲内の数字であるかどうかを確認します。

以下に、手動で日付の書式をチェックするサンプルコードを示します。

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int is_digit_string(const char *str, int length) {
    for (int i = 0; i < length; i++) {
        if (!isdigit(str[i])) {
            return 0;
        }
    }
    return 1;
}
int is_valid_date(const char *date) {
    if (strlen(date) != 10) {
        return 0;
    }
    // YYYY-MM-DDの形式かどうかをチェック
    if (date[4] != '-' || date[7] != '-') {
        return 0;
    }
    // 年、月、日が数字かどうかをチェック
    if (!is_digit_string(date, 4) || !is_digit_string(date + 5, 2) || !is_digit_string(date + 8, 2)) {
        return 0;
    }
    // 月と日の範囲をチェック
    int year = atoi(date);
    int month = atoi(date + 5);
    int day = atoi(date + 8);
    if (month < 1 || month > 12) {
        return 0;
    }
    if (day < 1 || day > 31) {
        return 0;
    }
    // 簡易的なチェック(実際には月ごとの日数や閏年の考慮が必要)
    return 1;
}
int main() {
    const char *date = "2023-10-05";
    if (is_valid_date(date)) {
        printf("Valid date format\n");
    } else {
        printf("Invalid date format\n");
    }
    return 0;
}

このコードでは、is_valid_date関数が文字列が日付の書式(YYYY-MM-DD)に一致するかどうかを手動でチェックします。

まず、文字列の長さが10であることを確認し、次にハイフンの位置と年、月、日が数字であることを確認します。

最後に、月と日の範囲が適切であるかどうかをチェックします。

以上の2つの方法を使うことで、C言語で文字列が日付の書式かどうかをチェックすることができます。

正規表現を使う方法は簡潔で強力ですが、手動での解析方法も柔軟性があり、特定の要件に応じてカスタマイズすることができます。

応用例

複数の書式に対応する方法

日付の書式は国や地域によって異なるため、複数の書式に対応する必要があります。

例えば、YYYY-MM-DDDD/MM/YYYYMM-DD-YYYYなどがあります。

これらの書式に対応するためには、複数の正規表現パターンを用意し、それぞれのパターンに対してチェックを行う方法が有効です。

複数の正規表現パターンの使用

複数の正規表現パターンを使用することで、異なる日付書式に対応できます。

以下に、YYYY-MM-DDDD/MM/YYYYMM-DD-YYYYの3つの書式に対応する正規表現パターンを示します。

#include <stdio.h>
#include <regex.h>
int match_regex(const char *string, const char *pattern) {
    regex_t regex;
    int result;
    // 正規表現のコンパイル
    result = regcomp(®ex, pattern, REG_EXTENDED);
    if (result) {
        fprintf(stderr, "正規表現のコンパイルに失敗しました\n");
        return 0;
    }
    // 正規表現のマッチング
    result = regexec(®ex, string, 0, NULL, 0);
    regfree(®ex);
    return !result;
}
int main() {
    const char *date1 = "2023-10-01";
    const char *date2 = "01/10/2023";
    const char *date3 = "10-01-2023";
    const char *pattern1 = "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"; // YYYY-MM-DD
    const char *pattern2 = "^[0-9]{2}/[0-9]{2}/[0-9]{4}$"; // DD/MM/YYYY
    const char *pattern3 = "^[0-9]{2}-[0-9]{2}-[0-9]{4}$"; // MM-DD-YYYY
    if (match_regex(date1, pattern1)) {
        printf("%s は YYYY-MM-DD の形式です\n", date1);
    }
    if (match_regex(date2, pattern2)) {
        printf("%s は DD/MM/YYYY の形式です\n", date2);
    }
    if (match_regex(date3, pattern3)) {
        printf("%s は MM-DD-YYYY の形式です\n", date3);
    }
    return 0;
}

書式ごとのチェック関数の作成

複数の書式に対応するために、書式ごとにチェック関数を作成することも有効です。

以下に、YYYY-MM-DDDD/MM/YYYYMM-DD-YYYYの書式ごとのチェック関数を示します。

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int is_valid_yyyy_mm_dd(const char *date) {
    if (strlen(date) != 10) return 0;
    if (!isdigit(date[0]) || !isdigit(date[1]) || !isdigit(date[2]) || !isdigit(date[3])) return 0;
    if (date[4] != '-') return 0;
    if (!isdigit(date[5]) || !isdigit(date[6])) return 0;
    if (date[7] != '-') return 0;
    if (!isdigit(date[8]) || !isdigit(date[9])) return 0;
    return 1;
}
int is_valid_dd_mm_yyyy(const char *date) {
    if (strlen(date) != 10) return 0;
    if (!isdigit(date[0]) || !isdigit(date[1])) return 0;
    if (date[2] != '/') return 0;
    if (!isdigit(date[3]) || !isdigit(date[4])) return 0;
    if (date[5] != '/') return 0;
    if (!isdigit(date[6]) || !isdigit(date[7]) || !isdigit(date[8]) || !isdigit(date[9])) return 0;
    return 1;
}
int is_valid_mm_dd_yyyy(const char *date) {
    if (strlen(date) != 10) return 0;
    if (!isdigit(date[0]) || !isdigit(date[1])) return 0;
    if (date[2] != '-') return 0;
    if (!isdigit(date[3]) || !isdigit(date[4])) return 0;
    if (date[5] != '-') return 0;
    if (!isdigit(date[6]) || !isdigit(date[7]) || !isdigit(date[8]) || !isdigit(date[9])) return 0;
    return 1;
}
int main() {
    const char *date1 = "2023-10-01";
    const char *date2 = "01/10/2023";
    const char *date3 = "10-01-2023";
    if (is_valid_yyyy_mm_dd(date1)) {
        printf("%s は YYYY-MM-DD の形式です\n", date1);
    }
    if (is_valid_dd_mm_yyyy(date2)) {
        printf("%s は DD/MM/YYYY の形式です\n", date2);
    }
    if (is_valid_mm_dd_yyyy(date3)) {
        printf("%s は MM-DD-YYYY の形式です\n", date3);
    }
    return 0;
}

日付の変換とフォーマット

日付の書式をチェックするだけでなく、異なる書式に変換することもよくあります。

例えば、YYYY-MM-DD形式の日付をDD/MM/YYYY形式に変換する場合です。

日付文字列の変換方法

以下に、YYYY-MM-DD形式の日付をDD/MM/YYYY形式に変換する方法を示します。

#include <stdio.h>
#include <string.h>
void convert_yyyy_mm_dd_to_dd_mm_yyyy(const char *input, char *output) {
    strncpy(output, input + 8, 2); // 日
    output[2] = '/';
    strncpy(output + 3, input + 5, 2); // 月
    output[5] = '/';
    strncpy(output + 6, input, 4); // 年
    output[10] = '\0';
}
int main() {
    const char *date = "2023-10-01";
    char converted_date[11];
    convert_yyyy_mm_dd_to_dd_mm_yyyy(date, converted_date);
    printf("変換後の日付: %s\n", converted_date);
    return 0;
}

日付のフォーマット変更

日付のフォーマットを変更することで、異なる書式に対応することができます。

以下に、DD/MM/YYYY形式の日付をYYYY-MM-DD形式に変換する方法を示します。

#include <stdio.h>
#include <string.h>
void convert_dd_mm_yyyy_to_yyyy_mm_dd(const char *input, char *output) {
    strncpy(output, input + 6, 4); // 年
    output[4] = '-';
    strncpy(output + 5, input + 3, 2); // 月
    output[7] = '-';
    strncpy(output + 8, input, 2); // 日
    output[10] = '\0';
}
int main() {
    const char *date = "01/10/2023";
    char converted_date[11];
    convert_dd_mm_yyyy_to_yyyy_mm_dd(date, converted_date);
    printf("変換後の日付: %s\n", converted_date);
    return 0;
}

これらの方法を組み合わせることで、様々な日付書式に対応し、必要に応じて変換することができます。

これにより、日付の入力や表示に柔軟に対応することが可能となります。

目次から探す