第四次作业 计算器第二步

题目链接:

http://www.cnblogs.com/fzuoop/p/5326667.html

github链接:

https://github.com/MeKChen2/object-oriented/tree/master/Calculator-fourth homework

1.解题思路:

这次拿到的题目要求在第三次作业上进行修改,在看过学长在第三次作业上的评论后,我重新审了一次第三次的题目,发现我把题目理解错了。
在将第三次作业的代码改成五个文件的时候,出现了很多问题,无论用什么编译器都无法正常将代码分成五个文件。
所以,在进一步学习了栈的知识和浏览了许多博客后,我打算完全放弃第三次的代码来写第四次的作业。

表达式的计算思路:

1)准备两个栈:数据栈和运算符栈;反复读取表达式 。
2)如果是数,入数据栈;
3)如果是左括号,入运算符栈,如果是右括号,反复从运算符栈顶取运算符和从数据栈里取两个数据进行计算,并把结果入数据栈,直到遇到栈顶是左括号为止。
4)如果是运算符op,先跟栈顶的运算符比,只要不高于栈顶优先级,就取出栈顶的运算符和数据栈的两个数据进行计算,并把结果入数据栈,直到高于栈顶运算符优 先级或者遇到左括号或者运算符栈空为止,此时把op入栈;
5)处理栈中的运算符:取出栈顶的运算符和数据栈的两个数据进行计算,并把结果入数据栈,直到运算符栈空为止;
6)这时数据栈中的数据就是计算结果。

代码如下:
#include <iostream>  
#include <stack>  
#include <string>
#include <cstring> 
using namespace std;  
   
class Calculation
{  
    private:  
        stack<char> oper;
        stack<double> shu;
        double v,a,b;
        char op; //运算符   
    public:  
        double calinput() //读取并计算表达式直到结束为止  
        {  
            do  
            {  
                readdata();
            }  
            while(readop());
            calsurplus(); //处理栈中剩余的运算符 
            cout << v << endl;
            return 0;
        }   
          
        void readdata() //读取数据 
        {
            while(!(cin>>v))  //判断读取数据是否正常 
            {
                cin.clear();
                cin >> op;
                oper.push(op);
            }  
            shu.push(v);
            return;
        }
        
        bool readop() //读取运算符   
        {   
             while((op = cin.get()) == ')')  
             {  
                while( oper.top() != '(' )  
                {  
                    b = shu.top(); 
                    shu.pop();   
                    a = shu.top();  
                    shu.pop();  
                    shu.push(cal(a, oper.top(), b)); //计算并入栈  
                    oper.pop(); //取走运算符   
                }     
                oper.pop();   
             }  
             if(op == '\n')  
             {  
                return false;  
             }  
               
             while(!oper.empty() && oper.top() != '(' && !com( op, oper.top()))  
             {  
                b = shu.top(); 
				shu.pop();  
                a = shu.top(); 
				shu.pop();  
                shu.push(cal( a, oper.top(), b )); //计算并入栈  
                oper.pop(); //取走运算符    
             }  
               
             oper.push(op);  
             return true;  
        }   
          
        void calsurplus()
        {  
            while(!oper.empty())  
            {  
                b = shu.top(); 
		shu.pop();  
                a = shu.top(); 
		shu.pop();  
                shu.push(cal( a, oper.top(), b )); //计算并入栈  
                oper.pop(); //取走运算符   
            }  

            v = shu.top();  
            shu.pop();  
            return;  
        }  
        
        double cal(double a, char op, double b)  
        {  
			if(op=='+')
			    return a+b;
			else if(op=='-')
			    return a-b;
			else if(op=='*')
			    return a*b;
			else if(op=='/')
			    return a/b;
        }  
          
        bool com(char c, char d) //若c比d优先级高返回true,否则返回false   
        {  
            if(c != '+' && c != '-' && d != '*' && d != '/')
            	return true;
            else
            	return false;
        }  
          
};  
  
int main()  
{  
    Calculation e;
    e.calinput();
    system("pause");  
    return 0;  
} 

运行结果:

存在的问题:

这部分代码无法满足题目要求,即当输入-a时要输出表达式,本想写完主要代码再进行-a那步骤的修改,想了很久没有想出方法。
而且我定义的两个栈,一个是char,一个是double,所以没有用到sstream来将字符转换成数字。

改进:

剩下的三天时间,打算用其他方法再进行尝试,改进代码。

反思:

此次代码虽然没有通过第三次代码基础修改得到,但是这次我查阅学习了资料,自我感觉代码比之前第三次的要好了很多,第三次的代码用这次的方法也能更容易写出,现在来看第三次作业反而觉得很简单。以后的学习中应该先掌握好足够的知识,再进行做题,更有效果

参考资料:

http://www.nowamagic.net/librarys/veda/detail/2306
http://blog.csdn.net/anye3000/article/details/7941231
http://blog.sina.com.cn/s/blog_786ce14d01014ixq.html

4.10更新版本二:

#include <iostream>  
#include <stack>   
#include <string>  
using namespace std;  
const int SIZE = 100;  
  
bool isOperator( char op )  
{  
    switch(op)  
    {  
        case '+':  
        case '-':  
        case '*':  
        case '/':  
            return true;  
        default:  
            return false;  
    }  
}  
  
