第四次程序設計作業 C++計算器計算及命令行的使用 前綴表達式方法實現


關鍵詞:前綴中綴后綴表達式 波蘭式 命令行

myGithub

一.前言

很有意思的開發和學習經歷,從剛剛開始看到作業思考半天到現在的Debug過程,對我來說都或多或少有所提升。
也許這個時候自己挺迷茫的,想未來的路在哪里。一轉眼,自己就走出去了很遠,白駒過隙,時光荏苒。

二.本次作業的步驟梳理

  • 1.Windows系統下的cmd命令行操作
  • 2.輸入字符串input過程中的特判負號
  • 3.計算過程中符號優先級的判斷
  • 4.輸入錯誤的判斷
  • 5.總結與反饋

這里我的解決步驟是:2->4->3->1->5。本篇博客主要介紹第3步和第1步。

三.計算的實現

代碼:

calculation.h

//==============================//
//文件名稱:calculation.h       
//作者:031502209               
//更新時間:2016/4/7            
//博客:qq952693358             
//==============================//
#ifndef CALCULATION_H
#define CALCULATION_H
#include<stack>
#include<queue>
#include<iostream>
#include<stdlib.h>
#include<string>
using namespace std;

//===============================//
//class:Calculation              
//包含:執行計算函數carryout     
//函數類型:int                  
//===============================//
class Calculation
{

	public:
        int carryout(queue<string> que);   
};

#endif // CALCULATION_H

calculation.cpp

//==============================//
//代碼主體部分:calculation      
//文件名稱:calculation.cpp     
//作者:031502209               
//更新時間:2016/4/7            
//博客:qq952693358            
//==============================//

//==================================//
//說明:該部分分為兩大塊            
//1.把原來的式子轉換成為前綴表達式  
//2.前綴表達式的計算                
//==================================//
#include "calculation.h"
#include<stack>
#include<queue>
#include<iostream>
#include<stdlib.h>
#include<string>
#include<sstream>

//======priority=======//
//說明:用於判斷優先級 
//=====================// 
int priority(string s)
{
    if(s=="(" || s== ")")return 0;
	if(s=="+" || s=="-")return 1;
	if(s=="*" || s=="/")return 2;
	if(s=="#")return -1;
}

//======calculate======//
//說明:用於計算      
//=====================// 
int calculate(string s,int a,int b)//double
{	
	if(s=="+")return b+a;
	if(s=="-")return b-a;
	if(s=="*")return b*a;
	
	if(s=="/" && a!=0)return b/a;
	else return 0;
}
//========代碼主體========// 
int Calculation::carryout(queue<string> que)
{
	//判斷是否出錯 
	if(que.empty())
	{
		cout<<"error"<<endl;
		return 0;
	}
	
	stack<string> sign1,sign2;
	stack<string> signstore;//倒序 
	
	string s;
	string que_s;
	string sign1_top;
	
	//==========================//
	//從'='開始從右向左遍歷      
	//所以用一個棧signstore實現 
	//==========================//
	while(!que.empty())
	{
		signstore.push(que.front());
		que.pop();
	}
	
//-------------------------BEGIN-------------------------//	
    
    //======部分1======//
	//轉換為前綴表達式 
	//=================// 
	while(!signstore.empty())
	{
		s=signstore.top();
	    signstore.pop();
		
		if(s=="=")continue;
		if(s=="+" || s=="-" || s=="*" || s=="/" || s=="(" || s==")")
		{
			//=============說明=============// 
			//如果存在以下情況:             
			//(1)s的優先級大於sign1棧頂元素 
			//(2)s==")"                     
			//(3)sign1為空棧                
			//則:s直接push進sign1          
			//==============================//
			
			//sign1為空棧  
			if(sign1.empty())
			{
				sign1.push(s);
				
				continue;
			}
			
			//s==")"
			if(s==")")
			{
				sign1.push(s);
				
				continue;
			}
			
			//=============說明=============// 
			//如果遇到左括號:             
			//把sign1里面的字符push進sign2  
			//直至遇見右括號               
			//==============================//
			if(s=="(")
			{
			    while(sign1.top()!=")")
			    {
			    	sign2.push(sign1.top());
			    	
			    	sign1.pop();
			    }
				sign1.pop();//右括號出棧 
				continue;
			}
			
			//s的優先級大於sign1棧頂元素 //
			if(priority(s) > priority(sign1.top()))
			{
				sign1.push(s);
			    
				continue;
			}
		    
			//s的優先級小於sign1棧頂元素//
			
			//==============說明===============//
			//當遇到s的優先級小於棧頂元素時   
			//把sign1里面的字符從棧頂          
			// push進sign2                    
			//直到棧頂元素優先級大於s          
			//=================================// 
			else if(priority(s) < priority(sign1.top()))
			{
				while(priority(s) < priority(sign1.top()))
				{
					sign1_top=sign1.top();
					
				    sign1.pop();
				    sign2.push(sign1_top);
				}
				sign1.push(s);
				continue;
			}
			else //優先級相同 且非"("括號")"直接入sign1 
			{
				if(s=="+" || s=="-" || s=="*" || s=="/")
				sign1.push(s);
			}
		}
		else //如果是數字的話 push進sign2 
		{
			sign2.push(s);
			continue;
		}
	}
	
	//將sign1中剩余的部分按順序push進sign2 
	while(!sign1.empty())
	{
		sign2.push(sign1.top());
		sign1.pop();
	}
	
	//轉換為前綴表達式 完成 
	
//-------------------------END-------------------------//	
	
	//========部分2========// 
	//計算前綴表達式       
	//=====================//
	
	//sign2逆序存放->sign_2 
	stack<string> sign_2;
	while(!sign2.empty())
	{
		sign_2.push(sign2.top());
		
		sign2.pop();
	}
	
	//使用stringstream 把字符串轉換為數字 
	stringstream stream;
	int number;
	stack<int> numberstore;//存儲數字的棧 
	string s2;
	
	//計算部分 
	while(!sign_2.empty())
	{
		s2=sign_2.top();
		sign_2.pop();
		
		//遇到運算符 提取出numberstore棧頂兩個元素進行計算
		//結果push進numberstore 
		if(s2=="+" || s2=="-" || s2=="*" || s2=="/")
		{
			int number1;
			number1=numberstore.top();
			numberstore.pop();
			
			int number2;
			number2=numberstore.top();
			numberstore.pop();
			
			int cal_number;
			cal_number=calculate(s2,number2,number1);
			
			numberstore.push(cal_number);
			
			continue;
		}
		else //遇到操作數 轉換為數字之后入棧 
		{
			stream.str(s2);
			stream>>number;
			
			numberstore.push(number);
			stream.clear();
			
			continue;
		}
	}
	
	int value=0;
	
	value=numberstore.top();//棧頂元素即最終結果 
	 
	return value;
}

