In the personal project, we completed the arithmetic-type automatic generation of small program, in the pair project we need to do is to divide our program by function module, the different functional modules completely separate, as a separate part of the test.
After a software engineering theory class study, we know that a program design is good or bad sign is the class cohesion is high, whether the coupling degree is low, can achieve high cohesion low coupling design is what we want to see, this time, and then look at their own writing procedures, almost want to cry. At that time, the program was written using the structure of the tree, in the recursive generation of the expression of the expression in the way to complete the solution, this is not exactly the opposite of the requirements? This program in addition to the user input, output, and other generated expressions, the calculation of expressions are written in a module, completely does not meet the requirements of high cohesion. So what we need to do now is to divide the main module of the previous program into two modules, which are automatically generated expression module and solved by expression.
For the auto-generated expression module, our existing code can only be done with simple changes, and the main problem is how to solve it based on an expression. Because we started with the tree structure, in order to reuse the code, our idea is to get the user input expression string, the string into a tree structure.
Before the concrete completion of an expression string conversion. We also need to consider the problem of the multiplicity of operands, which allows the user to input fractions and integers, and the first step is to convert the operand string in the expression string to the appropriate data type. (This data type is the value type data in the personal project, the private variable is int numer,int demon, i.e. the numerator denominator)
Specific code:
voidCharstoint (Char*TMPSTR,intFlag1,intFlag2,int* Numer,int* Demon,inti) { //Judging by Flag1 as a fraction or a true fraction intJ; if(Flag1! =0) { //the integer part with fractions Chartmpstr1[Ten]; intTmpint1,tmpint2,tmpint3; for(j =0; J < Flag1; J + +) {Tmpstr1[j]=Tmpstr[j]; } Tmpstr1[j]=' /'; Tmpint1=atoi (TMPSTR1); //part of the molecule with fractions for(j = flag1+1; J < Flag2; J + +) {tmpstr1[j-Flag1-1] =Tmpstr[j]; } tmpstr1[j-Flag1-1] =' /'; Tmpint2=atoi (TMPSTR1); //the denominator portion of the band Fraction for(j = flag2+1; J < I; J + +) {tmpstr1[j-Flag2-1] =Tmpstr[j]; } tmpstr1[j-Flag2-1] =' /'; Tmpint3=atoi (TMPSTR1); * (Numer) = Tmpint1 * Tmpint3 +Tmpint2; * (Demon) =Tmpint2; } Else { Chartmpstr1[Ten]; for(j =0; J < Flag2; J + +) {Tmpstr1[j]=Tmpstr[j]; } Tmpstr1[j]=' /'; * (Numer) =atoi (TMPSTR1); for(j = Flag2 +1; J < I; J + +) {tmpstr1[j-Flag2-1] =Tmpstr[j]; } Tmpstr1[j]=' /'; * (Demon) =atoi (TMPSTR1); }}
Next, is the main function, generated by the expression string tree, the first code:
voidExperssion::generatetree (stringexpr) {Stack<Char> operstack;//operator StacksStack <experssion *> datastack;//Data StacksExpr + =' /'; CharTmpchar,c; intIDX =0; Tmpchar= expr[idx++]; Experssion*p; while(Operstack.size ()! =0|| Tmpchar! =' /') { //if it is not an operator, the operand is received, which may be a false score, a true fraction, and an integer. if(Tmpchar! =' /'&&!Isoper (Tmpchar)) { intFlag1 =0;//whether the mark is a false score of 0, not 0, is a false fraction, and this value indicates the position of "'" in the false fraction intFlag2 =0;//Is the mark of the score, 0, not 0, is the fraction, and this value represents the position of "/" in the fraction Chartmpstr[Ten];//To Save the operand string temporarily intNumer,demon;//operand numerator denominator inti =0; while(Tmpchar! =' /'&&!Isoper (Tmpchar)) {Tmpstr[i]=Tmpchar; if(Tmpchar = ='\ '')//If the character is "'"{Flag1=i; } if(Tmpchar = ='/') {Flag2=i; } Tmpchar= expr[idx++]; I++; } Tmpstr[i]=' /'; //process This staged string to get the numerator denominator if(Flag1 = =0&& Flag2 = =0)//as an integer{Demon=1; Numer=atoi (TMPSTR); } Else//as Fractions{charstoint (Tmpstr,flag1,flag2,&numer,&demon,i); } Value operation (Numer,demon); P=Newexperssion (); P->result =operation; Datastack.push (P); } Else//the operator is read { Switch(Tmpchar) { Case '(': Operstack.push ('('); Tmpchar= expr[idx++]; Break; Case ')': while(true) {C=Operstack.top (); Operstack.pop (); if(c = ='(') { Break; } P=Newexperssion (); P->oper =C; if(Datastack.size ()) {p->right =Datastack.top (); Datastack.pop (); } if(Datastack.size ()) {p->left =Datastack.top (); Datastack.pop (); } datastack.push (P); } Tmpchar= expr[idx++]; Break; default: if(operstack.size () = =0|| Tmpchar! =' /'&& Operlevel (Operstack.top ()) <Operlevel (Tmpchar)) {//into the stackOperstack.push (Tmpchar); Tmpchar= expr[idx++]; } Else {//out of the stackp =Newexperssion (); P->oper =Operstack.top (); if(Datastack.size ()) {p->right =Datastack.top (); Datastack.pop (); } if(Datastack.size ()) {p->left =Datastack.top (); Datastack.pop (); } datastack.push (P); Operstack.pop (); } Break; } }} p=Datastack.top (); Datastack.pop (); This->oper = p->Oper; This->left = p->Left ; This->right = p->Right ;}
This function mainly uses two stacks, the operand stack and the operator stack. Reading a character from the first bit of the expression, not the operator, indicates that the operand is next read and the operand supports fractions and integers. Explain with a more complicated example:
For example, the operand is 11 ' 2/3, which is a band fraction, which is now read ' 1 ', according to which the numerator of the operand is numer, the denominator demon. In the process of reading, the symbol ' and the symbol/position are represented by two flag bits. Then use Charstoint () to change the substring to the operand of value type, i.e. Operation.numer = 35,operation.demon = 3.
If the operator is being read, the operator is also divided into parentheses. The left parenthesis is in the stack, and the closing parenthesis is the parenthesis.
Finally, based on the number of expressions generated, the code is as follows:
//solved by the resulting expression treeValue Experssion::getresult () {if(Left! = NULL && Right! =NULL) {Value LResult= left->GetResult (); Value Rresult= right->GetResult (); Switch(oper) { Case '+': Result= LResult +Rresult; Break; Case '-': Result= LResult-Rresult; Break; Case '*': Result= LResult *Rresult; Break; Case '>'://">" Instead of Division signResult = LResult/Rresult; Break; } returnResult; } Else { returnResult; }}
Knot-to-project stage-modular analysis