Qt之加减乘除四则运算-支持负数

Posted swarmbees

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt之加减乘除四则运算-支持负数相关的知识,希望对你有一定的参考价值。

一、效果展示

如图1所示,是简单的四则运算测试效果,第一列为原始表达式,第二列为转换后的后缀表达式,冒号后为结果。表达式支持负数和空格,图中是使用了5组测试数据,测试结果可能不全,如大家发现算法有问题,可留言,谢谢。

技术分享图片技术分享图片

图1 四则运算展示

 

二、一些小技巧

  在网上找了很多四则运算帖子,讲的都挺不错,思路很清晰,可是很少有拿来直接能用的,并且大多数的都不支持负数运算,既然是四则运算当然需要支持负数运算了,在这里我们只需要使用一点儿小技巧即可。

1、针对负号进行字符串修复 例如:-1*-3+2*(3+3) -> (0-1)*(0-3)+2*(3+3)。

 1 //针对负号进行字符串修复 例如:-1*-3+2*(3+3) -> (0-1)*(0-3)+2*(3+3)
 2 void repairExpress(QString & express)
 3 {
 4     bool repair = false;
 5     int lpos = -1, rpos = -1;
 6     QString result;
 7     for(int i = 0; i < express.size(); ++i)
 8     {
 9         QChar c = express[i];
10         if (c == + || c == - || c == * || c == /)//出现符号时记录
11         {
12             if (repair)
13             {
14                 result.append());
15                 lpos = -1;
16                 repair = false;
17             }
18 
19             if (c == -&&
20                 (i == 0  || lpos != -1 && lpos == i - 1))
21             {
22                 result.append(();
23                 repair = true;
24             }
25 
26             lpos = i;
27         }
28 
29         result.append(c);
30     }
31 
32     express = result;
33 }

2、为了方便后续我们计算表达式,在中缀表达式转后缀表达式时,我们在数字和负号之间加了一个空格。

1 //数字和负号之间插入空格, 方便后续计算时分割
2 void rettifyExpress(QString & express)
3 {
4     if (express.endsWith( ) == false)
5     {
6         express.append( );
7     }
8 }

三、后缀表达式

中缀表达式:是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:3 + 4),中缀表达式是人们常用的算术表示方法。

后缀表达式:后缀表达式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则)。

中缀表达式转后缀表达式的方法:

1.遇到操作数:直接输出(添加到后缀表达式中)
2.栈为空时,遇到运算符,直接入栈
3.遇到左括号:将其入栈
4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
6.最终将栈中的元素依次出栈,输出。

下边我直接给出实现代码

技术分享图片
 1 //中缀表达式转后缀表达式
 2 QString change(const QString & s_mid)
 3 {  
 4     QString result;
 5     QStack<QChar> stk;
 6 
 7     QMap<QChar, int> op;//利用map来实现运算符对应其优先级
 8     op[(]=0;
 9     op[)]=0;
10     op[+]=1;
11     op[-]=1;
12     op[*]=2;
13     op[/]=2;
14     auto iter = s_mid.begin();
15     for(int i = 0; i < s_mid.size(); ++i)
16     {
17         QChar c = s_mid[i];
18         if (c ==  )
19         {
20             continue;
21         }
22         if (c == - &&
23             (i == 0 || op.contains(s_mid[i-1])))//可能为负号
24         {
25             result.append(0);
26         }
27         if(op.contains(c))//判断该元素是否为运算符
28         {
29             if(c == ))//情况2
30             {
31                 while(stk.top() != ()
32                 {
33                     rettifyExpress(result);
34                     result.append(stk.top());
35                     stk.pop();
36                 }
37                 stk.pop();
38             }
39             else if(stk.empty() || c == ( || op[c] > op[stk.top()])//情况1、情况3
40             {
41                 stk.push(c);
42             }
43             else if(op[c] <= op[stk.top()])//情况3
44             {
45                 while(op[c] <= op[stk.top()] && (!stk.empty()))
46                 {
47                     rettifyExpress(result);
48                     result.append(stk.top());
49                     stk.pop();
50                     if(stk.empty()) break;
51                 }
52                 stk.push(c);
53             }
54 
55             rettifyExpress(result);
56         }
57         else
58         {
59             result.append(c);
60         }
61     }
62 
63     while(stk.empty() == false)//当中缀表达式输出完成,所有元素出栈
64     {
65         rettifyExpress(result);
66         result.append(stk.top());
67         stk.pop();
68     }
69 
70     return result;
71 }
View Code

四、表达式计算

通过后缀表达式计算时,我们就不需要考虑优先级了,只需要严格按照从左向右,遇到负号取之前的两个数值进行计算即可。

 1 //计算表达式值
 2 double CalExp(const QStringList & express)
 3 {
 4     double result;
 5     QStack<QString> stk;
 6     for (int i = 0; i < express.size(); ++i)
 7     {
 8         QString item = express[i];
 9         if (item.size() == 1 && 
10             (item.at(0) == "+" || item.at(0) == "-" || item.at(0) == "*" || item.at(0) == "/"))
11         {
12             double r = stk.pop().toDouble();
13             double l = stk.pop().toDouble();
14             switch(item.at(0).toLatin1())
15             {
16             case +:
17                 result = l + r;break;
18             case -:
19                 result = l - r;break;
20             case *:
21                 result = l * r;break;
22             case /:
23                 result = l / r;break;
24             }
25 
26             stk.push_back(QString::number(result));
27         }
28         else 
29         {
30             stk.push_back(item);
31         }
32     }
33 
34     return result;
35 }

五、下载链接

  Qt之加减乘除四则运算-支持负数

参考文章:

1、四则运算表达式树 C++模板 支持括号和未知数

2、中缀表达式得到后缀表达式(c++、python实现)

 

以上是关于Qt之加减乘除四则运算-支持负数的主要内容,如果未能解决你的问题,请参考以下文章

python四则运算

四则运算二

软件工程个人作业02

C语言计算器 功能要求: 可以输入0-9数字、小数点、正负数 可以进行加减乘除运算及简单的数学函数运算?

2016012084+小学四则运算练习软件项目报告

小学四则运算题