C + + implementation calculator

Keywords: C++ data structure

1, Experimental objects

1. Master stack operation and application;

2. Understand the robustness of the algorithm;

2, Experimental contents

1. Implement lp, rp and operate functions in calculator class;

2. Improve the evaluate function of calculator class and increase the legitimacy check of input, including filtering out all illegal inputs and processing the input with mismatched left and right brackets;

3. Compile the application program to test the calculator;

4. Test with the following expression:

(56-23)/8-4# Expected result: 0.125 
34+p(u89-12.3)k/3# Expected result: 59.5667 
89.5*749+25)# Expected result: incorrect input 
(8*(7-4)# Expected result: incorrect input 
65*(72+98)(70-45)# Expected result: incorrect input 
6*# Expected result: incorrect input 
)5+3(# Expected result: incorrect input

5. Verify the calculation results.

3, Experimental steps (yoursepsorcodes)

1st. Overall design

The overall design of this experiment consists of two classes as the main framework. One is the Stack class; One is the Calculator class. Among them, Generic is used for Stack class. The overall design is as follows:

/********************************************Stack construction*********************************************/ 
template<typenameT> 
classStack{//The creation of stack template class and its data variables 
private:
	T* n;//An array of data stored in the stack; 
	Stac_Int Nlen;//Current stack length; 
	Stac_Int capacity;//The longest length of the stack; 
	Stac_Int top_;//Store the subscript of the current stack top element; 
public:
	Stack();//Constructor 
	~Stack();//Destructor 
	void push(Tx);//The push function of the stack adds elements to the top of the stack 
	T top();//The top function of the stack returns the top element of the stack 
	bool isEmpty();//Empty stack judgment 
	bool isFull();//Stack full judgment 
	Stac_Int backNlen();//Returns the length of the stack 
	void pop();//Pop function of the stack to pop up the top element of the stack 
	void to_empty();//Empty stack 
	};
	//****************************************Construction of calculator class*******************************************// 
classCalculator{ 
private:
	Stack<char> optr;//Operator stack; 
	Stack<double> opnd;//Operand stack; 
	char* at;//The head pointer of the expression string of the calculator class; 
	int n; 
	int lp(chara);//Return the priority command of the character at the head of the character stack; 
	int rp(chara);//Return the priority command of entering and reading characters; 
	double char_to_double(char*a,intn);
	//This function converts the decimal of a string to a decimal of type double (but only works for decimals with one point) 
	double operate_double(chara,doublex1,doublex2);//This function calculates four operations of two numbers 
public:
	Calculator();//Parameterless constructor; 
	Calculator(char*a,intnn);//Constructor with parameters; 
	~Calculator();//Destructor; 
	void operate();The processing of an input string of arithmetic strings (core processing function); 
	bool rr(chara)const;//Auxiliary function; 
	bool evaluate()const;//Judge whether the input string of arithmetic strings is legal; 
	double result();//Return the operation result; 
	};

The core function definitions of Stack class and Calculator class will be described in detail in the column of algorithm framework.

2nd. Algorithm framework

1. About the algorithm framework of the core function of Stack class:

The core functions are:

void push(T x);//The push function of the stack adds elements to the top of the stack 
T top();//The top function of the stack returns the top element of the stack 
void pop();//Pop function of the stack to pop up the top element of the stack 
void to_empty();//Empty stack

1> . about the push function:

//The push function of the stack adds elements to the top of the stack 
template<typename T> 
void Stack<T>::push(T x){
 if(!isFull()){ 
 	top_++; 
 	n[top_]=x; 
 	Nlen++; 
 	}
 else
 	printf("Stack full; Creation failed!\n"); 
 }

When the stack is not empty, let save the top of the foot code of the top element of the stack_ First increase by one, and then let n[top_]=x; At this time, the stack element increases, Nlen + +; When the stack is empty, the output "stack full; creation failed!".

2> . about pop function:

//Pop function of the stack to pop up the top element of the stack 
template<typename T> 
void Stack<T>::pop(){ 
	top_--; 
	Nlen--; 
}

Only top_; Nlen–; Just.

3> . about the top function:

//The top function of the stack returns the top element of the stack 
template<typename T> 
T Stack<T>::top(){ 
	returnn[top_]; 
}

Just return to the top element directly.

4> About to_empty function:

//Empty stack 
template<typename T> 
void Stack<T>::to_empty(){ 
	top_=0; 
	Nlen=0; 
}

Just make the foot code of the top element of the stack 0 and the stack length 0.

2. Framework of core functions of Calculator class:

The core functions are:

void operate();The processing of an input string of arithmetic strings (core processing function);
double char_to_double(char*a,int n);
//This function converts the decimal of a string to a decimal of type double (but only works for decimals with one point)

The following are auxiliary functions:

 int lp(char a);//Return the priority command of the character at the head of the character stack; 
 int rp(char a);//Return the priority command of entering and reading characters; 
 double operate_double(char a,double x1,double x2);//This function calculates four operations of two numbers 
 bool rr(char a)const;//Auxiliary function; 
 bool evaluate()const;//Judge whether the input string of arithmetic strings is legal; 
 double result();//Return the operation result;

See the source code for its main definitions.

1> . discussion char_ to_ Implementation algorithm of double function:

//This function converts the decimal of a string to a decimal of type double (but only works for decimals with one point) 
double Calculator::char_to_double(char*a,int n){ 
	double su=0; 
	int i; 
	int t1=-1; 
	int t2; 
	for(i=0;i<n;i++){ 
		if(a[i]=='.'){ 
			t1=i; break; 
			} 
		}
		if(t1!=-1){ 
			t2=t1-1; 
			for(i=0;i<t1;i++,t2--){ 
				su+=(a[i]-'0')*pow(10,t2); 
				}
			int j=-1; 
			for(i=t1+1;i<n;i++,j--){ 
				su+=(a[i]-'0')*pow(10,j); 
				} 
			}
			else { 
				t2=n-1; 
				for(i=0;i<n;i++,t2--) 
					su+=(a[i]-'0')*pow(10,t2); 
					}
				return su; 
		}

In this function, su's double type variable is used to store the decimal after the number of the final string type is converted to the double type. First, pass in the number of the string and judge whether it has a decimal point:

for(i=0;i<n;i++){ 
	if(a[i]=='.'){ 
		t1=i; 
		break; 
		} 
	}

If yes, t1 is used to store the subscript of the current array element. t1 is initially - 1 to judge whether the string number has a decimal point. If yes, it is divided into two parts: integer part and decimal part.

if(t1!=-1){
	t2=t1-1; 
	for(i=0;i<t1;i++,t2--){ 
		su+=(a[i]-'0')*pow(10,t2);
	}
	int j=-1; 
	for(i=t1+1;i<n;i++,j--){ 
		su+=(a[i]-'0')*pow(10,j); 
		} 
	}else { 
		t2=n-1; 
		for(i=0;i<n;i++,t2--) 
			su+=(a[i]-'0')*pow(10,t2); 
}

If not, only the integer part can be processed. Finally, su is returned.
Algorithm complexity analysis: in the worst case, if there is no decimal point, each element must be processed twice, so it is processed 2*n times. That is O(n);

2> . implementation of the operate function;

//The processing of an input string of arithmetic strings 
void Calculator::operate(){ 
	int i; 
	int k=0; 
	int t=0; 
	char a1; 
	int ii; 
	double tt1,tt2; 
	optr.push('#'); 
	for(i=0;i<n;i++){ 
		if(at[i]>='0'&&at[i]<='9'){ 
		/*This part is mainly used to intercept the digital string in the input formula string. After interception, char is needed_ to_ The double () function converts a string number to a value of type double before it can be pushed into the opnd stack*/ 
		k=i; 
		while((at[i]>='0'&&at[i]<='9')||at[i]=='.'){ 
			t++; 
			i++; 
			}
		char u[100]; 
		for(ii=0;ii<t;ii++,k++) 
			u[ii]=at[k]; 
		opnd.push(char_to_double(u,t)); 
		t=0; 
		i--; 
		}
		else if(at[i]=='#'&&optr.top()=='#') /*If '#' is read at this time, nothing is done, which also means that the overall processing is ended*/		else{/*The following is the implementation of operator priority*/ 
			while(1){ 
				if(rp(at[i])==-1) /*Filter non numeric characters*/ 
				break; 
				else if(rp(at[i])>lp(optr.top())){ optr.push(at[i]); /*If the incoming character priority is greater than the character priority at the top of the optr stack, it is pushed into the top of the stack.*/ 
					break;
	}
	else if(rp(at[i])<lp(optr.top())){ 
		a1=optr.top(); 
		optr.pop(); 
		tt1=opnd.top(); 
		opnd.pop(); 
		tt2=opnd.top(); 
		opnd.pop(); 
		opnd.push(operate_double(a1,tt2,tt1)); /*If the priority of the incoming character is lower than that of the character at the top of the optr stack, four operations are performed to process the result, and then pushed into the top of the opnd stack*/ 
		}
	else if(
		rp(at[i])==lp(optr.top())){ 
			optr.pop(); /*If the incoming character priority is equal to the optr stack top priority, the optr stack top character will pop up.*/ 
			break; } } } } }

The main algorithms in this part are the character priority algorithm and the algorithm for intercepting string numbers: as follows: the algorithm idea of determining the operator priority first:

It can be specified in the idea of operator priority as shown in the figure above.
First, the horizontal operator can be called t2 operator, and the vertical operator can be called t1 operator. The figure above shows the priority relationship between operators.
The priority relationship is derived from four algorithms:
-Multiplication and division before addition and subtraction
-First left then right
-First inside the bracket and then outside the bracket
The algorithm idea of operator operation sequence is described below:
*Set up an operator stack x1 and an operand stack x2. x1 put an end character at the bottom of the stack #.
*Scan the expression from left to right. If it is an operand, press it into x2 stack to continue scanning; If it is operator t2, compare it with x1 stack top element t1:
-If t2t1 '#', the operation ends and the result is at the top of x2 stack;
-If the priority of t2 is high, t2 enters x1 stack and continues scanning;
-If the priorities are equal, exit x1 stack top element '(' and continue scanning;
-If the priority of t2 is low, exit t1 from the x1 stack and two operands b and a from the x2 stack. After operation at1b, press the result into the x2 stack.
The implementation is as follows:

if(at[i]=='#'&&optr.top()=='#') /*If '#' is read at this time, nothing is done, which also means that the overall processing is ended*/ ; 
	else{/*The following is the implementation of operator priority*/ 
		while(1){ 
			if(rp(at[i])==-1) /*Filter non numeric characters*/ 
				break; 
			else if(rp(at[i])>lp(optr.top())){ 
				optr.push(at[i]); /*If the incoming character priority is greater than the character priority at the top of the optr stack, it is pushed into the top of the stack.*/ 
				break; 
			}
			else if(rp(at[i])<lp(optr.top())){ 
				a1=optr.top(); 
				optr.pop(); 
				tt1=opnd.top(); 
				opnd.pop(); 
				tt2=opnd.top(); 
				opnd.pop(); 
				opnd.push(operate_double(a1,tt2,tt1)); /*If the priority of the incoming character is lower than that of the character at the top of the optr stack, four operations are performed to process the result, and then pushed into the top of the opnd stack*/ 
				}
			else if(rp(at[i])==lp(optr.top())){ 
				optr.pop(); /*If the incoming character priority is equal to the optr stack top priority, the optr stack top character will pop up.*/ 
				break; 
				} 
	}

Then, the algorithm of intercepting string numbers, converting them into double numbers and pressing them into the top of opnd stack:

if(at[i]>='0'&&at[i]<='9'){ /*This part is mainly used to intercept the digital string in the input formula string. After interception, char is needed_ to_ The double () function converts a string number to a value of type double before it can be pushed into the opnd stack*/ 
	k=i; 
	while((at[i]>='0'&&at[i]<='9')||at[i]=='.'){ 
		t++; 
		i++; 
		}
	char u[100]; 
	for(ii=0;ii<t;ii++,k++) 
		u[ii]=at[k]; 
		opnd.push(char_to_double(u,t)); 
		t=0; 
		i--; 
	}

First use k to store the subscript of the character that was originally a number in the array, and then continue to traverse until a at[i] is not a number or '.'. Use t to calculate the length of the number of the string. Then save it to a new array of u[100]. Finally, call char_. to_ The double () function converts u[t] into a number of double type, which can directly perform four operations, and presses it into the top of the opnd stack. Finally, initialize t. Easy to use next time.

4, Source program

For various reasons, the source code is not convenient to display here.
You can trust me if you need the source code.

Posted by dashti on Fri, 24 Sep 2021 06:55:41 -0700