zoukankan      html  css  js  c++  java
  • 栈应用之中缀表达式计算 MFC实现(计算器核心)

    大家好,我是小鸭酱,博客地址为:http://www.cnblogs.com/xiaoyajiang

    支持小数、阶乘、乘方、加减乘除、括号优先级运算,美化输出结果(显示结果末尾没有多余的0)

    void CCaculator_LittleduckDlg::OnBnClickedButton12()  // 在这里进行运算 最关键的代码
    {
    // TODO: 在此添加控件通知处理程序代码
    CString editText;
    GetDlgItemText(IDC_EDIT2, editText);
     
    double ans = 0;
    CString CString_ans("Sorry, but I do not know.");
    int noans = 0;
     
     
     
     
    CString operators ("$");  // 运算符栈
    int operators_len = 1;
     
    double numbers[100]={0};  // 数字栈
    int numbers_len = 0;
     
    const char pri[9][9] = {  // [栈顶][当前]     = 表示抵销  >表示计算  <表入栈   " "为匹配不成功
    //------------当前运算符
    //  +   -   *   /   ^   !   (   )   $
    //  0   1   2   3   4   5   6   7   8
    /*    + 0*/'>','>','<','<','<','<','<','>','>',
    /* 栈 - 1*/'>','>','<','<','<','<','<','>','>',
    /* 顶 * 2*/'>','>','>','>','<','<','<','>','>',
    /* 运 / 3*/'>','>','>','>','<','<','<','>','>',
    /* 算 ^ 4*/'>','>','>','>','>','<','<','>','>',
    /* 符 ! 5*/'>','>','>','>','>','>',' ','>','>',
    /*    ( 6*/'<','<','<','<','<','<','<','=',' ',
    /*    ) 7*/' ',' ',' ',' ',' ',' ',' ',' ',' ',
    /*    $ 8*/'<','<','<','<','<','<','<',' ','='
    };
     
    CString tail("$");
    editText += tail;
     
    CString blank(" ");
    CString mynum("0123456789.");
    CString myoper("+-*/^!()$");
     
    int digit = 0;  // 当前数字位数
    int point = 0;  // 小数点个数
    for(int i = 0; i < editText.GetLength(); ++i)  // 开始处理这个字符串
    {
    if( editText[i] == blank )  // 空白则略过
    {
    continue;
    }
    else if(editText[i] == mynum[0] || editText[i] == mynum[1] ||
        editText[i] == mynum[2] || editText[i] == mynum[3] ||
    editText[i] == mynum[4] || editText[i] == mynum[5] ||
    editText[i] == mynum[6] || editText[i] == mynum[7] ||
    editText[i] == mynum[8] || editText[i] == mynum[9] )   // 数字处理
    {
    ++ digit;
    if (digit > 1)  // 数字位数大于1,则数字栈顶数字出栈,重新整理再入栈
    {
    CString temp = blank;
    temp = editText[i];  
    numbers[ numbers_len - 1] = numbers[ numbers_len - 1] * 10 + _wtof(temp) ;
    if(point > 0)
     ++ point;   // 记录小数的位数
    }
    else  // 数字入栈
    {
    ++ numbers_len;
    CString temp = blank;
    temp = editText[i];  
    numbers[numbers_len -1] = _wtof(temp);
    //* (numbers + numbers_len - 1) = atof(temp);
    }
    }
    else if (editText[i] == mynum[10])
    {
    point = 1;
    }
    else   //   !!! 最重要的运算 = 表示抵销  >表示计算  <表入栈   " "为匹配不成功   
    {
    digit = 0;
    if (point > 0)
    {
    point --;
    for(int tem = 0; tem < point; ++ tem)
    numbers[ numbers_len - 1] = numbers[ numbers_len - 1] / 10;  // 刚刚入栈的那个数调整其小数点
    point = 0;
    }
     
     
    CString temp = blank;
    temp = editText[i];  //当前运算符
     
    int top = 0, cur = 0;
    for(int a = 0; a < myoper.GetLength(); ++ a)
    {
    if( myoper[a] == temp )
    {
    cur = a;
    }
    if( myoper[a] == operators[operators_len - 1] )
    {
    top = a;
    }
    }
    char cpri = pri[top][cur];
    if(cpri == '<')//运算符入栈
    {
    ++ operators_len;
    operators += temp;
    }
    if(cpri == '>')  // 计算 注意i的值在下一次不变 记得取出运算符
    {
    if(top < 5 && numbers_len < 2)
    {
    noans = 1;
    break;
    }
    if(numbers_len > 1 && top < 5)
    {
    //  取出两个数
    double number1, number2, number3 = 1;
    number1 = numbers[ numbers_len - 2 ];
    number2 = numbers[ numbers_len - 1 ];
     
    // 进行运算
    switch (top)
    {
    case 0:  // + 运算
    number3 = number1 + number2;
    break;
    case 1:  // - 运算
    number3 = number1 - number2;
    break;
    case 2:  // * 运算
    number3 = number1 * number2;
    break;
    case 3:  // / 运算
    number3 = number1 / number2;
    break;
    case 4:  // ^ 运算
    for(int te = 0; te < number2; ++ te)
    {
    number3 *= number1;
    }
    break;
    }
     
    // 把结果放回栈顶
    -- numbers_len;
    numbers[ numbers_len - 1 ] = number3;
    //
     
    //丢掉最后一个运算符
    -- operators_len;
    CString temp11("");
    for(int l = 0; l < operators_len; ++ l) 
    {
    temp11 += operators[l];
    }
    operators = temp11;
     
    }
     
    if(top == 5 && numbers_len > 0)  // ! 运算 取出一个数做阶层运算 并把结果放回栈中
    {
    double number2, number3 = 1;
    number2 = numbers[ numbers_len - 1 ];
     
    -- operators_len;
    CString temp11("");
    for(int l = 0; l < operators_len; ++ l)   // 丢掉最后一个运算符
    {
    temp11 += operators[l];
    }
    operators = temp11;
     
    for (int te = 1; te <= number2; te++)
    {
    number3 *= te;
    }
    if(number2 == 0)
    {
    number3 = 1;
    }
     numbers[ numbers_len - 1 ] = number3;
    }
     
    -- i;
    }
    if(cpri == '=')  // 运算符抵销
    {
    -- operators_len;
    CString temp11("");
    for(int l = 0; l < operators_len; ++ l)   // 丢掉最后一个运算符
    {
    temp11 += operators[l];
    }
    operators = temp11;
    }
    if(cpri == ' ')  // 运算符不匹配 终止运算并显示Sorry, but I do not know.
    {
    noans = 1;
    break;
    }
    }
    }
     
    if (numbers_len == 1 && operators_len == 0 && noans == 0)
    {
    ans = numbers[ numbers_len - 1];
    CString_ans.Format(L"%f", ans);
    int point = 0;
    CString cpoint(".");
    CString blank("0");
    for (int i = 0; i < CString_ans.GetLength(); i++)
    {
    if(CString_ans[i] == cpoint)
    {
    point = i;
    break;
    }
    }
    if(point > 0)
    {
    for (int i = CString_ans.GetLength() - 1; i >= point; i--)
    {
    if(CString_ans[i] != blank)
    {
    CString mystr("");
    for(int k = 0; k < i; ++k)
    {
    mystr += CString_ans[k];
    }
    if(i > point)
    {
    mystr += CString_ans[i];
    }
    CString_ans = mystr;
    break;
    }
    }
    }
    }
    if(noans == 1 || numbers_len > 1 || operators_len > 0)
    {
    CString_ans = "Sorry, but I do not know.";
    }
    SetDlgItemText(IDC_EDIT2, CString_ans);
    }
  • 相关阅读:
    python种的builtin函数详解第三篇 C
    python中的buildin函数详解(第一篇) C
    python中的formatter的详细用法 C
    python中的builtin函数详解第二篇 C
    python中函数的默认参数陷阱问题 C
    介绍C++11标准的变长参数模板
    猜数字
    父类和子类
    矩形的面积
    水果类
  • 原文地址:https://www.cnblogs.com/xiaoyajiang/p/5950285.html
Copyright © 2011-2022 走看看