int check( char op )
{  
    int value = -1;  
    switch(op)  
    {   
        case '(':  
            value = 0;  
            break;  
        case '+':  
        case '-':  
            value = 1;  
            break;  
        case '*':  
        case '/':  
            value = 2;  
            break;  
    }  
      
    return value;  
}    

int change( string str, char a[SIZE], int &len ,int &sum )  
{  
	// 中缀式转换为后缀式    	
    stack<char> oper;   
    oper.push('\0');  
    int i = 0;  
    int j = 0;  
      
    while( str[i] != '\0' )  
    {  
        if( str[i] >= '0' && str[i] <= '9' || str[i] == '.' )  
        {  
            a[j++] = str[i];  
            len++;  
        }   
        else if( str[i] == '(' ) 
        {  
            oper.push(str[i]);  
        }  
        else if( str[i] == ')' )   
        {  
            while( oper.top() != '(' )  
            {  
               	a[j++] = oper.top();  
                oper.pop();  
                len++;  
            }  
            oper.pop(); 
        }  
        else if( i == 0 && (str[i] == '+' || str[i] == '-') && str[i+1] != 'a') //表明第一个数为正负号  
        {  
            a[j++] = str[i];  
            len++;  
        }
        else if( i == 2 && (str[i] == '+' || str[i] == '-') && str[i-1] == 'a') //表明当出现"-a"时第三个数为正负号  
        {  
            a[j++] = str[i];  
            len++;  
        }
		else if( i == 0 && str[i] == '-' && str[i+1] == 'a' /*&& str[i+2] == ' '*/ )
        {  
            sum = 1;
        }
        else if( isOperator(str[i]) )  
        {  
            a[j++] = ' ';  //用空格隔开数  
            len++;    
            while( check(str[i]) <= check( oper.top() ) )  
            {  
                a[j++] = oper.top();  
                oper.pop();  
                len++;  
            }  
            oper.push(str[i]); 
        }  
        i++;  
    }   
      
    while( oper.top() != '\0' )
    {  
        a[j++] = oper.top();  
        oper.pop();  
        len++;  
    }  
      
    return 0;  
}  
  
double read(char str[],int *i)    
{    
    double x=0.0;    
    int k = 0;    
    while(str[*i] >='0' && str[*i]<='9')  // 处理整数部分    
    {    
        x = x*10+(str[*i]-'0');    
        (*i)++;    
    }    
    
    if(str[*i]=='.') // 处理小数部分    
    {    
        (*i)++;    
        while(str[*i] >= '0'&&str[*i] <='9')    
        {    
            x = x * 10 + (str[*i]-'0');    
            (*i)++;    
            k++;    
        }    
    }    
    while(k!=0)    
    {    
        x /= 10.0;    
        k--;    
    }    
    
    return x;    
}    
  
  
double calculate( char post[SIZE] )  
{  
	// 计算后缀表达式结果 
    stack<double> stack;   // 操作数栈   
    double x1 = 0;  
    double x2 = 0;  
    bool flag = false;  
    int i = 0;  
    double d = 0;  
      
    while( post[i] != '\0' )  
    {  
        if( post[i] >= '0' && post[i] <= '9' )  
        {  
            d =  read(post,&i);  
            if(flag) // 第一个数为负数  
            {  
                d = -d;  
                flag = false;  
            }  
            stack.push(d);  
        }   
        else if(post[i] == ' ' )  
            i++;    
        else if (post[i] =='+')    
        {    
            x2 = stack.top();    
            stack.pop();  
            x1 = stack.top();   
            stack.pop();  
            stack.push(x1+x2);    
            i++;    
        }    
        else if( post[i] == '-' && i == 0 ) //表明第一个数为负数,方便计算-1+2*3  
        {  
            flag = true;  
            i++;  
        }  
        else if (post[i] =='-')    
        {    
            x2 = stack.top();    
            stack.pop();  
            x1 = stack.top();  
            stack.pop();   
            stack.push(x1-x2);    
            i++;    
        }    
        else if (post[i] =='*')    
        {    
            x2 = stack.top();    
            stack.pop();  
            x1 = stack.top();    
            stack.pop();  
            stack.push(x1*x2);    
            i++;    
        }    
        else if (post[i] =='/')    
        {    
            x2 = stack.top();    
            stack.pop();  
            x1 = stack.top();    
            stack.pop();  
            stack.push(x1/x2);    
            i++;    
        }    
    }    
      
    return stack.top();   
}  
  
int main()  
{  
    string str = "";
	string str1 = ""; 
	int i = 0;
	int chang = 0;
    char a[SIZE];   
    cin >> str;
    chang = str.size();
    int len = 0;
	int sum = 0;  
    change( str, a, len ,sum);  
    a[len] = '\0';
	if(sum == 1)  
	{
		str1 = str.substr(2,chang-2); 
    	cout << str1 << "= " << calculate(a) << endl;
	}
    else
    	cout << calculate(a) << endl;
    system("pause");  
    return 0;  
} 

运行结果:

反思:

换了一种方案后能够实现输入“-a”时输出表达式,通过把中缀表达式转换成后缀表达式进行计算。但代码仍有很多细节不符合题目要求,需要进一步修改。

posted @ 2016-04-07 15:09  MeKChen  阅读(265)  评论(12编辑  收藏  举报