四.CMD命令行

以下是主函數的寫法:

#include "calculation.h"
#include "calculator.h"
#include "print.h"

#include<string>
#include<string.h>
#include<queue>
#include<stdlib.h>
#include<iostream>
using namespace std;
int bitjudge=0;

int main(int argc,char*argv[])    //不通過命令行輸入時通過Input類來輸入 
{
    queue<string> que; // type:queue<string>
    
	Scan Sc;    // Define a "Scan" object:"Sc".
    Print Put;  // Define a "Print" object "Put".
    Calculation Ca; // Define a "Calculation" object "Ca".
    
    string str=argv[argc-1];  
    
    if(strcmp(argv[1],"-a")==0) //判斷是否有輸入'-a' 
    {
    	que.push(str);
    	Put.pout(que);    // printf que.
    }
    
    while(!que.empty())que.pop();  // 清空que 
     
	que=Sc.ToStringQueue(argv[argc-1]);
    
    cout<<Ca.carryout(que)<<endl;
    return 0;
}

實現效果如下:

五.不足的地方(已做出改進)

我從我原來的代碼進行了改進,在原來的要求下,我輸出了整個式子,並且在之后進行了錯誤判斷:<1>輸入的式子左右括號匹配判斷 <2>輸入的數超過十位
但是如果使用命令行的話,在輸入'-a'的時候會進行判斷,但是沒有'-a'的時候就會跳過(判斷在調用的print.cpp內)。還有一個就是小數的處理。
這是美中不足的地方。

今天改進了一下:實現報錯功能,處理了小數的情況,對主函數進行了修改。

六.數據處理(舉兩個例子):

1.(-3+(9-((10-8)+(9-8*6/2+3)-10*10))*(8-(1+8/4)+2))=830
2.(3+(-1+2*8)*2)+(9-8*1)=34

七.總結:

經過這些天的努力和嘗試,把之前想象中異常困難的任務完成了。在我之前的代碼上依照要求進一步的開發,學習了CMD命令行和sstream的使用,總體上對這些天的經歷感到滿意。但是我也看到了自己的不足和缺點,主要是:
1.自己的知識儲備相對淺薄,仍然需要擴寬知識面,不斷學習新的知識。
2.編程能力仍然需要提升。
3.提高閱讀代碼的能力,多去思索別人的想法和做法。
希望接下來的自己再接再厲,堅持下去。

                                                                                                                  2016/4/9

更新:關於參考網址。
1.前后綴表達式 寫的超贊。
2.命令行

更新:(2016/4/11) 解決了開頭為負號的特殊情況


免責聲明!

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



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