C/C++ 算数表达式计算

一、原理探讨

其实如果要理清编译原理之类的东西,第一步就是要搞词法分析,有了词法分析,就可以再做语法分析,我文讨论简单的词法分析的一个小例子—算数表达式,这个是我一个网友问到我的问题,虽然脑子里有个大概的思路,要么使用栈模型,要么使用二叉树模型,但思路不是很清晰,花了一些时间来整理了一下思路并形成了代码。思路如下:

  1. 我们要把每个数据拆分开,例:3*2.3+2,即拆成3,*,2.3,+,2
  2. 有了单个数据,我们它由中缀转成后缀表达式,3,2.3,*,2,+
  3. 有了后缀表达式,我们就可以利用栈特性算出值了。

第一个问题比较好解决,第二个问题,怎么转?有括号怎么办?看似比较麻烦,但实质有规律可寻。规律如下:

  1. 符号栈top()优先级大于当前遍历的符号的话,出栈,再入当前当前遍历的符号入栈。
  2. 遇’(‘左括号,符号栈保持不变,并添加’(‘入栈。
  3. 遇’)’右括号,符号栈一直出栈,直到遇到’(‘左括号。

二、上代码

分析了这如上原理,我们可以写出个试试代码来了。由于没有优化的好,代码可能不是很简洁,但足够分析原理。

#include <iostream>
#include <stack>
#include <algorithm>
#include <vector>
using namespace std;
enum AnalysisType:unsigned char{FLOAT=0x01,OPERATOR=0x02};
struct ItemValue
{
    union ValueUnion
    {
        float fdigit;
        char symbol;
    };
    AnalysisType type;
    ValueUnion value;
};
//简单的int加减乘除
int GetPriority(char symbol)
{
    switch (symbol)
    {
    case '+':
    case '-':
        return 0;
    case '*':
    case '/':
        return 1;
    case '(':
    case ')':
        return 2;
    }
    return -1;
}

bool IsOperator(char symbol)
{
    switch (symbol)
    {
        case '+':
        case '-':
        case '*':
        case '/':
        case '(':
        case ')':
        return true;
    }
    return false;
}
//转成vector存
void wordsAnalysis(char*pIn, vector<ItemValue>&vec)
{
    int nCount = strlen(pIn);
    int nIndex = 0;
    while (nIndex<nCount)
    {
        ItemValue item = { FLOAT,0};
//处理操作符
        if (IsOperator(pIn[nIndex]))//如果是操作符
        {
            item.type = OPERATOR;
            item.value.symbol = pIn[nIndex];
            vec.push_back(item);
        }
//处理数字
        int nTemp = nIndex;
        char nBuffer[20] = {0};//20位
        while (isdigit(pIn[nTemp]) || '.'==pIn[nTemp])
        {   
            nBuffer[nTemp - nIndex]=pIn[nTemp];
            ++nTemp;
        }
        if (nTemp != nIndex)
        {
            item.value.fdigit = atof(nBuffer);
            vec.push_back(item);
        }
//
        if (nTemp != nIndex)
            nIndex += strlen(nBuffer);
        else
            ++nIndex;
    }
}
//中缀转后缀
void midToLast(vector<ItemValue> & vecIn, vector<ItemValue> & vecOut)
{
    ItemValue item{ OPERATOR ,0.0f };
    stack<char> stack_symbol;
    for_each(std::begin(vecIn), std::end(vecIn), [&](ItemValue &it) {
        if (FLOAT == it.type )
        {
            vecOut.push_back(it);
        }
        else if (OPERATOR == it.type)
        {
            if (')' == it.value.symbol)
            {
                while (!stack_symbol.empty())
                {
                    if (stack_symbol.top() == '(')
                    {
                        stack_symbol.pop();
                        return;
                    }
                    item.value.symbol = stack_symbol.top();
                    stack_symbol.pop();
                    vecOut.push_back(item);
                }
            }
            if (!stack_symbol.empty())
            {
                if (GetPriority(stack_symbol.top()) - GetPriority(it.value.symbol) >= 0 && stack_symbol.top()!='(')
                {
                    item.value.symbol = stack_symbol.top();
                    stack_symbol.pop();
                    vecOut.push_back(item);
                }
            }
            if(')' != it.value.symbol)
                stack_symbol.push(it.value.symbol);
        }
    });
    //把栈里的操作符提出来
    while (!stack_symbol.empty())
    {
        item.value.symbol = stack_symbol.top();
        stack_symbol.pop();
        vecOut.push_back(item);
    }
}
//计算
float Calculate(vector<ItemValue>& vec)
{
    float fResult=0.0f;
    stack<ItemValue> stack_value;
    for_each(std::begin(vec), std::end(vec), [&](ItemValue &it) {
        if (FLOAT == it.type)
        {
            stack_value.push(it);
        }
        else if(OPERATOR == it.type)
        {
            ItemValue Value1, Value2 ;
            Value2=stack_value.top();
            stack_value.pop();

            Value1=stack_value.top();
            stack_value.pop();

            switch (it.value.symbol)
            {
            case '+':
                Value1.value.fdigit += Value2.value.fdigit;
                break;
            case '-':
                Value1.value.fdigit -= Value2.value.fdigit;
                break;
            case '*':
                Value1.value.fdigit *= Value2.value.fdigit;
                break;
            case '/':
                Value1.value.fdigit /= Value2.value.fdigit;
                break;
            }
            Value1.type = FLOAT;
            stack_value.push(Value1);
        }
    });
    fResult = stack_value.top().value.fdigit;
    return fResult;
}

int main()
{
    char buffer[64] = {0};
    vector<ItemValue> vecIn,vecOut;
    cout << "请输入表达式:";
    cin >> buffer;
    wordsAnalysis(buffer, vecIn);//拆分数据
    midToLast(vecIn,vecOut);//转到后缀表达式,vecOut内
    cout << "中缀到后缀:";
    for_each(std::begin(vecOut), std::end(vecOut), [&](ItemValue &it) {
        FLOAT == it.type?       
        cout << it.value.fdigit << "  ":
        cout << (char)it.value.symbol << "  ";
    });
    cout <<endl<<"计算结果:" << Calculate(vecOut)<<endl ;
    return 0;
}
三、运行成功:

a


更多文章:http://blog.csdn.net/what951006?viewmode=list
powered by:小乌龟在大乌龟背上~

  • 2
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
数据结构课程设计之C编写的算术表达式是一个程序,用于对算术表达式进行求值。它支持括号运算、小数运算,并能检测并报告错误,如非法字符、括号不完整、缺运算数、算式不完整等。同时,它还可以显示中间过程,包括输入串、运算数栈和操作符栈。这个程序可以使用DevC项目进行开发。 另外,如果你想了解如何用算符优先法对算术表达式求值的过程,可以设计一个程序来演示。该程序可以从终端输入一个语法正确且不含变量的整数表达式,并利用运算符优先关系来实现对算术四则混合运算表达式的求值。 值得一提的是,Java编程语言也具备类似于C语言的形式和感觉,但相比C语言更易于使用,并完全采用了以对象为导向的编程方式。使用Java编写的应用程序既可以在单独的电脑上运行,也可以分布在网络上。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [数据结构 算术表达式求值 C++ 栈方法](https://download.csdn.net/download/jinhangdev/10232225)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [数据结构大作业C++实现简单的计算器——算术表达式计算(包含实验报告)](https://download.csdn.net/download/qq_29711355/85774341)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [超详细Java入门到精通自学视频课程-10、继承:构造器特点、this、super小结.rar](https://download.csdn.net/download/weixin_54787054/88280698)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值