zoukankan      html  css  js  c++  java
  • 【7002】模拟计算机处理算术表达式过程

    Time Limit: 3 second
    Memory Limit: 2 MB

    问题描述
         从键盘上输入算术表达式串(只含+、-、*、/运算符,允许含圆括号,运算数为整型、实型常量),输出算术表达式的值。设输入的表达式串是合法的。

    Input

        输入为一行算术表达式串

    Output

        输出一行,算术表达式的值(输出两位小数,整数部分按实际位数输出,最后用换行结束)。

    Sample Input

        (3+2)-5*(6-1)
    

    Sample Output

        -20.00
    【题解】
    用分治法来求中缀表达式:
    具体过程.每层递归,都找到所有运算符里面优先级别最低的运算符。
    假设这个运算符的位置为k
    则把1..k-1截出来 设为x,k+1..length(s)也截出来,设为y;
    然后对x和y进行相同的操作。也去找运算级别最小的运算符。。。
    直到最后操作的一个字符串全是数字。然后就返回这个数字就好。
    最后根据k位置的运算符。做相应的运算。
    即"x" 运算符 "y";
    【代码】
    #include <cstdio>
    #include <stdlib.h>
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    string s;
    
    char cmp(char x, char y) //判断操作符x和操作符y,哪一个优先级大 
    {
    	if (x == '$')
    		return '>';
    	if ( (x == '*' || x == '/')	&& (y == '+' || y =='-'))//乘法和除法的优先级比加减法高 
    		return '>';
    	if ( (x == '+' || x == '-') && (y == '+' || y =='-')) //如果是同一优先级。则往后找运算符。因为同一优先级先找到的是后运算的 
    		return '>';
    	if ( (x == '*' || x == '/')	&& (y == '*' || y =='/')) //依旧是同一优先级的处理; 
    		return '>';		
    	return '<';
    }
    
    int find(string tt) //表示找tt这个字符串的优先级最小的操作符 
    {
    	int k =0;
    	char now = '$'; 
    	int i = 0;
    	while (i <= tt.size()-1) //用i来枚举 
    		{
    			if (tt[i] == '(') //如果是括号的话就要跳过。因为括号里的东西一定是后算的,不能考虑优先级 
    				{
    					int b = 0; //这是用来匹配这个括号,当然可能有多个括号 用栈的思想来匹配 
    					do
    						{
    							switch (tt[i])
    								{
    									case '(':
    										b++;
    										break;
    									case ')':
    										b--;
    										break;
    								}
    							i++;
    						}
    						while (b !=0);
    				}
    				else
    					if (tt[i] == '*' || tt[i] == '/' || tt[i] == '+' || ( tt[i] == '-' && i >0 && (tt[i-1] ==')' || (tt[i-1] >='0' && tt[i-1] <='9'))))
    						{ //如果是运算符,就先和当前获得的优先级最小的运算符比较。看看是否优先级更低 
    							if (cmp(now,tt[i]) == '>')
    								{
    									now = tt[i];//如果更低 则更新 
    									k = i;
    								}
    							i++;
    						}
    						else
    							i++; //不管是什么 都要递增循环变量 
    		}
    	return k;
    }
    
    void reducebracket(string & tss) //去掉两边的括号 表示对括号里的string进行操作 
    {
    	int ltss = tss.size(); //表示tss的长度 
    	if (tss[0] !='(' || tss[ltss-1]!=')') //如果两边不是配对的括号就返回。 
    		return;
    	int b =0;
    	for (int i = 1;i <= ltss-2;i++) //表示在2到l-1之间查看括号是否配对,因为可能有()+()这样的情况。 
    		{
    			if (tss[i] == '(')
    				b++;
    			if (tss[i] == ')')
    				b--;
    			if (b < 0)
    				return;
    		}
    	if (b!=0)
    		return;
    	tss = tss.erase(ltss-1,1); //去除两边的括号 
    	tss = tss.erase(0,1);	
    }
    
    double reduce( string ss)
    {
    	int i = 0,ls = ss.size();
    	if (ls == 0) //如果长度为0,则直接返回0; 
    		return 0;
    	bool judge = false; //表示是否找到了运算符 
    	while (i <= ls-1)
    		{
    			if (ss[i] == '+' || ss[i] == '*' || ss[i] == '/') //+*/都可以直接判断 
    				 {
    				 	judge = true;
    				 	break;
    				 }
    				 	else //如果是减法的话,要判断它前一位是不是右括号或者是数字。因为可能是负数 
    				 		if (ss[i] == '-' && i > 0 && (ss[i-1] == ')' || (ss[i-1] >='0' && ss[i-1] <='9')))
    				 			{
    							 	judge = true;
    				 				break;
    				 			}
    			i++;
    		}
    	if (!judge) //如果没有运算符。则这个串就是一个数字。直接返回就可以了 
    		{
    			double x = atof(ss.c_str());
    			return x;
    		}
    	reducebracket(ss); //如果有运算符。就先去掉两边的括号(如果有) 
    	int k = find(ss); //找到运算级别最小的运算符的位置 
    	
    	string s1 = ss.substr(0,k); //截取这个运算符左边的"数字" 
    	string s2 = ss.substr(k+1,ss.size()-s1.size()-1); //截取这个运算符右边的"数字" 
    	double x = reduce(s1),y = reduce(s2),z; //对左边和右边的进行计算。 
    	switch (ss[k])  //对ss[k]进行判断 根据运算符做相应的运算。 
    		{
    			case '+':
    				z = x + y;
    				break;
    			case '-':
    				z = x - y;
    				break;
    			case '*':
    				z = x * y;
    				break;
    			case '/':
    				z = x / y;
    				break;
    		}
    	return z; //返回这个值。 
    }
    
    int main()
    {
    	//freopen("F:\rush.txt","r",stdin);
    	getline(cin,s);
    	printf("%.2lf",reduce(s)); 
    	return 0;
    }


  • 相关阅读:
    联想 Vibe Shot(Z90-3) 免recovery 获取ROOT权限 救砖 VIBEUI V3.1_1625
    联想 Z5S(L78071)免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 10.5.370
    联想 Z5(L78011) 免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 10.5.254
    联想 S5 Pro(L78041)免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 5.0.123
    第二阶段 冲刺八
    第二阶段 冲刺七
    第二阶段 冲刺六
    第二阶段 冲刺五
    代码大全阅读笔记03
    学习进度十二
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632348.html
Copyright © 2011-2022 走看看