• 【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;
    }


  • 相关阅读:
    [贪心] JZOJ P3757 随机生成器
    [kmp] JZOJ P3756 动物园
    [kmp] JZOJ P3756 动物园
    [记忆化搜索] JZOJ P3767 路径
    [dfs序][线段树][并查集] JZOJ P3766 大融合
    [归并][随机算法] JZOJ P3765 想法
    [枚举][dfs] JOZJ P3749 Fox and City
    [hash] JZOJ P3669 抄卡组
    [dfs][图] 洛谷 P1330 封锁阳光大学
    [并查集]NOIP 2015 Day1 信息传递
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632348.html
Copyright © 2020-2023  润新知