FSM c++多种实现方法

bcode parser不使用switch实现

B编码中有四种类型:string,integer,dictionary,list。示例分别如下:

integer: i43e 表示数字32。
string: 5:world 前面数字表示字符长度为5,字符串为world。
dictionary: d9:publisher3:bobe表示key:publisher,value:bob。
list:l4:worlde 表示列表成员world。

实现1:

这种主要也是利用函数指针来保存一个processor,每个processor对应一个状态。处理完对应的区块信息就返回下一种处理方法。对于嵌套类型,可以使用递归来做。

class BecodeParser{
public:
    void start(const std::string& str)
    {
        std::string::const_iterator itr = str.cbegin();
        shiftState(itr);
        while( itr != str.cend() ) {
            processor(itr);
        }
    }
    void processDictionary(std::string::const_iterator& itr) {
        // process
        shiftState(++itr);
    }

    void processList(std::string::const_iterator& itr) {
        // process
        shiftState(++itr);
    }

    void processInterger(std::string::const_iterator& itr) {
        // process
        shiftState(++itr);
    }

    void processString(std::string::const_iterator& itr) {
        // process
        shiftState(++itr);
    }

    void shiftState(std::string::const_iterator& itr){
        if( *itr == 'l') processor = processList;
        if( *itr == 'i') processor = processInterger;
        if( isNumber(itr) ) processor = processString;
    }

    void(*processor)(std::string::const_iterator& itr); // 这儿可以使用boost::function来保存函数对象。
    boost::function<void(std::string::const_iterator& )> processsor_; 
    //这样就可以搭配bind,lambda使用,发挥函数编程优势
};

实现2:

利用和类型来实现,在TypeScript中有和类型,但是c++中则没有。但是cpp可以用基类指针来模拟和类型。具体实现见代码。

class AbsBecodeType{
public:
    virtual AbsBecodeType* Parser(std::string::const_iterator& itr);
};

class ListParser: public AbsBecodeType{
public:
    virtual AbsBecodeType* Parser(std::string::const_iterator& itr);
};

class DictionaryParser: public AbsBecodeType{
public:
    virtual AbsBecodeType* Parser(std::string::const_iterator& itr);
};

class IntergerParser: public AbsBecodeType{
public:
    virtual AbsBecodeType* Parser(std::string::const_iterator& itr) {
        // processe
        if( *itr == l) return std::make_shared<ListParser>();
    }
};

void processBcodeStr(const std::string& str) {
    std::shared_ptr<AbsBecodeType> processor = std::make_shared<IntergerParser>();
    std::string::const_iterator itr = str.cbegin();
    while( itr != str.cend() ) {
        processor.reset(processor->Parser(itr));
    }
}

实现3:

这一种实现是常见的一种方式。定义一个state,然后在这个state里面周转。今天刷题(leetcode No.8) 又收货了一种状态定义的方式。

int get_col(char c) {
        if (isspace(c)) return 0;
        if (c == '+' or c == '-') return 1;
        if (isdigit(c)) return 2;
        return 3;
}

unordered_map<string, vector<string>> table = {
        {"start", {"start", "signed", "in_number", "end"}},
        {"signed", {"end", "end", "in_number", "end"}},
        {"in_number", {"end", "end", "in_number", "end"}},
        {"end", {"end", "end", "end", "end"}}
    };


state = table[state][get_col(c)];
posted @ 2021-12-13 16:40  uttep  阅读(237)  评论(0)    收藏  举报