大家好,我是小鸭酱,博客地址为: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);
}

栈应用之中缀表达式计算 MFC实现(计算器核心)的更多相关文章

  1. 栈应用之 后缀表达式计算 (python 版)

    栈应用之 后缀表达式计算 (python 版) 后缀表达式特别适合计算机处理 1.  中缀表达式.前缀表达式.后缀表达式区别  中缀表达式:(3 - 5) * (6 + 17 * 4) / 3 17 ...

  2. Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算

    中缀表达式与后缀表达式的转换和计算 目录 中缀表达式转换为后缀表达式 后缀表达式的计算 1 中缀表达式转换为后缀表达式 中缀表达式转换为后缀表达式的实现方式为: 依次获取中缀表达式的元素, 若元素为操 ...

  3. C++实现顺序栈类求解中缀表达式的计算

    控制台第一行打印的数值为使用形如以下方式得到的结果: cout << +*(+)*/- << endl; 即第一个待求解表达式由C++表达式计算所得结果,以用于与实现得出的结果 ...

  4. javascript使用栈结构将中缀表达式转换为后缀表达式并计算值

    1.概念 你可能听说过表达式,a+b,a+b*c这些,但是前缀表达式,前缀记法,中缀表达式,波兰式,后缀表达式,后缀记法,逆波兰式这些都是也是表达式. a+b,a+b*c这些看上去比较正常的是中缀表达 ...

  5. 《java数据结构与算法》笔记-CH4-8栈结构实现后缀表达式计算结果

    /** * 中缀表达式转换成后缀表达式: 从输入(中缀表达式)中读取的字符,规则: 操作数: 写至输出 左括号: 推其入栈 右括号: 栈非空时重复以下步骤--> * 若项不为(,则写至输出: 若 ...

  6. 关于利用STL栈求解四则中缀表达式以及中缀表达式转逆波兰表达式和逆波兰表达式的求解

    今天总结一下栈的一个重要应用---四则数学表达式的求解 数学表达式的求解是栈的一个重要的应用,在计算机的应用中 如果求解一个四则运算表达式,我们可能会直接写一个程序例如什么printf("% ...

  7. 第四章 栈与队列(c4)栈应用:中缀表达式求值

  8. c语言,中缀表达式转后缀表达式并计算

    //c语言中缀表达式计算 #include <stdio.h> #include <stdlib.h> #include <string.h> #include & ...

  9. 算法笔记_044:表达式计算求值(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个表达式. 输出格式 输出这个表达式的 ...

随机推荐

  1. 关于split splice slice 的一些事

    学的知识很久不用总会忘记,更何况这三个的拼写都差不多,在这里特意写下自己的一些见解,以便以后可以更好地理解. slice  : 定义:接收一个或两个参数,它可以创建一个由当前数组中的一项或多项组成的新 ...

  2. [POJ] 1274 The Perfect Stall(二分图最大匹配)

    题目地址:http://poj.org/problem?id=1274 把每个奶牛ci向它喜欢的畜栏vi连边建图.那么求最大安排数就变成求二分图最大匹配数. #include<cstdio> ...

  3. pfsense 2.2RC下的L2TP配置

    还不有测试完成,不过,基本上应该差不多了. 主要参考以下文档: http://blog.sina.com.cn/s/blog_541a3cf10101ard3.html http://thepract ...

  4. 计算机语言学习导论[C/C++]

    作者:@幻の上帝 1 前置条件语文其实挺重要,这个没问题,但容易被忽视.当然,如果不是经常要折腾文档,要求不高:但起码要能说清楚话.数学重要,主要是广度,作为快速学习相关领域知识的基础.深度上面可深可 ...

  5. 合天网安实验室学习笔记----Linux基础

    一.Linux的发展 linux kernel的版本是:2.6.32-279.el6.x86_64,此格式为:主版本.次版本.释出版本-修改版本 次版本为奇数:测试版: 次版本为偶数:稳定版: Lin ...

  6. thinkphp分页时修改last显示标题

    需要修改Page.class.php里lastSuffix为false,这样才能修改last显示标题. 然后就可以设置了 或者直接在方法中声明: $p->lastSuffix = false; ...

  7. 【Eclipse DDMS】 Can't bind to local 8600 for debugger

    问题原因: 电脑上同时安装了Eclipse 和Android Studio两个ide. 关键是使用eclipse adb连接真机时候,android studio也处于运行状态,后者默认也是要连接ad ...

  8. npm 和 bower的区别

    npm和bower在功能上有一定的重合,但不是互斥关系,可以在项目中同时运用.区别在于npm在设计之初就采用了的是嵌套的依赖关系树.一个普通的前端包的依赖树比较长,npm 会将开发环境一起下载下来,  ...

  9. python3-day4(yield)

    1.yield 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外,迭代器的一 ...

  10. vuex 模块

    今天,在我编写系统中一个模块功能的时候,由于我使用vuex存储数据的状态,并分模块存储.我是这样在存储文件中定义state,getters,actions,mutations的,我打算在不同模块文件都 ...