万年暦というものがありますが、累計日数を計算すれば簡単に作れます。次のような簡単な関数で、ほぼキリスト誕生からの日数になります。

#define leap(y) ((y)%4 == 0 && ((y)%100 != 0 || (y)%400 == 0))

 

static int DaysOfMonth[2][12] = {

    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,

    31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

 

static int md[2][12] = {

       0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,

       0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };

 

int TotalDays(int y, int m, int d)

{

    int ty = y - 1;

    int t = ty * 365 + ty / 4 - ty / 100 + ty / 400;

 

    t += md[leap(y)][m - 1];

    return t + d;

}

プログラムを動かすと次のようになります。

 

操作としては前半をクリックすると1月から6月まで、後半をクリックすると7月から12月までの表示になります。PrevとNextをクリックすると前の年や次の年になります。次の例は三年後のカレンダーです。

年の表示をクリックすると入力できます。

次のものは1945年のカレンダーです。

次のような関数を使えば累計日数から日付に戻せます。つまり、ある日から1000日後というような日付を求めることができます。例を示そうかと思いましたが、手間がかかるのでやめました。

 

int ipM[366 * 2];

BOOL bIpm;

 

void TotalToDate(int td, int& y, int& m, int& d)

{

    //  year

    td--;

    int ya = td / (365 * 400 + 97);

    int t1 = td % (365 * 400 + 97);

    int yb = t1 / (365 * 100 + 24);

    int t2 = t1 % (365 * 100 + 24);

    int yc = t2 / (365 * 4 + 1);

    int t3 = t2 % (365 * 4 + 1);

    int yd = t3 / 365;

    int t4 = t3 % 365;

    if (t1 == 365 * 400 + 96)                  // leap year : 400

    {

        y = (ya + 1) * 400;

        t4 = 365;

    }

    else

    {

        if (yd > 3)                            // leap year : 4

        {

            yd = 3;

            t4 = 365;

        }

        y = ya * 400 + yb * 100 + yc * 4 + yd + 1;

    }

 

    // month

  //  static int *ipM = NULL;   // work : not yet deleted ?????????????

    if (!bIpm)//ipM)

    {

        //    ipM = new int[366 * 2];

        int at = 0;

        for (int i = 0; i < 12; i++)

        {

            int n = DaysOfMonth[0][i];

            for (int j = 0; j < n; j++)

            {

                ipM[at++] = i + 1;

            }

        }

        for (int i = 0; i < 12; i++)

        {

            int n = DaysOfMonth[1][i];

            for (int j = 0; j < n; j++)

            {

                ipM[at++] = i + 1;

            }

        }

    }

    int yy = leap(y);

    m = ipM[yy * 365 + t4];

 

    // day

    d = t4 - md[yy][m - 1] + 1;

}

 

ダウンロード
Calendar.exe 64bitの実行ファイル
VisualC++2022で作成しています。ランタイムライブラリがないとか言われたら検索してダウンロードしてください。64biなのでx64にします。
Calendar.exe
exe ファイル 110.0 KB
ダウンロード
関連するファイルです。 Calendar.zip
Calendar.zip
zip ( 圧縮 ) ファイル 27.9 KB

ワイルドカードというものがあり、*は任意の文字列 ?は任意の一文字にマッチします。たとえばc*tにはcatやcourtがマッチします。形式言語学で言うと、ワイルドカードは正規表現の一種なのでオートマトンの応用で判定できます。たとえばc*tとcatを考えます。

   c * t   ->  c * t  ->  c * t  ->  c * t

  ^          c    ^      a     ^ ^   t     ^ ^ ^

まずスタート位置にコマ(^)を置きます。文字が一致すれば次に進みます。パターンが?の時にはどの文字にもマッチします。パターンが*の時には、元の位置にも残して次の位置にもコマを進めます。このようにして、最後にゴール地点にコマがあればマッチしたことになります。

 

 

以前に考えたコードに間違いがあったようで、複数のコマがある情況では処理が衝突することがあるので、いったん新しい所に作成して書き戻すようにしました。またc*tにctをマッチさせるにはイプシロン遷移という処理が必要です。とりあえず、動いています。

 

BOOL IsWild()

{

    int lenP = lstrlen(pat);

    int lenS = lstrlen(str);

    for (int i = 0; i < 100; i++)

        bWild[i] = FALSE;

    bWild[0] = TRUE;

    for (int i = 0; i < lenS; i++)

    {

        for (int j = 0; j <= lenP; j++)

            bNext[j] = FALSE;

        int c = str[i];

        for (int j = 0; j < lenP; j++)

        {

            int d = pat[j];

            if (bWild[j])

            {

                switch (d)

                {

                case '*':

                    bNext[j] = TRUE;

                    bNext[j + 1] = TRUE;

                    break;

                case '?':

                    bNext[j + 1] = TRUE;

                    break;

                default:

                    if (c == d)

                        bNext[j + 1] = TRUE;

                    break;

                }

            }

        }

        for (int j = 0; j <= lenP; j++)

            bWild[j] = bNext[j];

        for (int j = lenP; j > 0; j--)

        {

            if (bWild[j - 1] && pat[j - 1] == '*')

                bWild[j] = TRUE;

        }

    }

    return bWild[lenP];

}

 

 

ダウンロード
関連するファイルです。こちらも入れなおしました。
wild.zip
zip ( 圧縮 ) ファイル 22.2 KB