又一篇四则运算代码

代码分为两段

一段为将输入分解为TOKEN :  0-9 ( ) + _ * /

一段为根据输入进行计算

第一段

#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <tuple>
#include <assert.h>
using namespace std;

enum CALC_STATUS{
    InitStatus = 0,
    InNumberStatus,
    InIdentStatus,
    EndLineStatus,
    BadStatus
};

enum Token_Type{
    NumberTokenType,
    LparamTokenType,
    RparamTokenType,
    AddTokenType,
    SubTokenType,
    MulTokenType,
    DivTokenType,
    BadTokenType
};

typedef struct TOKEN_TUPLE{
    TOKEN_TUPLE(const std::string& token,const Token_Type& type){
        s = token;
        t = type;
    }
    TOKEN_TUPLE(){};
    TOKEN_TUPLE(const TOKEN_TUPLE& tt){
        s = tt.s;
        t = tt.t;
    }
    std::string s;
    Token_Type t;
};

std::deque<TOKEN_TUPLE> tokenDeque;


void InsertToken(const std::string& token,const Token_Type& type){
    tokenDeque.push_front(TOKEN_TUPLE(token,type));
}


bool IsIdent(const char cc){
    return ( cc == '+' ||
             cc == '-' ||
             cc == '*' ||
             cc == '/' ||
             cc == '(' ||
             cc == ')' );
}

void InsertIdentToken(const std::string& token)
{
    Token_Type tokenType = BadTokenType;
    if(token.size() != 1 || !IsIdent(token[0]))
        return;
    if(token[0] == '+'){
        tokenType = AddTokenType;
    }else if(token[0] == '-'){
        tokenType = SubTokenType;
    }else if(token[0] == '*'){
        tokenType = MulTokenType;
    }else if(token[0] == '/'){
        tokenType = DivTokenType;
    }else if(token[0] == '('){
        tokenType = LparamTokenType;
    }else if(token[0] == ')'){
        tokenType = RparamTokenType;
    }

    InsertToken(token,tokenType);
}

bool ParseInput(const std::string& input)
{
    bool bRet = false;
    CALC_STATUS status = InitStatus;
    size_t begPos , endPos ;
    bool foundPoint = false;

    tokenDeque.clear();

    for(size_t index= 0;index < input.size();++index){
        switch(status){
        case InitStatus:
            if(isspace(input[index])){
                continue;
            }else if(isdigit(input[index])){
                status =  InNumberStatus;
                begPos = index;
                continue;
            }else if( IsIdent(input[index]) ){
                status =  InIdentStatus;
                begPos = index;
                continue;
            }else{
                status =  BadStatus;
                //std::cout << "parse bad input,index is " << index << std::endl;
                break;
            }
            break;
        case InNumberStatus:
            if(isdigit(input[index])){
                status =  InNumberStatus;
                continue;
            }else if(input[index]=='.'){
                if(foundPoint){
                    status =  BadStatus;
                    //std::cout << "parse bad input,index is " << index << std::endl;
                    break;
                }
                status =  InNumberStatus;
                foundPoint = true;
                continue;
            }else if( IsIdent(input[index])){
                endPos = index;
                InsertToken(input.substr(begPos,endPos-begPos),NumberTokenType);
                begPos = index;
                status =  InIdentStatus;
                foundPoint = false;
                continue;
            }else if(isspace(input[index])){
                endPos = index;
                InsertToken(input.substr(begPos,endPos-begPos),NumberTokenType);
                status =  InitStatus;
                foundPoint = false;
                continue;
            }
            else{
                status =  BadStatus;
                break;
            }
        case InIdentStatus:
            endPos = index;
            InsertIdentToken(input.substr(begPos,endPos-begPos));
            status =  InitStatus;
            --index;
            continue;
        default:
            status =  BadStatus;
            break;
       }//switch(status)
    }//for(size_t index= 0;index < input.size();++index)

    if(status !=  BadStatus &&  status !=  InitStatus){
        endPos = std::string::npos;
        if(status == InNumberStatus)
        {
            InsertToken(input.substr(begPos,endPos-begPos),NumberTokenType);
        }else if(status == InIdentStatus){
            InsertIdentToken(input.substr(begPos,endPos-begPos));
        }

        bRet = true;
    }else if(status ==  InitStatus){
        bRet = true;
    }

    if(!bRet)
        tokenDeque.clear();
    return bRet;
}

