又一篇四则运算代码

代码分为两段

一段为将输入分解为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 << "\ttimes 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;
}

显示结果

第二段

  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__ << ".\tLine : " << __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 }

显示结果

2+3-2 = 3

2+3*3 = 11

2+(3*3) = 11

Error. Func : ParsePrimaryExpression. Line : 57
expression is ()2+(3*3). error index is 1

时间: 2024-08-24 07:03:29

又一篇四则运算代码的相关文章

iOS开发UI篇—从代码的逐步优化看MVC

iOS开发UI篇—从代码的逐步优化看MVC 一.要求 要求完成下面一个小的应用程序. 二.一步步对代码进行优化 注意:在开发过程中,优化的过程是一步一步进行的.(如果一个人要吃五个包子才能吃饱,那么他是否直接吃第五个,前面四个不用吃就饱了?) 1.完成基本要求的代码(使用了字典转模型和xib连线) (1)文件结构 (2)主要代码 字典转模型部分: YYappInfo.h头文件 // // YYappInfo.h // 12-视图改进(1) // // Created by apple on 14

文顶顶 iOS开发UI篇—从代码的逐步优化看MVC

iOS开发UI篇—从代码的逐步优化看MVC 一.要求 要求完成下面一个小的应用程序. 二.一步步对代码进行优化 注意:在开发过程中,优化的过程是一步一步进行的.(如果一个人要吃五个包子才能吃饱,那么他是否直接吃第五个,前面四个不用吃就饱了?) 1.完成基本要求的代码(使用了字典转模型和xib连线) (1)文件结构 (2)主要代码 字典转模型部分: YYappInfo.h头文件 1 // 2 // YYappInfo.h 3 // 12-视图改进(1) 4 // 5 // Created by a

ASP.NET 5系列教程(七)完结篇-解读代码

在本文中,我们将一起查看TodoController 类代码. [Route] 属性定义了Controller的URL 模板: [Route("api/[controller]")] 所有符合该模板类型的HTTP 请求都会被路由到该controller.在本例中, 路由的命名规范为对应Controller 的前缀,对于TodoController 类,路由模板为 “api/todo”. HTTP 方法 [HttpGet].[HttpPost]和[HttpDelete] 属性定义为 co

iOS开发数据库篇—SQL代码应用示例

iOS开发数据库篇—SQL代码应用示例 一.使用代码的方式批量添加(导入)数据到数据库中 1.执行SQL语句在数据库中添加一条信息 插入一条数据的sql语句: 点击run执行语句之后,刷新数据 2.在ios项目中使用代码批量添加多行数据示例 代码示例: 1 // 2 // main.m 3 // 01-为数据库添加多行数据 4 // 5 // Created by apple on 14-7-26. 6 // Copyright (c) 2014年 wendingding. All rights

Cocos2d-x3.0游戏实例之《别救我》第六篇——从代码中获取UI控件

这篇的内容很简单,获取UI控件,然后使用它. 还记得我们在UI编辑器中给三个按钮分别命名了吧? 现在要用上了. 笨木头花心贡献,啥?花心?不呢,是用心~ 转载请注明,原文地址: http://www.benmutou.com/blog/archives/918 文章来源:笨木头与游戏开发 根据名字查找控件 首先给TollgateScene再include一些头文件,不然等会编译又报错了: #include "editor-support/cocostudio/CCSGUIReader.h&quo

Spring Boot 揭秘与实战(五) 服务器篇 - Tomcat 代码配置

Spring Boot 内嵌的 Tomcat 服务器默认运行在 8080 端口.如果,我们需要修改Tomcat的端口,我们可以在 src/main/resources/application.properties 中配置Tomcat信息. server.port=8089 现在,你可以重新运行上面的例子,看下是不是 Tomcat 的端口变成 8089 了. 如果想直接通过代码配置 Tomcat, 可以直接定义 TomcatEmbeddedServletContainerFactory. 现在,我

持续集成篇SonarQube 代码质量管理平台的安装

持续集成篇 SonarQube 代码质量管理平台的安装 -------------------------------- 1.SonarQube的介绍 SonarQube是一个管理代码质量的开放平台. 可以从七个维度检测代码质量(为什么要用SonarQube): (1) 复杂度分布(complexity):代码复杂度过高将难以理解.难以维护 (2) 重复代码(duplications):程序中包含大量复制粘贴的代码是质量低下的表现 (3) 单元测试(unit tests):统计并展示单元测试覆盖

(2)dotnet开源电商系统-brnshop VS nopCommerce(dotnet两套电商来PK--第二篇:代码从哪开始-BrnMall3.0Beta)

看大牛们的源码,对于水平一般的人,还是略微有点难度的.我从我自身读码的亲身体验,写下杂散片语,希望能和大家一同进步,也为了日后记忆上的备查. 先看的是brnMall的源码结构,从哪看起呢? 首先推荐看的肯定是官方的剖析:BrnShop开源网上商城第二讲:ASP.NET MVC框架 官方的这篇文章主要讲清楚了几点: (1)brnshop设计时对网页环境上下文是如何获得,如何保存,并如何访问的(重载了控制器的基类,用于截获http访问时的预处理,身份授权和验证等问题),这些都是mvc程序自定义时惯用

四则运算代码(java版本) 采用正则表达式

//加减乘除 负数.括号这几种//具体看代码以及注释 (测试没发现bug,如发现有bug 请指正) package com.test; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 四则运算,可能不是最优的写法,自己测试没发现bug<br> * 前提:正确的算式,因为没做算式的验证<br>