C#でsscanfもどき

たまに、クラスライブラリ一覧を見ながら知らないクラスをチェックしてたりするのですが、今回目にとまったのはArgIterator。調べてみたら確かにこれはあんま使わなさそう。取りあえずサンプルとして、Cライブラリのsscanfもどきをこさえてみました。手抜きなので%s,%dにしか対応してません。

#region Using directives

using System;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;

#endregion

class Program
{
    // %s,%dにしか対応していない
    static int sscanf(string str, string fmt, __arglist)
    {
        bool flag = false;
        ArrayList al = new ArrayList();
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < fmt.Length; ++i)
        {
            if (flag)
            {
                if (fmt[i] == 's')
                {
                    sb.Append(@"(\w+)");
                    al.Add(typeof(string));
                }
                else if (fmt[i] == 'd')
                {
                    sb.Append(@"(\d+)");
                    al.Add(typeof(int));
                }
                else
                {
                    sb.Append('%');
                    sb.Append(fmt[i]);
                }
                flag = false;
            }
            else
            {
                if (fmt[i] == '%')
                    flag = true;
                else
                    sb.Append(fmt[i]);
            }
        }
        sb.Append(".*");
        Match m = Regex.Match(str, sb.ToString());
        if (m.Success)
        {
            Type types = (Type)al.ToArray(typeof(Type));
            ArgIterator it = new ArgIterator(__arglist);
            if (types.Length > it.GetRemainingCount())
                throw new ArgumentException();
            for (int i = 0; i < types.Length; ++i)
            {
                TypedReference tr = it.GetNextArg();
                Type t = __reftype(tr);
                if (t != types[i])
                    throw new ArgumentException();
                if (t == typeof(int))
                    __refvalue(tr, int) = Int32.Parse(m.Groups[i + 1].Value);
                else if (t == typeof(string))
                    __refvalue(tr, string) = m.Groups[i + 1].Value;
            }
            return types.Length;
        }
        return 0;
    }

    static void Main(string[] args)
    {
        string str = "ドラえもん 2112年9月3日";
        string name = "";
        int year = 0;
        int mon = 0;
        int day = 0;

        sscanf(str, "%s %d年%d月%d日",
            __arglist(__makeref(name), __makeref(year), __makeref(mon), __makeref(day)));

        Console.WriteLine("{0} {1}/{2}/{3}", name, mon, day, year);

        Console.ReadLine();
    }
}
/* 結果
ドラえもん 9/3/2112
 */

C#でプログラム組んでて、アンダーバーで始まるキーワードなんか普通使いませんよね。