void PrintErrorMsg(const string& input){
    std::cout << std::endl << "test error!!" << std::endl;
    std::cout << "input is " << input << "."<< std::endl;
}



void TestInput(const string& input,bool result,size_t tokenCount){
    static int i = 1;
    if( ParseInput(input) != result) {
        PrintErrorMsg(input);
        std::cout << "result is not  " << result << std::endl<< std::endl;
    }else if( tokenDeque.size() != tokenCount ){
        PrintErrorMsg(input);
        std::cout <<"tokenCount is " <<tokenDeque.size() << " not  " << tokenCount << std::endl <<std::endl;
    }else{
        std::cout << i << "	times test pass!" << std::endl;
    }
    i++;
}



bool GetNextToken(TOKEN_TUPLE& tokenTuple)
{
    if(tokenDeque.empty()){
        tokenTuple.t = BadTokenType;
        return false;
    }
    tokenTuple = tokenDeque.back();
    tokenDeque.pop_back();
    return true;
}

void UngetToken(const TOKEN_TUPLE& tokenTuple){
    tokenDeque.push_back(tokenTuple);
}

bool ParsePression(double& value);

bool ParsePrimaryExpression(double& value)
{
    bool ret = false;
    bool minusFlag = false;
    TOKEN_TUPLE tt;

    GetNextToken(tt);
    if (tt.t == SubTokenType) {
        minusFlag = true;
    } else {
        UngetToken(tt);
    }

    GetNextToken(tt);
    if(tt.t == NumberTokenType){
        value = std::stod(tt.s);
    }else if(tt.t == LparamTokenType){
        if(!ParsePression(value))
            return false;
        GetNextToken(tt);
        if(tt.t != RparamTokenType){
            return false;
        }
    }else{
        UngetToken(tt);//??
    }

    if(minusFlag)
        value = -value;

    ret =true;
    return ret;
}

bool ParseTerm(double& value){
    bool ret = false;
    double v1;
    double v2;
    TOKEN_TUPLE tt;

    if(!ParsePrimaryExpression(v1) )
        return ret;

    for(;;){
        GetNextToken(tt);
        if(tt.t != MulTokenType &&
                tt.t != DivTokenType&&ret){
            UngetToken(tt);
            break;
        }
        ParsePrimaryExpression(v2);
        if(tt.t == MulTokenType){
            v1 = v1*v2;
        }else if(tt.t == DivTokenType){
            if(v2 ==0.0)
                return ret;
            v1 = v1/v2;
        }
    }

    value = v1;
    ret = true;
    return ret;
}

bool ParsePression(double& value){
    bool ret = false;
    double v1;
    double v2;
    TOKEN_TUPLE tt;

    if(tokenDeque.empty())
        return ret;

    if(!ParseTerm(v1))
        return ret;
    for(;;){
        GetNextToken(tt);
        if(tt.t != AddTokenType && tt.t != SubTokenType){
            UngetToken(tt);
            break;
        }
        ParseTerm(v2);
        if(tt.t == AddTokenType){
            v1 = v1+v2;
        }else if(tt.t == SubTokenType){
            v1 = v1-v2;
        }else{
            UngetToken(tt);
        }
    }


    value = v1;
    ret = true;
    return ret;
}


int main(int argc, char *argv[])
{
//    std::string input;
//    cin >> input;
//    cout << input << endl;
//    TestInput("2",true,1);
//    TestInput("0.2",true,1);
//    TestInput("2 3",true,2);
    TestInput("2.467  + 3",true,3);
    double d;
    bool ret = ParsePression(d);
//    TestInput("()2.467  + 3",true,5);
//    TestInput("3.14 + ( 2.43-1) /3 *(2*6)",true,15);

//    TestInput(".()2.467  + 3",false,0);
//    TestInput("aas+2()2.467  + 3",false,0);
//    TestInput("2.46.7  + 3",false,0);
//    TestInput("2.4(6.7  + 3",true,5);

    return 0;
}
View Code

显示结果

