在上次的基础上,这次我们要完成两个功能——约分和逐条读入算式。
约分:
约分就是将分子分母同时除以它们的最大公约数。所以我们需要先得到它们的最大公约数。
这里我们可以使用辗转相除发来得到它,辗转相除法是一种递归过程,它的函数实现如下:
1 int Fraction::get_gcd(int a, int b)//求最大公约数,a为分子,b为分母 2 { 3 if (b == 0) 4 return a; 5 return get_gcd(b, a%b); 6 }
这个函数的使用方法很简单,只需要输入两个参数便可以得到最大公约数。
约分函数的函数实现如下:
1 void Fraction::reduction() { 2 int gcd = get_gcd(numerator, denominator); 3 numerator = numerator / gcd; 4 denominator = denominator / gcd; 5 if (denominator < 0) 6 { 7 numerator = -numerator; 8 denominator = -denominator; 9 } 10 }
在除完最大公约数后,为了方便打印分数,我们把整个分数的正负号在分子中表示,分母是恒正的。但因为计算中间可能会有分母为负的情况,所以我们在约分中进行判断,如果分母小于0,则分子分母都取反。
逐条读入算式:
引入
1 #include <fstream>
这是输入文件流的头文件,文件流fstream和输入输出流iostream的使用方法类似。
Calculator类是负责输入、转换、输出的类。在Calculator类中添加两个成员变量:
1 ifstream ifs, ifs_line
ifs流是用来读入计算器的文件流,即一个字符一个字符读入,就像用手输入一样。
ifs_line流是用来读入文件里的算式并打印在控制台的文件流。
建立一个txt文件Expressions.txt,里面写下10个算式。
Calculator类主成员函数Run()实现如下:
1 void Calculator::Run() { 2 ifs = ifstream("Expressions.txt"); 3 ifs_line = ifstream("Expressions.txt"); 4 5 Fraction correct_answer, user_answer; // 正确答案和用户答案 6 int correct_num = 0, wrong_num = 0; 7 8 // 输入中缀表达式 9 cout << "请计算下列算式:" << endl; 10 while (!ifs_line.eof()) 11 { 12 // 每个算式计算之前清空成员变量 13 il = 0; 14 pl = 0; 15 while (!is.empty()) 16 is.pop(); 17 while (!ps.empty()) 18 ps.pop(); 19 for (int i = 0; i < 100; i++) 20 { 21 InfixExp[i] = PostfixExp[i] = Expression(); 22 } 23 // 获得中缀表达式及中缀表达式转后缀表达式 24 if (GetInfixExp() && Transform()) { 25 for (int i = 0; i < pl; i++) { 26 if (PostfixExp[i].Operator == NULL) 27 ps.push(PostfixExp[i].Operand); 28 else { 29 if (!Compute(PostfixExp[i].Operator)) 30 return; 31 } 32 } 33 correct_answer = ps.top(); 34 } 35 else 36 { 37 cout << "算式格式错误" << endl; 38 return; 39 } 40 41 cin >> user_answer; 42 user_answer.reduction(), correct_answer.reduction(); 43 if (user_answer == correct_answer) 44 { 45 correct_num++; 46 cout << "计算正确" << endl; 47 48 } 49 else 50 { 51 wrong_num++; 52 cout << "计算错误,正确答案是" << correct_answer << endl; 53 54 } 55 } 56 cout << "所有算式计算完毕" << endl; 57 cout << "共" << correct_num + wrong_num << "题,"; 58 cout << "正确" << correct_num << "道,错误" << wrong_num << "道" << endl; 59 }
运行结果: