正規表現は
^[-+]?[1-9][0-9]*$
でいいんじゃないかな。これに相当する状態遷移図は
でいいんじゃないかな。S2が受理状態。S3になったら直ちにエラーとして停止していい。これを元に作ってみたC#のクラスは
interface Checker { /// <summary>このオブジェクトの状態を初期状態に戻す</summary> void Reset(); /// <summary>1文字読む</summary> /// <param name="ch">読込む文字</param> void Next(char ch); /// <summary>受理状態かどうか調べる</summary> /// <returns>true:受理状態, false:受理状態ではない</returns> bool IsAcceptable(); /// <summary>エラー状態かどうか調べる</summary> /// <remarks>エラー状態になった場合、それ以降の文字を読む必要が無い</remarks> /// <returns>true:エラー状態, false:エラー状態ではない</returns> bool IsError(); }
class IntChecker : Checker { enum IntParsingState { /// <summary>状態0</summary> State0, /// <summary>状態1</summary> State1, /// <summary>状態2</summary> State2, /// <summary>状態3</summary> State3, } IntParsingState _state; public IntChecker() { Reset(); } public void Reset() { _state = IntParsingState.State0; } public void Next(char ch) { switch (_state) { case IntParsingState.State0: if (ch == '-' || ch == '+') { _state = IntParsingState.State1; } else if (ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || ch == '8' || ch == '9') { _state = IntParsingState.State2; } else { _state = IntParsingState.State3; } break; case IntParsingState.State1: if (ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || ch == '8' || ch == '9') { _state = IntParsingState.State2; } else { _state = IntParsingState.State3; } break; case IntParsingState.State2: if (ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || ch == '8' || ch == '9') { _state = IntParsingState.State2; } else { _state = IntParsingState.State3; } break; case IntParsingState.State3: _state = IntParsingState.State3; break; } } /// <summary>受理状態かどうかを判断する</summary> /// <returns></returns> public bool IsAcceptable() { return _state == IntParsingState.State2; } public bool IsError() { return _state == IntParsingState.State3; } }
でいいんじゃないかな。これを
Checker checker = new IntChecker(); string str = "+123"; foreach (char ch in str) { checker.Next(ch); if (checker.IsError()) { break; } } if (checker.IsAcceptable()) { Console.WriteLine("整数だよ"); } else { Console.WriteLine("整数じゃないよ"); }
こんな感じで使ってみたりなんかしちゃって。
実数でも同じことしたい。実数を表す文字列の正規表現は
^[-+]?([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][-+]?[0-9]+)?$
でよさげだけど、今のところ状態遷移図を描けてない。ちょっと考える。