第二段

  1 // 11111.cpp : 定义控制台应用程序的入口点。
  2 //
  3  
  4 #include "stdafx.h"
  5 #include <string>
  6 #include <iostream>
  7  
  8  
  9 using namespace std;
 10  
 11 std::string s1 = "2+3-2";
 12 std::string s2 = "2+3*3";
 13 std::string s3 = "2+(3*3)";
 14 std::string s4 = "()2+(3*3)";
 15  
 16 int gStringIndex = 0;
 17  
 18 bool ParseExPression(const std::string& s, int& v);
 19  
 20 #define ERROR_MSG   
 21 std::cerr << "Error. Func : " << __FUNCTION__ << ".	Line : " << __LINE__ << std::endl;   
 22 std::cerr << "expression is " << s << ".  error index is " << gStringIndex << std::endl;  
 23 exit(0);
 24  
 25  
 26 bool ParsePrimaryExpression(const std::string& s, int& v)
 27 {
 28     bool minusFlag = false;
 29  
 30     if (s[gStringIndex] == '-') {
 31         minusFlag = true;
 32         ++gStringIndex;
 33     }
 34  
 35     if (isdigit(s[gStringIndex])) {
 36         std::string token = s.substr(gStringIndex, 1);
 37         v = stoi(token);
 38         gStringIndex++;
 39         if (minusFlag)
 40             v = -v;
 41         return true;
 42     }
 43     else if (s[gStringIndex] == '(')
 44     {
 45         gStringIndex++;
 46         if (!ParseExPression(s, v)) {
 47             ERROR_MSG;
 48         }
 49         if (s[gStringIndex] == ')') {
 50             gStringIndex++;
 51             if (minusFlag)
 52                 v = -v;
 53             return true;
 54         }
 55     }
 56     else {
 57         ERROR_MSG;
 58     }
 59          
 60  
 61  
 62  
 63     return false;
 64 }
 65  
 66  
 67 bool ParseTerm(const std::string& s, int& v)
 68 {
 69     int v1;
 70     int v2;
 71     char ident = 0;
 72  
 73     if (!ParsePrimaryExpression(s, v1)) {
 74         ERROR_MSG;
 75     }
 76     while (1) {
 77         if (s[gStringIndex] != '*' &&
 78             s[gStringIndex] != '/')
 79         {
 80             break;
 81         }
 82         else {
 83             ident = s[gStringIndex];
 84             ++gStringIndex;
 85         }
 86  
 87         if (!ParsePrimaryExpression(s, v2)) {
 88             ERROR_MSG;
 89         }
 90  
 91         if (ident == '*')
 92         {
 93             v1 = v1*v2;
 94         }
 95         else if (ident == '/' && v2 != 0) {
 96             v1 = v1 / v2;
 97         }
 98         else {
 99             ERROR_MSG;
100         }
101     }
102  
103     v = v1;
104     return true;
105 }
106  
107 bool ParseExPression(const std::string& s, int& v)
108 {
109     int v1;
110     int v2;
111     char ident = 0;
112  
113  
114     if (!ParseTerm(s, v1)) {
115         ERROR_MSG;
116     }
117  
118     while (1) {
119         if (s[gStringIndex] != '+' &&
120             s[gStringIndex] != '-')
121         {
122             break;
123         }
124         else {
125             ident = s[gStringIndex];
126             ++gStringIndex;
127         }
128  
129         if (!ParseTerm(s, v2)) {
130             ERROR_MSG;
131         }
132  
133         if (ident == '+')
134         {
135             v1 = v1+v2;
136         }
137         else if (ident == '-') {
138             v1 = v1 - v2;
139         }
140         else {
141             ERROR_MSG;
142         }
143  
144     }
145  
146     v = v1;
147     return true;
148 }
149  
150  
151 bool  ParseInput(const std::string& s)
152 {
153     gStringIndex = 0;
154     int v;
155     if (!ParseExPression(s, v)) {
156         ERROR_MSG;
157     }
158          
159     std::cout << s << " = " << v << endl;
160  
161  
162     return true;
163 }
164  
165 int main()
166 {
167     ParseInput(s1);
168     std::cout << std::endl << std::endl;
169  
170     ParseInput(s2);
171     std::cout << std::endl << std::endl;
172  
173     ParseInput(s3);
174     std::cout << std::endl << std::endl;
175  
176     ParseInput(s4);
177     std::cout << std::endl << std::endl;
178  
179     return 0;
180 }
View Code

显示结果

作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
阿里打赏 微信打赏
原文地址:https://www.cnblogs.com/itdef/p/7106101.html