end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

状態遷移図 / 状態遷移表によるメールアドレスのチェック

GoFのステートパターンは以前のエントリで記載していますが、 次のurlで、状態遷移図 / 状態遷移表 の実装があった為、写経。

日経ソフトウエア 2020年3月号|日経ソフトウエア

状態遷移図 と 状態遷移表

まぁ、記載している通りです f:id:end0tknr:20200126201554p:plain

現在の状態 / 外部からの入力 英数字 ドット 末尾
初期状態 (State_0) State_1 State_7 State_7 State_7 State_7
≠ドット in ローカル部 (State_1) State_1 State_2 State_3 State_7 State_7
=ドット in ローカル部 (State_2) State_1 State_2 State_3 State_7 State_7
@(State_3) State_4 State_7 State_7 State_7 State_7
≠ドット in ドメイン部 (State_4) State_4 State_5 State_7 State_7 State_6
=ドット in ドメイン部 (State_5) State_4 State_7 State_7 State_7 State_7
=メールアドレス (State_6) State_8 State_8 State_8 State_8 State_8
≠メールアドレス (State_6) State_8 State_8 State_8 State_8 State_8
完了 (State_8)

状態遷移表によるメールアドレスのチェック

上記の状態遷移表をpythonで実装すると、以下の通り

#!/usr/local/python3/bin/python3
# -*- coding: utf-8 -*-

def main():
    string = input("文字列を入力下さい-->")
    if is_email(string):
        print("これはメールアドレスです。")
    else:
        print("これはメールアドレスではありません。")


def is_alphanum(char):
    if "0" <= char <= "9" or "A" <= char <= "Z" or "a" <= char <= "z":
        return True
    return False

def is_dot(char):
    if char == ".":
        return True
    return False

def is_atmark(char):
    if char == "@":
        return True
    return False

def is_end(char):
    if char == "$":
        return True
    return False

def is_email(str):
    str += "$"  # 文字列に末尾を意味する$を付加

    # 状態遷移表
    table = [ [1, 7, 7, 7, 7],
              [1, 2, 3, 7, 7] ,
              [1, 7, 7, 7, 7],
              [4, 7, 7, 7, 7],
              [4, 5, 7, 7, 6],
              [4, 7, 7, 7, 7],
              [8, 8, 8, 8, 8],
              [8, 8, 8, 8, 8] ]

    state = 0   # 0 = 初期状態
    
    for char in str:    # 文字列から1文字ずつ取り出し状態遷移
        if is_alphanum(char):
            col = 0
        elif is_dot(char):
            col = 1
        elif is_atmark(char):
            col = 2
        elif is_end(char):
            col = 4
        else:
            col = 3
        
        state = table[state][col]
        
        if state == 6 or state == 7:    # OK or NGなら終了
            break

    if state == 6:
        return True
    return False

if __name__ == '__main__':
    main()