状态机学习(五)解析四则运算式
将四则运算拆分成一个个数字和符号后
就进行运算分析
使用以下语法规则:(摘录自《自编编程语言》)
expression:
term:
primary expression:
代码如下:
#pragma once #include <string> #include <deque> #include <iostream> enum TokenType { BAD_TOKEN, NUM_TOKEN, ADD_TOKEN, SUB_TOKEN, MUL_TOKEN, DIV_TOKEN, LPAREN_TOKEN, RPAREN_TOKEN, ENDFILE_TOKEN }; class Token { private: TokenType type_; std::string valueStr_; public: Token() : type_(BAD_TOKEN) {} Token(TokenType t,std::string s) : type_(t),valueStr_(s) {} bool operator ==(const Token& t) { if (type_ == t.type_ && valueStr_ == t.valueStr_) { return true; } return false; } Token(const Token& t) { if (*this != t) { type_ = t.type_; valueStr_ = t.valueStr_; } } bool operator != (const Token& t) { return !(*this == t); } Token& operator=(const Token& t) { if (*this != t) { type_ = t.type_; valueStr_ = t.valueStr_; } return *this; } /*void SetType(TokenType type) { type_ = type; } void SetValue(double value) { value_ = value; } void SetValStr(std::string valueStr) { valueStr_ = valueStr; }*/ TokenType GetType() { return type_; } std::string GetValStr() { return valueStr_; } }; class Expression2Tokens { std::string contentStr_; Expression2Tokens& operator=(const Expression2Tokens&) {}; Expression2Tokens(const Expression2Tokens&); enum Status { INIT_STATUS, NUM_STATUS, OPERATOR_STATUS, LPAREN_STATUS, RPAREN_STATUS, END_STATUS, ERROR_STATUS }; public: std::deque<Token> tokenDeque_; Expression2Tokens(std::string s):contentStr_(s){} bool Analyzer(); void PrintTokens() { for (std::deque<Token>::iterator it = tokenDeque_.begin(); it != tokenDeque_.end(); it++) { std::cout << "type: " << (*it).GetType() << ", string: " << (*it).GetValStr() << std::endl; } std::cout << std::endl; } }; class ParseExpression { Expression2Tokens express2token_; ParseExpression& operator=(const ParseExpression&) {}; ParseExpression(const ParseExpression&); double result_; double ParseTerm(); double ParsePrimaryExpression(); public: ParseExpression(std::string s) : express2token_(s), result_(0.0){} bool StartParse(); double GetResult() { return result_; } };
#include "token.h" #include <iostream> bool Expression2Tokens::Analyzer() { bool bRet = false; size_t index = 0, valueBeg = 0, valueEnd = 0; Status status = INIT_STATUS; for (;index < contentStr_.size();index++) { if (isdigit(contentStr_[index])) { if (status != NUM_STATUS) { status = NUM_STATUS; valueBeg = index; } continue; } //对于 非数字进行判断 if (NUM_STATUS == status ) { std::string s(contentStr_.substr(valueBeg, index - valueBeg)); Token t(NUM_TOKEN,s); tokenDeque_.push_back(t); valueBeg = 0; } if (contentStr_[index] == '+') { Token t(ADD_TOKEN, "+"); tokenDeque_.push_back(t); status = OPERATOR_STATUS; continue; }else if (contentStr_[index] == '-') { Token t(SUB_TOKEN, "-"); tokenDeque_.push_back(t); status = OPERATOR_STATUS; continue; }else if (contentStr_[index] == '*') { Token t(MUL_TOKEN, "*"); tokenDeque_.push_back(t); status = OPERATOR_STATUS; continue; }else if (contentStr_[index] == '/') { Token t(DIV_TOKEN,"/"); tokenDeque_.push_back(t); status = OPERATOR_STATUS; continue; }else if (contentStr_[index] == ';') { Token t(ENDFILE_TOKEN, ";"); tokenDeque_.push_back(t); status = END_STATUS; bRet = true; return bRet; } else { std::cerr << "analyzer error (" << contentStr_[index] << ")" << std::endl; status = ERROR_STATUS; return false; } } return bRet; } double ParseExpression::ParsePrimaryExpression() { Token token; token = express2token_.tokenDeque_.front(); if (token.GetType() == NUM_TOKEN) { //return atof(token.GetValStr().c_str()); express2token_.tokenDeque_.pop_front(); return stod(token.GetValStr()); } std::cerr << "syntax error." << std::endl; exit(1); return 0.0; } double ParseExpression::ParseTerm() { double dRet; double v; Token token; dRet = ParsePrimaryExpression(); for (;;) { token = express2token_.tokenDeque_.front(); if (token.GetType() != MUL_TOKEN && token.GetType() != DIV_TOKEN) { break; } express2token_.tokenDeque_.pop_front(); v = ParsePrimaryExpression(); if (token.GetType() == MUL_TOKEN) { dRet *= v; } else if (token.GetType() == DIV_TOKEN) { dRet /= v; } } return dRet; } bool ParseExpression::StartParse() { bool bRet = false; if (!express2token_.Analyzer()) return bRet; express2token_.PrintTokens(); double v; Token token; result_ = ParseTerm(); for (;;) { token = express2token_.tokenDeque_.front(); if (token.GetType() != ADD_TOKEN && token.GetType() != SUB_TOKEN) { break; } express2token_.tokenDeque_.pop_front(); v = ParseTerm(); if (token.GetType() == ADD_TOKEN) { result_ += v; } else if (token.GetType() == SUB_TOKEN) { result_ -= v; } } bRet = true; return bRet; }
测试代码如下:
// MyParse.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "token.h" #include <iostream> int main() { Expression2Tokens e("1+2/3*45-67-89+999;"); if (e.Analyzer()) { e.PrintTokens(); } ParseExpression p("132+243/7*4455-6-89+34;"); if(p.StartParse()) std::cout << "result: " << p.GetResult() << std::endl; return 0; }
type: 1, string: 1
type: 2, string: +
type: 1, string: 2
type: 5, string: /
type: 1, string: 3
type: 4, string: *
type: 1, string: 45
type: 3, string: -
type: 1, string: 67
type: 3, string: -
type: 1, string: 89
type: 2, string: +
type: 1, string: 999
type: 8, string: ;
type: 1, string: 132
type: 2, string: +
type: 1, string: 243
type: 5, string: /
type: 1, string: 7
type: 4, string: *
type: 1, string: 4455
type: 3, string: -
type: 1, string: 6
type: 3, string: -
type: 1, string: 89
type: 2, string: +
type: 1, string: 34
type: 8, string: ;
result: 154723
请按任意键继续. . .
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力