第四次作業 計算器第二步


題目鏈接:

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”時輸出表達式,通過把中綴表達式轉換成后綴表達式進行計算。但代碼仍有很多細節不符合題目要求,需要進一步修改。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM