如下图,为我们做的判卷程序,左侧为出题区,中间为答题去,右侧为结果区
首先点击自动出题按钮,自动生成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 }
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 };
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 }