• 结对变成项目总结


    如下图,为我们做的判卷程序,左侧为出题区,中间为答题去,右侧为结果区

    首先点击自动出题按钮,自动生成50道题目,长度随机

    然后点击开始测试按钮,即进入如下界面,学生可在题目后方的输入框内答题

    全部答完后,点击确认提交按钮,自动判卷

    最终结果会显示在右边,例如每道题目的答案和对错数量的信息

    之后点击再次测试按钮,可以继续答下10道题,总共有50道题,如果全部答完后,还想继续,可以再次点击自动出题按钮,然后可以继续测试

    测试结束后,点击退出测试按钮即可退出程序。

    以下为本程序的全部代码

      1 // MFCTest4Dlg.cpp : 实现文件
      2 //
      3 
      4 #include "stdafx.h"
      5 #include "MFCTest4.h"
      6 #include "MFCTest4Dlg.h"
      7 #include "afxdialogex.h"
      8 #include "Calculator.h"
      9 #include <string>
     10 #include "Auto_Equation.h"
     11 
     12 #ifdef _DEBUG
     13 #define new DEBUG_NEW
     14 #endif
     15 
     16 //int EqNum;
     17 MyError temperror;                            //错误缓存
     18 string str_buf[10];                            //算式缓存
     19 int correct;                                //正确题数
     20 int incorrect;                                //错误题数
     21 CString answer[10];                            //结果存在这里
     22 Calculator cal("1+1");                        //创建计算器类
     23 bool last;                                    //是否是最后一组题
     24 ifstream in("equation.txt");                //打开算式所在文件
     25 
     26 
     27 // CMFCTest4Dlg 对话框
     28 
     29 
     30 
     31 CMFCTest4Dlg::CMFCTest4Dlg(CWnd* pParent /*=NULL*/)
     32     : CDialogEx(IDD_MFCTEST4_DIALOG, pParent)
     33 {
     34     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
     35 }
     36 
     37 void CMFCTest4Dlg::DoDataExchange(CDataExchange* pDX)
     38 {
     39     CDialogEx::DoDataExchange(pDX);
     40     //DDX_Control(pDX, IDC_EQUALITY, Equality);
     41     DDX_Control(pDX, IDC_EQUALITY1, Equality1);
     42     DDX_Control(pDX, IDC_EQUALITY2, Equality2);
     43     DDX_Control(pDX, IDC_EQUALITY3, Equality3);
     44     DDX_Control(pDX, IDC_EQUALITY4, Equality4);
     45     DDX_Control(pDX, IDC_EQUALITY5, Equality5);
     46     DDX_Control(pDX, IDC_EQUALITY6, Equality6);
     47     DDX_Control(pDX, IDC_EQUALITY7, Equality7);
     48     DDX_Control(pDX, IDC_EQUALITY8, Equality8);
     49     DDX_Control(pDX, IDC_EQUALITY9, Equality9);
     50     DDX_Control(pDX, IDC_EQUALITY10, Equality10);
     51     DDX_Control(pDX, IDC_A1, Answer1);
     52     DDX_Control(pDX, IDC_A2, Answer2);
     53     DDX_Control(pDX, IDC_A3, Answer3);
     54     DDX_Control(pDX, IDC_A4, Answer4);
     55     DDX_Control(pDX, IDC_A5, Answer5);
     56     DDX_Control(pDX, IDC_A6, Answer6);
     57     DDX_Control(pDX, IDC_A7, Answer7);
     58     DDX_Control(pDX, IDC_A8, Answer8);
     59     DDX_Control(pDX, IDC_A9, Answer9);
     60     DDX_Control(pDX, IDC_A10, Answer10);
     61 }
     62 
     63 BEGIN_MESSAGE_MAP(CMFCTest4Dlg, CDialogEx)
     64     ON_WM_PAINT()
     65     ON_WM_QUERYDRAGICON()
     66     ON_BN_CLICKED(IDOK, &CMFCTest4Dlg::OnBnClickedOk)
     67     ON_EN_CHANGE(IDC_EDIT1, &CMFCTest4Dlg::OnEnChangeEdit1)
     68     //ON_STN_CLICKED(IDC_STATIC_INT, &CMFCTest4Dlg::OnStnClickedStaticInt)
     69     //ON_BN_CLICKED(IDC_BUTTON1, &CMFCTest4Dlg::OnBnClickedButton1)
     70     ON_STN_CLICKED(IDC_STATIC1, &CMFCTest4Dlg::OnStnClickedStatic1)
     71     ON_STN_CLICKED(IDC_EQUALITY2, &CMFCTest4Dlg::OnStnClickedEquality2)
     72     ON_BN_CLICKED(IDOK2, &CMFCTest4Dlg::OnBnClickedOk2)
     73     ON_BN_CLICKED(IDC_BUTTON10, &CMFCTest4Dlg::OnBnClickedButton10)
     74     ON_EN_CHANGE(IDC_EDIT2, &CMFCTest4Dlg::OnEnChangeEdit2)
     75     ON_BN_CLICKED(IDC_AUTO, &CMFCTest4Dlg::OnBnClickedAuto)
     76 END_MESSAGE_MAP()
     77 
     78 
     79 // CMFCTest4Dlg 消息处理程序
     80 
     81 BOOL CMFCTest4Dlg::OnInitDialog()
     82 {
     83     CDialogEx::OnInitDialog();
     84 
     85     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
     86     //  执行此操作
     87     SetIcon(m_hIcon, TRUE);            // 设置大图标
     88     SetIcon(m_hIcon, FALSE);        // 设置小图标
     89 
     90     // TODO: 在此添加额外的初始化代码
     91     GetDlgItem(IDC_BUTTON10)->EnableWindow(false);
     92 
     93     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
     94 }
     95 
     96 // 如果向对话框添加最小化按钮,则需要下面的代码
     97 //  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
     98 //  这将由框架自动完成。
     99 
    100 void CMFCTest4Dlg::OnPaint()
    101 {
    102     if (IsIconic())
    103     {
    104         CPaintDC dc(this); // 用于绘制的设备上下文
    105 
    106         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
    107 
    108         // 使图标在工作区矩形中居中
    109         int cxIcon = GetSystemMetrics(SM_CXICON);
    110         int cyIcon = GetSystemMetrics(SM_CYICON);
    111         CRect rect;
    112         GetClientRect(&rect);
    113         int x = (rect.Width() - cxIcon + 1) / 2;
    114         int y = (rect.Height() - cyIcon + 1) / 2;
    115 
    116         // 绘制图标
    117         dc.DrawIcon(x, y, m_hIcon);
    118     }
    119     else
    120     {
    121         CDialogEx::OnPaint();
    122     }
    123 }
    124 
    125 //当用户拖动最小化窗口时系统调用此函数取得光标
    126 //显示。
    127 HCURSOR CMFCTest4Dlg::OnQueryDragIcon()
    128 {
    129     return static_cast<HCURSOR>(m_hIcon);
    130 }
    131 
    132 void CMFCTest4Dlg::OnBnClickedOk()                //这个是"开始测试"按钮
    133 {
    134     // TODO: 在此添加控件通知处理程序代码
    135     CDialogEx::OnOK();
    136 }
    137 
    138 void CMFCTest4Dlg::OnEnChangeEdit1()
    139 {
    140     // TODO:  如果该控件是 RICHEDIT 控件,它将不
    141     // 发送此通知,除非重写 CDialogEx::OnInitDialog()
    142     // 函数并调用 CRichEditCtrl().SetEventMask(),
    143     // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
    144 
    145     // TODO:  在此添加控件通知处理程序代码
    146     //SetDlgItemText(IDC_STATIC1, "shit");
    147     /*CString str;
    148     GetDlgItemText(IDC_EDIT1, str);
    149     str.Format("算式%d", ++EqNum);
    150     SetDlgItemText(IDC_STATIC1, str);*/
    151 }
    152 
    153 
    154 void CMFCTest4Dlg::OnStnClickedStaticInt()
    155 {
    156     // TODO: 在此添加控件通知处理程序代码
    157 
    158 }
    159 
    160 
    161 void CMFCTest4Dlg::OnBnClickedButton1()//这个是“确定”按钮
    162 {
    163     // TODO: 在此添加控件通知处理程序代码
    164     
    165     
    166     
    167     //EqNum++;
    168 }
    169 
    170 
    171 void CMFCTest4Dlg::OnStnClickedStatic1()
    172 {
    173     // TODO: 在此添加控件通知处理程序代码
    174 }
    175 
    176 
    177 void CMFCTest4Dlg::OnStnClickedEquality2()
    178 {
    179     // TODO: 在此添加控件通知处理程序代码
    180 }
    181 
    182 
    183 void CMFCTest4Dlg::OnBnClickedOk2()        //真正的开始按钮
    184 {
    185     // TODO: 在此添加控件通知处理程序代码
    186     int e = 0;
    187     last = false;
    188     correct = 0;
    189     incorrect = 0;
    190     SetDlgItemText(IDC_CORRECT, "0");
    191     SetDlgItemText(IDC_INCORRECT, "0");
    192     
    193     while (e < 10)
    194     {
    195         if (in >> str_buf[e])
    196         {
    197             switch (e)
    198             {
    199             case 0:
    200                 SetDlgItemText(IDC_EDIT1, "");
    201                 SetDlgItemText(IDC_A1, "第一题答案");
    202                 SetDlgItemText(IDC_EQUALITY1, str_buf[e].c_str());
    203                 break;
    204             case 1:
    205                 SetDlgItemText(IDC_EDIT2, "");
    206                 SetDlgItemText(IDC_A2, "第二题答案");
    207                 SetDlgItemText(IDC_EQUALITY2, str_buf[e].c_str());
    208                 break;
    209             case 2:
    210                 SetDlgItemText(IDC_EDIT3, "");
    211                 SetDlgItemText(IDC_A3, "第三题答案");
    212                 SetDlgItemText(IDC_EQUALITY3, str_buf[e].c_str());
    213                 break;
    214             case 3:
    215                 SetDlgItemText(IDC_EDIT4, "");
    216                 SetDlgItemText(IDC_A4, "第四题答案");
    217                 SetDlgItemText(IDC_EQUALITY4, str_buf[e].c_str());
    218                 break;
    219             case 4:
    220                 SetDlgItemText(IDC_EDIT5, "");
    221                 SetDlgItemText(IDC_A5, "第五题答案");
    222                 SetDlgItemText(IDC_EQUALITY5, str_buf[e].c_str());
    223                 break;
    224             case 5:
    225                 SetDlgItemText(IDC_EDIT6, "");
    226                 SetDlgItemText(IDC_A6, "第六题答案");
    227                 SetDlgItemText(IDC_EQUALITY6, str_buf[e].c_str());
    228                 break;
    229             case 6:
    230                 SetDlgItemText(IDC_EDIT7, "");
    231                 SetDlgItemText(IDC_A7, "第七题答案");
    232                 SetDlgItemText(IDC_EQUALITY7, str_buf[e].c_str());
    233                 break;
    234             case 7:
    235                 SetDlgItemText(IDC_EDIT8, "");
    236                 SetDlgItemText(IDC_A8, "第八题答案");
    237                 SetDlgItemText(IDC_EQUALITY8, str_buf[e].c_str());
    238                 break;
    239             case 8:
    240                 SetDlgItemText(IDC_EDIT9, "");
    241                 SetDlgItemText(IDC_A9, "第九题答案");
    242                 SetDlgItemText(IDC_EQUALITY9, str_buf[e].c_str());
    243                 break;
    244             case 9:
    245                 SetDlgItemText(IDC_EDIT10, "");
    246                 SetDlgItemText(IDC_A10, "第十题答案");
    247                 SetDlgItemText(IDC_EQUALITY10, str_buf[e].c_str());
    248                 break;
    249             }
    250         }
    251         else
    252         {
    253             last = true;
    254         }
    255         e++;
    256     }
    257     //按完开始之后就不能再次按下
    258     SetDlgItemText(IDOK2, "再次测试");
    259     GetDlgItem(IDOK2)->EnableWindow(false);
    260     GetDlgItem(IDC_BUTTON10)->EnableWindow(true);
    261     if (last)
    262     {
    263         MessageBox("没有更多的题了!测试结束!", "提示", MB_ICONINFORMATION);
    264         GetDlgItem(IDC_BUTTON10)->EnableWindow(false);
    265         in.close();
    266     }
    267 }
    268 
    269 
    270 void CMFCTest4Dlg::OnBnClickedButton10()//确认提交按钮
    271 {
    272     int a = 0;
    273     //循环存用户答案
    274     while (a < 10)
    275     {
    276         cal.recalculator(str_buf[a]);                    //重启计算器,并传入算式参数
    277         temperror = cal.run();
    278         switch (a)
    279         {
    280         case 0:
    281             GetDlgItemText(IDC_EDIT1, answer[a]);
    282             SetDlgItemText(IDC_A1, cal.getMyResult().c_str());
    283             break;
    284         case 1:
    285             GetDlgItemText(IDC_EDIT2, answer[a]);
    286             SetDlgItemText(IDC_A2, cal.getMyResult().c_str());
    287             break;
    288         case 2:
    289             GetDlgItemText(IDC_EDIT3, answer[a]);
    290             SetDlgItemText(IDC_A3, cal.getMyResult().c_str());
    291             break;
    292         case 3:
    293             GetDlgItemText(IDC_EDIT4, answer[a]);
    294             SetDlgItemText(IDC_A4, cal.getMyResult().c_str());
    295             break;
    296         case 4:
    297             GetDlgItemText(IDC_EDIT5, answer[a]);
    298             SetDlgItemText(IDC_A5, cal.getMyResult().c_str());
    299             break;
    300         case 5:
    301             GetDlgItemText(IDC_EDIT6, answer[a]);
    302             SetDlgItemText(IDC_A6, cal.getMyResult().c_str());
    303             break;
    304         case 6:
    305             GetDlgItemText(IDC_EDIT7, answer[a]);
    306             SetDlgItemText(IDC_A7, cal.getMyResult().c_str());
    307             break;
    308         case 7:
    309             GetDlgItemText(IDC_EDIT8, answer[a]);
    310             SetDlgItemText(IDC_A8, cal.getMyResult().c_str());
    311             break;
    312         case 8:
    313             GetDlgItemText(IDC_EDIT9, answer[a]);
    314             SetDlgItemText(IDC_A9, cal.getMyResult().c_str());
    315             break;
    316         case 9:
    317             GetDlgItemText(IDC_EDIT10, answer[a]);
    318             SetDlgItemText(IDC_A10,cal.getMyResult().c_str());
    319             break;
    320         }
    321         if (answer[a].GetString() == cal.getMyResult())
    322         {
    323             correct++;
    324         }
    325         else
    326         {
    327             incorrect++;
    328         }
    329         a++;
    330     }
    331     if (temperror != ERROR_NO)                        //显示错误
    332     {
    333         MessageBox(printError(temperror).c_str(), "ERROR", MB_ICONHAND);
    334     }
    335     char buf[2][3];
    336     sprintf(buf[0], "%d", correct);
    337     sprintf(buf[1], "%d", incorrect);
    338     SetDlgItemText(IDC_CORRECT, buf[0]);
    339     SetDlgItemText(IDC_INCORRECT, buf[1]);
    340     // TODO: 在此添加控件通知处理程序代码
    341     GetDlgItem(IDOK2)->EnableWindow(true);
    342     GetDlgItem(IDC_BUTTON10)->EnableWindow(false);
    343 }
    344 
    345 
    346 void CMFCTest4Dlg::OnEnChangeEdit2()
    347 {
    348     // TODO:  如果该控件是 RICHEDIT 控件,它将不
    349     // 发送此通知,除非重写 CDialogEx::OnInitDialog()
    350     // 函数并调用 CRichEditCtrl().SetEventMask(),
    351     // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
    352 
    353     // TODO:  在此添加控件通知处理程序代码
    354 
    355 }
    356 
    357 
    358 void CMFCTest4Dlg::OnBnClickedAuto()
    359 {
    360     // TODO: 在此添加控件通知处理程序代码
    361     srand((int)time(0));
    362     string equation;
    363     char temp[100];
    364     ofstream outf("equation.txt");
    365     int i = 50;
    366     //cout << "输入生成算式的数量:";
    367     //cin >> i;
    368     while (i--) {
    369         equation.clear();
    370         if (i % 2) {                                            //分数运算 
    371             char lastop = '+';                                //上一个运算符 
    372             int num = random(5) + 4;                            //算式包含的操作数个数-1 
    373             sprintf(temp, "%d", random(20) + 1);                 //第一个操作数 
    374             equation.append(temp);
    375             while (num--) {
    376                 int b;
    377                 if (lastop == '/')                            //防止连续除法的出现 
    378                     b = random(2);
    379                 else
    380                     b = random(12);
    381                 switch (b) {
    382                 case 0:
    383                 case 4:
    384                 case 8:
    385                     lastop = temp[0] = '+';
    386                     break;
    387                 case 1:
    388                 case 5:
    389                 case 9:
    390                     lastop = temp[0] = '-';
    391                     break;
    392                 case 2:
    393                 case 6:
    394                 case 10:
    395                     lastop = temp[0] = '*';
    396                     break;
    397                 case 3:
    398                 case 7:
    399                 case 11:
    400                     lastop = temp[0] = '/';
    401                     break;
    402                 }
    403                 temp[1] = 0;
    404                 equation.append(temp);
    405                 sprintf(temp, "%d", random(20) + 1);
    406                 equation.append(temp);
    407             }
    408             int k, a = 0;
    409             for (int j = 0; j<equation.size(); j++) {                    //添加括号 
    410                 if ((equation[j] == '+' || equation[j] == '-') && a == 0) {
    411                     a++;
    412                 }
    413                 else if ((equation[j] == '+' || equation[j] == '-') && a == 1) {
    414                     k = j - 1;                                            //添加左括号 
    415                     while (!isoperator(equation[k - 1]) && k != 0) k--;
    416                     if (equation[k - 1] == '/') {
    417                         k--;
    418                         while (!isoperator(equation[k - 1]) && k != 0) k--;
    419                     }
    420                     equation.insert(k, "(");
    421 
    422                     k = j + 2;                                            //添加右括号 
    423                     while (!isoperator(equation[k + 1]) && k != equation.size() - 1) k++;
    424                     equation.insert(k + 1, ")");
    425 
    426                     break;
    427                 }
    428             }
    429             //cout<<equation<<endl;
    430         }
    431         else {                                                        //小数运算 
    432             char lastop = '+';                                //上一个运算符 
    433             int num = random(5) + 4;                            //算式包含的操作数个数-1 
    434             int temp1 = random(200) + 1;
    435             sprintf(temp, "%g", temp1 / 10.0);                 //第一个操作数 
    436             equation.append(temp);
    437             while (num--) {
    438                 int b;
    439                 if (lastop == '/')                            //防止连续除法的出现 
    440                     b = random(2);
    441                 else
    442                     b = random(12);
    443                 switch (b) {
    444                 case 0:
    445                 case 4:
    446                 case 8:
    447                     lastop = temp[0] = '+';
    448                     break;
    449                 case 1:
    450                 case 5:
    451                 case 9:
    452                     lastop = temp[0] = '-';
    453                     break;
    454                 case 2:
    455                 case 6:
    456                 case 10:
    457                     lastop = temp[0] = '*';
    458                     break;
    459                 case 3:
    460                 case 7:
    461                 case 11:
    462                     lastop = temp[0] = '/';
    463                     break;
    464                 }
    465                 temp[1] = 0;
    466                 equation.append(temp);
    467                 int temp2 = random(200) + 1;
    468                 if (equation[equation.size() - 1] == '/' && (temp1%temp2) != 0) {
    469                     temp2 = temp1 / 5 + 1;
    470                     while (temp1%temp2) {
    471                         temp2++;
    472                     }
    473                 }
    474                 temp1 = temp2;
    475                 sprintf(temp, "%g", temp2 / 10.0);
    476                 equation.append(temp);
    477             }
    478             //cout<<equation<<endl;
    479         }
    480         outf << equation << endl;
    481     }
    482     //cout << "生成算式成功" << endl;
    483     MessageBox("生成50道算式成功", "提示", MB_ICONINFORMATION);
    484     GetDlgItem(IDOK2)->EnableWindow(true);
    485     in.close();
    486     in.open("equation.txt");
    487     outf.close();
    488 }
    MFC code
      1 #pragma once
      2 #include <iostream>
      3 using namespace std;
      4 #include <string.h>
      5 #include <stack>
      6 #include <sstream>
      7 #include <fstream>
      8 #include <stdlib.h>
      9 #include <stdio.h>
     10 #include <math.h>
     11 
     12 enum MyError { ERROR_NO = 0, ERROR_SET = 1, ERROR_OPERATOR = 2, ERROR_ZERO = 4, ERROR_STRING = 8, ERROR_RANGE = 16 };
     13 
     14 string printError(MyError me) {
     15     if (me == ERROR_NO) {
     16         return "没有错误";
     17     }
     18     else if (me == ERROR_SET) {
     19         return "设置参数非法";
     20     }
     21     else if (me == ERROR_OPERATOR) {
     22         return "操作符非法";
     23     }
     24     else if (me == ERROR_ZERO) {
     25         return "除0错误";
     26     }
     27     else if (me == ERROR_STRING) {
     28         return "算式非法";
     29     }
     30     else if (me == ERROR_RANGE) {
     31         return "计算结果超出范围";
     32     }
     33     else {
     34         return "未定义的错误类型";
     35     }
     36     //cout<< "    错误代码:" << me << endl << endl;
     37 }
     38 
     39 class unit                        //后缀表达式用,单元类 
     40 {
     41 public:
     42     char op;
     43     double num;
     44     int kind;
     45     unit() {
     46         kind = 0;
     47     }
     48     void set(char c) {
     49         op = c;
     50         kind = 1;
     51     }
     52     void set(double d) {
     53         num = d;
     54         kind = 2;
     55     }
     56 };
     57 
     58 class fenshu                        //分数类 
     59 {
     60 public:
     61     int fz;
     62     int fm;
     63     fenshu(int a, int b) {
     64         fz = a; fm = b;
     65         yuefen();
     66     }
     67     void yuefen() {
     68         if (fz == 0)
     69             return;
     70         int t;
     71         int a = fz;
     72         int b = fm;
     73         if (a < b) {
     74             t = a;
     75             a = b;
     76             b = t;
     77         }
     78         while (t = a % b) {
     79             a = b;
     80             b = t;
     81         }
     82         if (b != 1) {
     83             fz /= b;
     84             fm /= b;
     85         }
     86         if (fm<0) {
     87             fz = -fz;
     88             fm = -fm;
     89         }
     90     }
     91     void print() {
     92         cout << fz << "/" << fm;
     93     }
     94     string getfenshu() {
     95         char s[20];
     96         if (fm == 1) {
     97             sprintf(s, "%d", fz);
     98         }
     99         else {
    100             sprintf(s, "%d/%d", fz, fm);
    101         }
    102         string ss = s;
    103         return ss;
    104     }
    105     fenshu operator +(fenshu &fs) {
    106         fenshu f(fz*fs.fm + fs.fz*fm, fm*fs.fm);
    107         f.yuefen();
    108         return f;
    109     }
    110     fenshu operator -(fenshu &fs) {
    111         fenshu f(fz*fs.fm - fs.fz*fm, fm*fs.fm);
    112         f.yuefen();
    113         return f;
    114     }
    115     fenshu operator *(fenshu &fs) {
    116         fenshu f(fz*fs.fz, fs.fm*fm);
    117         f.yuefen();
    118         return f;
    119     }
    120     fenshu operator /(fenshu &fs) {
    121         if (fs.fz == 0) {
    122             fenshu f1(0, 1);
    123             return f1;
    124         }
    125         fenshu f(fz*fs.fm, fm*fs.fz);
    126         f.yuefen();
    127         return f;
    128     }
    129     void operator =(fenshu &fs) {
    130         fz = fs.fz;
    131         fm = fs.fm;
    132     }
    133     bool operator ==(fenshu &fs) {
    134         return fz == fs.fz&&fm == fs.fm;
    135     }
    136 };
    137 
    138 class Calculator                    //核心计算器类 
    139 {
    140 public:
    141     //辅助计算参数 
    142     double result;                    //计算结果 
    143     fenshu fresult;                    //分数计算结果 
    144     MyError Error;                    //计算过程中是否有错误 
    145     string str;                        //存放中缀表达式 
    146 
    147     Calculator(string s) :fresult(1, 1) {            //计算器初始化 
    148         u = new unit();
    149         str = s;
    150         accuracy = -1;
    151         maxunit = 80;
    152         daterange = 1000;
    153         clear();
    154     }
    155 
    156     MyError run() {                        //计算表达式的值,存入result
    157         MyError temperror = zzh(str);
    158         if (temperror != ERROR_NO) {
    159             Error = temperror;
    160             result = -11111;
    161             return Error;
    162         }
    163         int i;
    164         bool b = true;
    165         for (i = 0; i<str.size(); i++) {    //没有小数点,就计算分数结果 
    166             if (str[i] == '.') {
    167                 b = false;
    168                 break;
    169             }
    170 
    171         }
    172 
    173         if (b) {
    174             temperror = getFResult();
    175             if (temperror != ERROR_NO) {
    176                 fenshu f(-1, -1);
    177                 fresult = f;
    178                 Error = temperror;
    179                 return Error;
    180             }
    181             else if (abs(fresult.fz)>daterange || abs(fresult.fm)>daterange) {
    182                 Error = ERROR_RANGE;
    183                 return Error;
    184             }
    185         }
    186         else {
    187             temperror = getResult();
    188             if (temperror != ERROR_NO) {
    189                 Error = temperror;
    190                 result = -11111;
    191                 return Error;
    192             }
    193             else if (abs(result)>daterange) {
    194                 Error = ERROR_RANGE;
    195                 return Error;
    196             }
    197         }
    198         return ERROR_NO;
    199     }
    200 
    201     void clear() {                    //清空计算器一切辅助计算参数 
    202         num = 0;
    203         Error = ERROR_NO;
    204         result = 0;
    205         fenshu f(1, 1);
    206         fresult = f;
    207         str = "";
    208         delete u;
    209         u = new unit[maxunit];
    210     }
    211 
    212     void recalculator(string s) {    //重启计算器对象 
    213         clear();
    214         str = s;
    215     }
    216 
    217     string getMyResult() {                                //获得计算结果,小数结果或者分数结果 
    218         int i = 0;
    219         char s[20];
    220         string ss;
    221         for (; i<str.size(); i++) {
    222             if (str[i] == '.') {
    223                 if (accuracy != -1)                            //判断精度并输出 
    224                     sprintf(s, "%.*lf", accuracy, result);
    225                 else
    226                     sprintf(s, "%g", result);
    227                 ss = s;
    228                 return ss;
    229             }
    230         }
    231         ss = fresult.getfenshu();
    232         return ss;
    233     }
    234 
    235     MyError setDateRange(int type) {                //设置数据范围 
    236         if (0<type) {
    237             daterange = type;
    238             return ERROR_NO;
    239         }
    240         else
    241             Error = ERROR_SET;
    242         return ERROR_SET;
    243     }
    244 
    245     MyError setMaxUnit(int num) {                //设置最大识别数量 
    246         if (0<num&&num <= 80) {
    247             maxunit = num;
    248             u = new unit[maxunit];             //清空后缀表达式 
    249             this->num = 0;
    250             return ERROR_NO;
    251         }
    252         else
    253             Error = ERROR_SET;
    254         return ERROR_SET;
    255     }
    256 
    257     MyError setAccuracy(int a) {                    //设置精度 
    258         if (a >= -1 && a <= 6) {
    259             accuracy = a;
    260             return ERROR_NO;
    261         }
    262         else
    263             Error = ERROR_SET;
    264         return ERROR_SET;
    265     }
    266 
    267 private:
    268     //非辅助计算参数,设置后,除非重复设置,否则不会被clear之类的清除 
    269     int daterange;                    //算式参数中数据的范围 
    270     int maxunit;                    //算式参数最多能识别的字符数量 
    271     int accuracy;                    //小数精确位数,-1为不精确,即去掉所有末尾的0,其他数字即小数点后保留的位数 
    272 
    273                                     //辅助计算参数 
    274     unit *u;                        //存储后缀表达式 
    275     int num;                        //后缀表达式unit数量 
    276 
    277     MyError zzh(string s) {                        //中缀表达式转后缀表达式
    278         if (s.size()>maxunit) {
    279             return ERROR_STRING;                //error,传入的算式长度超过设置的最大识别数量
    280         }
    281         char c;
    282         char *temp1 = new char[maxunit];
    283         double temp;
    284         string stemp;
    285         stack<char> st;
    286         while (!s.empty()) {                    //如果字符串不为空则继续循环 
    287             c = s[0];
    288             if (isoperator(c)) {                //是操作符 
    289                 s.erase(0, 1);                //从string中删除操作符  
    290                 if (pushintostack(c, &st) == ERROR_OPERATOR)
    291                     return ERROR_OPERATOR;
    292             }
    293             else if (isnum(c)) {                            //是数字 
    294                 stringstream sst(s);
    295                 sst >> temp;
    296                 sprintf(temp1, "%g", temp);
    297                 stemp = temp1;
    298                 s.erase(0, stemp.size());    //从string中删除数字
    299                 sst.clear();
    300                 u[num++].set(temp);            //存储数字到栈中 
    301             }
    302             else {
    303                 return ERROR_STRING;
    304             }
    305         }
    306         if (pushintostack('#', &st) == ERROR_OPERATOR)
    307             return ERROR_OPERATOR;
    308         return ERROR_NO;
    309     }
    310 
    311     bool isoperator(char c) {                //判断是否是操作符 
    312         if (c == '+')
    313             return true;
    314         if (c == '-')
    315             return true;
    316         if (c == '*')
    317             return true;
    318         if (c == '/')
    319             return true;
    320         if (c == '(')
    321             return true;
    322         if (c == ')')
    323             return true;
    324         return false;
    325     }
    326 
    327     bool isnum(char c) {
    328         if (c >= '0'&&c <= '9')
    329             return true;
    330         return false;
    331     }
    332 
    333     int youxian(char c1, char c2) {            //判断两操作符优先级 
    334         if (c2 == '#')        //结束符 
    335             return 0;
    336         if (c2 == '(')
    337             return 1;
    338         if (c2 == ')')
    339             if (c1 == '(')
    340                 return 2;
    341             else
    342                 return 0;
    343         if (c1 == '(')
    344             if (c2 == '+' || c2 == '-' || c2 == '*' || c2 == '/')
    345                 return 1;
    346         if (c1 == '*' || c1 == '/')
    347             return 0;
    348         if (c1 == '+' || c1 == '-')
    349             if (c2 == '*' || c2 == '/')
    350                 return 1;
    351             else if (c2 == '+' || c2 == '-')
    352                 return 0;
    353         return -1;                            //非法运算符 
    354     }
    355 
    356     MyError pushintostack(char c, stack<char> *st) {        //将操作符执行一系列入栈判断操作 
    357         char a;
    358         int y = 0;
    359         while (!st->empty()) {
    360             a = st->top();
    361             y = youxian(a, c);
    362             if (y == 0) {                //后来的操作符优先级小 
    363                 st->pop();
    364                 u[num++].set(a);
    365             }
    366             else if (y == 1) {            //后来的操作符优先级大 
    367                 break;
    368             }
    369             else if (y == 2) {            //俩操作符是'('和')'
    370                 st->pop();
    371                 return ERROR_NO;
    372             }
    373             else
    374                 return ERROR_OPERATOR;
    375         }
    376         st->push(c);
    377         return ERROR_NO;
    378     }
    379 
    380     void test() {                                    //输出后缀表达式,测试用(暂留) 
    381         int i;
    382         cout << num << endl;
    383         for (i = 0; i<num; i++) {
    384             if (u[i].kind == 1)
    385                 cout << u[i].op << " ";
    386             else if (u[i].kind == 2)
    387                 cout << u[i].num << " ";
    388         }
    389     }
    390 
    391     MyError getResult() {                        //由run函数调用,获取小数结果,存入result中 
    392         int i;
    393         char op;
    394         double num1, num2;
    395         stack<double> st;
    396         for (i = 0; i<num; i++) {                    //处理后缀表达式 
    397             if (u[i].kind == 2) {                //如果是数字则入栈 
    398                 st.push(u[i].num);
    399             }
    400             else if (u[i].kind == 1) {            //如果是操作符,则出栈两个数字 
    401                 op = u[i].op;
    402                 if (st.empty())
    403                     return ERROR_STRING;    //算式非法
    404                 num2 = st.top();
    405                 st.pop();
    406                 if (st.empty())
    407                     return ERROR_STRING;    //算式非法
    408                 num1 = st.top();
    409                 st.pop();
    410                 switch (op) {
    411                 case '+':
    412                     st.push(num1 + num2);
    413                     break;
    414                 case '-':
    415                     st.push(num1 - num2);
    416                     break;
    417                 case '*':
    418                     st.push(num1*num2);
    419                     break;
    420                 case '/':
    421                     if (num2 == 0)
    422                         return ERROR_ZERO;    //除0错误
    423                     st.push(num1 / num2);
    424                     break;
    425                 }
    426             }
    427             else
    428                 return ERROR_STRING;        //算式非法
    429         }
    430         result = st.top();
    431         return ERROR_NO;
    432     }
    433 
    434     MyError getFResult() {                        //由run函数调用,获取分数结果,存入fresult中 
    435         int i;
    436         char op;
    437         fenshu f1(1, 1), f2(1, 1);
    438         stack<fenshu> st;
    439         for (i = 0; i<num; i++) {
    440             if (u[i].kind == 2) {                //如果是数字则入栈 
    441                 st.push(fenshu(u[i].num, 1));
    442             }
    443             else if (u[i].kind == 1) {            //如果是操作符,则出栈两个数字 
    444                 op = u[i].op;
    445                 if (st.empty())
    446                     return ERROR_STRING;    //算式非法
    447                 f2 = st.top();
    448                 st.pop();
    449                 if (st.empty())
    450                     return ERROR_STRING;    //算式非法
    451                 f1 = st.top();
    452                 st.pop();
    453                 switch (op) {
    454                 case '+':
    455                     st.push(f1 + f2);
    456                     break;
    457                 case '-':
    458                     st.push(f1 - f2);
    459                     break;
    460                 case '*':
    461                     st.push(f1*f2);
    462                     break;
    463                 case '/':
    464                     if (f2.fz == 0)
    465                         return ERROR_ZERO;    //除0错误 
    466                     st.push(f1 / f2);
    467                     break;
    468                 }
    469             }
    470             else
    471                 return ERROR_STRING;        //算式非法
    472         }
    473         fresult = st.top();
    474         return ERROR_NO;
    475     }
    476 
    477 };
    Calculator code
     1 #include<time.h>
     2 #include<stdlib.h>
     3 /* run this program using the console pauser or add your own getch, system("pause") or input loop */
     4 #define random(x) (rand()%x)
     5 
     6 bool isoperator(char c) {
     7     if (c == '+' || c == '-' || c == '*' || c == '/')
     8         return true;
     9     return false;
    10 }
    auto_equation.h code
  • 相关阅读:
    VB.NET中lambda的写法
    C#中DllImport用法和路径问题
    SQL*Loader 和 Data Pump
    批处理-函数定义及应用01
    Office 2010 KMS激活原理和案例分享
    Hyper-V架构与VMware ESXi的差异
    Tomcat免安装配置2
    Tomcat免安装配置
    域名解析过程
    内部类访问的局部变量必须加final
  • 原文地址:https://www.cnblogs.com/chengyu404/p/5371290.html
Copyright © 2020-2023  润新知