• 结组项目-四则运算3


    团队成员:苗堃(http://www.cnblogs.com/brucekun/p/5294368.html)、罗毅(http://www.cnblogs.com/ly199553/p/5294779.html) 

    PSP总结http://www.cnblogs.com/ly199553/p/5295545.html

        本次软件工程老师提出了新任务:在上一次四则运算的题目基础上增加新的功能:比如四则运算要求能求出运算结果,对于用户输入的运算结果进行比对结果是否正确,加入真分数的计算,判断是否四则运算的产生式是否重复等。但这次要求我们结组开发,而且结组的目的是:两人合作,分解任务,协同开发,仔细分析程序的过程,同时在开发过程中需要检查程序的各个流程,有问题需要共同讨论解决。

        之后我便明确了我的任务:将上一次的程序产生的计算式全部考虑成string串,我做的就是一个接口,进入我的接口传入string类型的字符串后就能出栈得到需要的答案。这样我的任务便十分明确了,我希望在这次任务中用上我学的栈和队列的知识。前期我们商量后决定使用另一个小伙伴的程序作为模版进行迭代开发,所以我花了一个晚上研究了他写的程序,大致清晰了流程后,我考虑使用容器来简化整个计算的过程。参考了网上的一些小神的代码后,我开始如下编程设计:

        使用五个容器类deque<char> coll0  deque<char> coll1; stack<char> coll2; deque<char> coll3; stack<double>coll4; 整体过程就是通过coll0来消除string式中的空格,coll1来记录产生的中缀表达式,coll2来记录运算符,因为运算符有彼此的优先级和消除括号等,再通过coll3和coll4就将转换的后缀表达式可以计算出结果。将其中设计的过程全部设计为函数,以便以后可以封装成类可以调用。主要的问题就是处理多位数时判断花了一些功夫写在另一篇博客上了,具体详http://www.cnblogs.com/ly199553/p/5292391.html,本次程序先研讨了小学2-6年级的数学水平,发现真分数计算才是重点,乘除法不应过于复杂,而且最好有面向儿童的界面。

    下面是整个代码:

      1 #include<stack>
      2 #include<iostream>
      3 #include<deque>
      4 #include<string>
      5 #include<sstream>
      6 #include<time.h>
      7 using namespace std;
      8 
      9 int  Num[100];    //将数字存入数组a
     10 string op_arrays[100];    //将运算符存入数组b
     11 string  All[100];    //合成总数组e
     12 string fu[100];      //辅助数组
     13 int true_num = 0;     //统计做对的题目数
     14 int false_num = 0;    //统计做错的题目数
     15 
     16 bool isPra(char);    //判断是否为括号
     17 int getPri(char);    //获得符号优先性
     18 void check(char c, stack<char>& coll2, deque<char>& coll3);//判断符号优先性
     19 void allocate(deque<char>& coll1, stack<char>& coll2, deque<char>& coll3);  //将中缀表达式分解为符号和运算数
     20 void calculate(deque<char>& coll3, stack<double>& coll4);  //计算后缀表达式
     21 
     22 int main()
     23 {
     24     srand((int)time(NULL));//设置随机种子,使得程序每次运行的结果都不同
     25     int subject_number;    //出题数量
     26     int random_number = 0;    //运算数字字数
     27     int operation_character = 0;
     28     int fuhao = 0;    //判定运算符
     29 
     30     int Jude_has_brackets;       //定义左、右括号的是否存在的随机变量
     31     string left;    //左括号变量
     32     string right;    //左括号变量
     33     string sign = "a";   //定义符号变量
     34     char Jude_has_mul_dev;   //定义是否需要乘除法的变量
     35 
     36     deque<char> coll0;  //消除中缀表达式的空格
     37     deque<char> coll1;  //盛放中缀表达式
     38     stack<char> coll2;  //盛放操作符
     39     deque<char> coll3;    //盛放后缀表达式
     40     stack<double>coll4;    //计算后缀表达式的辅助容器
     41 
     42     int min, Max;    //定义输入的值得范围的最值(仅能输入整数<=30)
     43     string w = " ";
     44 
     45     //写一个简易菜单
     46     cout << "欢       / ̄\_/ ̄\ "<<endl;
     47     cout << "迎      ▏     ▔▔▔▔\    " << endl;
     48     cout << "使     /\ /      ﹨" << endl;
     49     cout << "用   ∕       /   )" << endl;
     50     cout << "小   ▏        ●  ▏"<<endl;
     51     cout << "天   ▏           ▔█ " << endl;
     52     cout << "才 ◢██◣      /\__/" << endl;
     53     cout << "四  █████◣       /" << endl;
     54     cout << "则  █████████████◣ " << endl;
     55     cout << "运◢██████████████▆▄" << endl;
     56     cout << "算 █◤◢██◣◥█████████◤\" << endl;
     57     cout << "自◥◢████ ████████◤   \" << endl;
     58     cout << "助  █████ ██████◤      ﹨" << endl;
     59     cout << "系 │   │█████◤        ▏" << endl;
     60     cout << "统 │   │              ▏" << endl;
     61     cout << "   ∕   ∕    /▔▔▔\     ∕" << endl;
     62     cout << "  ∕___/﹨   ∕      \  /\" << endl;
     63     cout << "             \    \_     ﹨/  ﹨" << endl;
     64     cout << "               \___\     ﹨/▔\﹨/▔\" << endl;
     65     cout << "                           \   ∕" << endl;
     66         cout << "1.请输入产生数字的范围(最小和最大):";
     67         cin >> min >> Max;
     68         cout << "提示:若您需要做乘除法 请不要做超过30以外的乘除法" << endl;
     69         cout << endl;
     70         cout << "2.是否需要乘除法[y为需要乘除法 n为不需要乘除法] ";
     71         cin >> Jude_has_mul_dev;
     72         while (min<0)
     73         {
     74         cout << "请做正数运算:" << endl;
     75         cout << "输入最小值" << endl;
     76         cin >> min;
     77          }
     78     while (Max>30 && Jude_has_mul_dev == 'y')
     79     {
     80         cout << "请重新输入最大值:" << endl;
     81         cin >> Max;
     82     }
     83     cout << "请输入出题数量:";
     84     cin >> subject_number;
     85 
     86     int i = 0, j, k;
     87     if ('y' == Jude_has_mul_dev)
     88     {
     89         random_number = rand() % 9 + 2;    //随机生成2~10个数
     90         for (j = 0; j < subject_number; j++)    //设置题目数量
     91         {
     92             //清除数组元素
     93             memset(Num, 0, sizeof(Num));    
     94             memset(op_arrays, 0, sizeof(op_arrays));    
     95             memset(fu, 0, sizeof(fu));    
     96 
     97             random_number = rand() % 9 + 2;    //随机生成2~10个数
     98             for (i = 0; i < random_number; i++)
     99             {
    100                 stringstream ss;
    101                 operation_character = rand() % (Max - min + 1) + min;
    102                 Num[i] = operation_character;
    103                 fuhao = rand() % 4 + 1;
    104                 switch (fuhao)
    105                 {
    106                 case 1:sign = "+"; break;
    107                 case 2:sign = "-"; break;
    108                 case 3:sign = "*"; break;
    109                 case 4:sign = "/"; break;
    110                 }
    111                 //若为除法则除数不为零
    112                 while (Num[i] == 0 && i >= 1)
    113                 {
    114                     if (op_arrays[i - 1] == "/")
    115                     {
    116                         operation_character = rand() % (Max - min + 1) + min;
    117                         Num[i] = operation_character;
    118                     }
    119                 }
    120                 op_arrays[i] = sign;
    121 
    122                 fu[4 * i] = w;
    123                 ss << Num[i];
    124                 ss >> fu[4 * i + 1];
    125                 fu[4 * i + 2] = w;
    126                 if (i != (random_number - 1))   //最后一次不产生符号
    127                     fu[4 * i + 3] = op_arrays[i];
    128                 else fu[4 * i + 3] = w;
    129             }
    130             Jude_has_brackets = rand() % 2 + 1;  //随机确定有无括号
    131             switch (Jude_has_brackets)
    132             {
    133             case 1:
    134                 left = "(";
    135                 right = ")";
    136                 break;
    137             case 2:
    138                 left = w;
    139                 right = w;
    140                 break;
    141             }
    142 
    143             for (i = 0; i < random_number; i++)
    144             {
    145                 for (k = 0; k < (random_number - 1) / 2; k++)
    146                 {
    147                     fu[4 * k] = left;
    148                     if (left == "(")
    149                     {
    150                         fu[4 * k + 10] = right;
    151                     }
    152                 }
    153                 if ((fu[4 * i] == left) && (fu[4 * i + 2] == right))
    154                 {
    155                     fu[4 * i] = w;
    156                     fu[4 * i + 2] = w;
    157                 }
    158 
    159                 All[j] += fu[4 * i] + fu[4 * i + 1] + fu[4 * i + 2] + fu[4 * i + 3];
    160             }
    161             cout << j + 1 << "题. " << All[j] << "= " ;
    162             for (int i = 0; i != All[j].size(); ++i)
    163             {
    164                 //逐一加入每个字符,这里使用deque因为deque在两端删除添加的速度最快
    165                 coll0.push_back(All[j][i]);      //在尾部加入一个元素
    166             }
    167 
    168             //将coll0转换为后缀表达式coll1
    169             for (int i = 0; i != All[j].size(); ++i)
    170             {
    171                 char k = coll0.front();
    172                 coll0.pop_front();
    173                 if (k != ' ')        //消除空格
    174                     coll1.push_back(k);
    175             }
    176             //从coll中取出元素,分配元素到coll2和coll3中
    177             allocate(coll1, coll2, coll3);
    178 
    179             //计算后缀表达式
    180             calculate(coll3, coll4);
    181 
    182             double result = 0;
    183             cin >> result;
    184             if (result == coll4.top())
    185             {
    186                 cout << "正确!" << endl;
    187                 true_num++;
    188                 cout << "计算结果为:" << coll4.top() << endl;
    189             }
    190             else
    191             {
    192                 cout << "错误!" << endl;
    193                 false_num++;
    194                 cout << "计算结果为:" << coll4.top() << endl;
    195             }
    196             //将栈清空
    197             coll4.pop();
    198         }
    199         if (true_num >= false_num)
    200             cout << "恭喜你!您共做对" << true_num << "道题!" << "做错" << false_num << "道题!" << endl;
    201         else
    202             cout << "还需加油!您共做对" << true_num << "道题!" << "做错" << false_num << "道题!" << endl;
    203     }
    204     else
    205     {
    206         random_number = rand() % 9 + 2;    //随机生成2~10个数
    207         for (j = 0; j < subject_number; j++)    //设置题目数量
    208         {
    209             //清除数组元素
    210             memset(Num, 0, sizeof(Num));
    211             memset(op_arrays, 0, sizeof(op_arrays));
    212             memset(fu, 0, sizeof(fu));
    213 
    214             random_number = rand() % 9 + 2;    //随机生成2~10个数
    215             for (i = 0; i < random_number; i++)
    216             {
    217                 stringstream ss;
    218                 operation_character = rand() % (Max - min + 1) + min;
    219                 Num[i] = operation_character;
    220                 fuhao = rand() % 2 + 1;
    221                 switch (fuhao)
    222                 {
    223                 case 1:sign = "+"; break;
    224                 case 2:sign = "-"; break;
    225                 }
    226                 op_arrays[i] = sign;
    227 
    228                 fu[4 * i] = w;
    229                 ss << Num[i];
    230                 ss >> fu[4 * i + 1];
    231                 fu[4 * i + 2] = w;
    232                 if (i != (random_number - 1))   //最后一次不产生符号
    233                     fu[4 * i + 3] = op_arrays[i];
    234                 else fu[4 * i + 3] = w;
    235             }
    236             Jude_has_brackets = rand() % 2 + 1;  //随机确定有无括号
    237             switch (Jude_has_brackets)
    238             {
    239             case 1:
    240                 left = "(";
    241                 right = ")";
    242                 break;
    243             case 2:
    244                 left = w;
    245                 right = w;
    246                 break;
    247             }
    248 
    249             for (i = 0; i < random_number; i++)
    250             {
    251                 for (k = 0; k < (random_number - 1) / 2; k++)
    252                 {
    253                     fu[4 * k] = left;
    254                     if (left == "(")
    255                     {
    256                         fu[4 * k + 10] = right;
    257                     }
    258                 }
    259                 if ((fu[4 * i] == left) && (fu[4 * i + 2] == right))
    260                 {
    261                     fu[4 * i] = w;
    262                     fu[4 * i + 2] = w;
    263                 }
    264 
    265                 All[j] += fu[4 * i] + fu[4 * i + 1] + fu[4 * i + 2] + fu[4 * i + 3];
    266             }
    267             cout << j + 1 << "题. " << All[j] << "= " << endl;
    268             for (int i = 0; i != All[j].size(); ++i)
    269             {
    270                 //逐一加入每个字符,这里使用deque因为deque在两端删除添加的速度最快
    271                 coll0.push_back(All[j][i]);      //在尾部加入一个元素
    272             }
    273 
    274             //将coll0转换为后缀表达式coll1
    275             for (int i = 0; i != All[j].size(); ++i)
    276             {
    277                 char k = coll0.front();
    278                 coll0.pop_front();
    279                 if (k != ' ')        //消除空格
    280                     coll1.push_back(k);
    281             }
    282             //从coll中取出元素,分配元素到coll2和coll3中
    283             allocate(coll1, coll2, coll3);
    284 
    285             //计算后缀表达式
    286             calculate(coll3, coll4);
    287 
    288             double result = 0;
    289             cin >> result;
    290             if (result == coll4.top())
    291             {
    292                 cout << "正确!" << endl;
    293                 true_num++;
    294                 cout << "计算结果为:" << coll4.top() << endl;
    295             }
    296             else
    297             {
    298                 cout << "错误!" << endl;
    299                 false_num++;
    300                 cout << "计算结果为:" << coll4.top() << endl;
    301             }
    302             //将栈清空
    303             coll4.pop();
    304         }
    305         if (true_num >= false_num)
    306             cout << "恭喜你!您共做对" << true_num << "道题!" << "做错" << false_num << "道题!" << endl;
    307         else
    308             cout << "还需加油!您共做对" << true_num << "道题!" << "做错" << false_num << "道题!" << endl;
    309     }
    310     return 0;
    311 }
    312 
    313 
    314 //判断是否为括号
    315 bool isPra(char c)
    316 {
    317     if (c == '(' || c == ')')
    318         return true;
    319     else
    320         return false;
    321 }
    322 
    323 //获得符号的优先性
    324 int getPri(char c)
    325 {
    326     switch (c)
    327     {
    328     case '+':
    329     case '-':
    330         return 0;    //如果是加减,返回0
    331         break;
    332     case '*':
    333     case '/':
    334         return 1;    //如果是乘除,返回1
    335         break;
    336     case '(':
    337     case ')':
    338         return -1;  //注意,这里将括号设为最低优先级,因此括号不会被弹出,除非遇到右括号
    339         break;
    340     }
    341     return 2;
    342 }
    343 
    344 //判断符号的优先性
    345 void check(char c, stack<char>& coll2, deque<char>& coll3)
    346 {
    347     if (coll2.empty())
    348     {
    349         coll2.push(c);
    350         return;
    351     }
    352 
    353     if (isPra(c))
    354     {
    355         if (c == '(')
    356             coll2.push(c);
    357         else
    358         {
    359             //弹出所有元素直到遇到左括号
    360             while (coll2.top() != '(')
    361             {
    362                 char ch = coll2.top();
    363                 coll3.push_back(ch);
    364                 coll2.pop();
    365             }
    366 
    367             //当遇到左括号时,弹出但不加入coll3(后缀表达式中)--(“(”“)”都不放入后缀表达式中)
    368             coll2.pop();  //弹出左括号
    369         }
    370     }
    371     else    //如果不是括号
    372     {
    373         //取出栈顶元素,与当前符号进行优先性比较
    374         char sym = coll2.top();
    375 
    376         //比较两符号的优先性
    377         if (getPri(c) <= getPri(sym))
    378         {
    379             //如果c的优先性比栈顶符号小或等于,弹出栈顶元素
    380             coll2.pop();
    381             //并将其压入coll3(后缀表达式)中
    382             coll3.push_back(sym);
    383             //递归调用check,比较当前符号c与下一个栈顶符号的优先性
    384             check(c, coll2, coll3);
    385         }
    386         else
    387         {
    388             //如果c比栈顶符号优先级大,那将c压入coll2(操作符栈)中
    389             coll2.push(c);
    390         }
    391     }
    392 }
    393 
    394 //从coll中取出元素,分配元素到coll2和coll3中
    395 void allocate(deque<char>& coll1, stack<char>& coll2, deque<char>& coll3)
    396 {
    397     while (!coll1.empty())
    398     {
    399         char c = coll1.front();
    400         coll1.pop_front();
    401 
    402         if (c >= '0'&&c <= '9')
    403         {
    404             coll3.push_back(c);
    405             //判断是否为两位数
    406             if (!coll1.empty())
    407             {
    408                 c = coll1.front();
    409                 if (c >= '0'&&c <= '9')
    410                     coll3.push_back('@');
    411             }
    412         }
    413         else
    414         {
    415             //调用check函数,针对不同情况作出不同操作
    416             check(c, coll2, coll3);
    417         }
    418 
    419     }
    420 
    421     //如果输入结束,将coll2的元素全部弹出,加入后缀表达式中
    422     while (!coll2.empty())
    423     {
    424         char c = coll2.top();
    425         coll3.push_back(c);
    426         coll2.pop();
    427     }
    428 }
    429 
    430 
    431 //计算后缀表达式(修改)
    432 void calculate(deque<char>& coll3, stack<double>& coll4)
    433 {
    434     while (!coll3.empty())
    435     {
    436         char c = coll3.front();   //取出第一个元素
    437         double op = 0;
    438         coll3.pop_front();   //并弹出此元素
    439                              //coll3.erase(coll3.begin());
    440                              //如果是操作数,压入栈中
    441 
    442                              //若是两位数在压入辅助数组后需要进行判断
    443         if (c >= '0'&&c <= '9')
    444         {
    445             op = (c - '0');
    446             coll4.push(op);
    447             //cout<<"op="<<op<<endl;
    448         }
    449         else if (c == '@')            //如果是两位数则再读一位(若超过两位需要while扩展)
    450         {
    451             char d = coll3.front();
    452             op = coll4.top();
    453             coll4.pop();
    454             op = op * 10 + (d - '0');
    455             coll4.push(op);
    456             coll3.pop_front();
    457         }
    458         else     //如果是操作符,从栈中弹出元素进行计算
    459         {
    460             double op1 = coll4.top();
    461             coll4.pop();
    462             double op2 = coll4.top();
    463             coll4.pop();
    464             switch (c)
    465             {
    466             case '+':
    467                 coll4.push(op2 + op1);
    468                 break;
    469             case '-':
    470                 coll4.push(op2 - op1);
    471                 break;
    472             case '*':
    473                 coll4.push(op2*op1);
    474                 break;
    475             case '/':
    476                 coll4.push(op2 / op1);  //注意是op2(op)op1而不是op1(op)op2
    477                 break;
    478             }
    479         }
    480     }
    481 }

    运行截图:

    工作截图:

    这星期有些懈怠了编程激情有些下降以至于都没有加上真分数等等的情况,所以我还要反思,因为最终要成为一个系统,我决定在安卓手机上显示,所以只有开始转换成java了,希望下次我能圆满完成把。

  • 相关阅读:
    Hadoop
    Mapreduce
    ssh原理
    HDFS
    Centos
    创建jira插件
    新型的领导者是一名推动者,而不是一名发号施令者
    上善若水,虚怀若谷
    GoAhead 嵌入式web
    Eclipse基金会
  • 原文地址:https://www.cnblogs.com/ly199553/p/5294779.html
Copyright © 2020-2023  润新知