四则运算第三版
Posted 来自代码的诅咒
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四则运算第三版相关的知识,希望对你有一定的参考价值。
相对于第二版又提出了新的要求
1.学生写的程序必须能判定用户的输入答案是否正确
2.程序必须能处理四种运算的混合算式
要求两人合作分析,单独编程,单独撰写博客
设计思路:
核心问题在于如何对随即产生的四则运算进行求值 通过查阅资料和复习数据结构 以及算符优先的概念 发现可以采用中缀表达式转化为后缀表达式
并采用栈结构进行求值
1 #include<iostream> 2 #include<ctime> 3 #include<string> 4 #include<sstream> 5 #include "SqStack.h" 6 using namespace std; 7 8 char ops[7] = { \'+\', \'-\', \'*\', \'/\', \'(\', \')\', \'=\' }; 9 char cmp[7][7] = { { \'>\', \'>\', \'<\', \'<\', \'<\', \'>\', \'>\' }, 10 { \'>\', \'>\', \'<\', \'<\', \'<\', \'>\', \'>\' }, 11 { \'>\', \'>\', \'>\', \'>\', \'<\', \'>\', \'>\' }, 12 { \'>\', \'>\', \'>\', \'>\', \'<\', \'>\', \'>\' }, 13 { \'<\', \'<\', \'<\', \'<\', \'<\', \'=\', \' \' }, 14 { \'>\', \'>\', \'>\', \'>\', \' \', \'>\', \'>\' }, 15 { \'<\', \'<\', \'<\', \'<\', \'<\', \' \', \'=\' } }; 16 17 bool IsOperator(char ch) 18 { 19 for (int i = 0; i < 7; i++) 20 if (ch == ops[i]) 21 return true; 22 return false; 23 } 24 char Compare(char ch1, char ch2) 25 { 26 int i, m, n; 27 char priority; 28 for (i = 0; i < 7; i++) { //找到相比较的两个运算符在比较矩阵里的相对位置 29 if (ch1 == ops[i]) 30 m = i; 31 if (ch2 == ops[i]) 32 n = i; 33 } 34 priority = cmp[m][n]; 35 return priority; 36 } 37 38 bool Compute(double x, char op, double y, double &z) 39 { 40 switch (op) { 41 case \'+\': z = x + y; 42 break; 43 case \'-\': z = x - y; 44 break; 45 case \'*\': z = x * y; 46 break; 47 case \'/\': if (fabs(y) > 1e-7) { 48 z = x / y; 49 break; 50 } 51 else 52 cout << "除数为0,出错!" << endl; 53 return false; 54 } 55 return true; 56 } 57 58 bool ExpEvaluation(char *str, double &result) 59 { 60 double a, b, v; 61 char ch, op; 62 int temp, i = 0; 63 SqStack <char> optr(20); //创建运算符栈optr 64 SqStack <double> opnd(20); //创建运算数栈opnd 65 optr.Push(\'=\'); 66 ch = str[i++]; 67 while (ch != \'=\' || optr.Top() != \'=\') { 68 while (ch == \' \') //跳过空格 69 ch = str[i++]; 70 if (IsOperator(ch)) { //是7种运算符之一 71 switch (Compare(optr.Top(), ch)) { 72 case \'<\': //栈顶运算符优先级低 73 optr.Push(ch); 74 ch = str[i++]; 75 break; 76 case \'=\': //脱括号并接收下一字符 77 optr.Pop(); 78 ch = str[i++]; 79 break; 80 case \'>\': //栈顶运算符优先级高,退栈并将运算结果入栈 81 op = optr.Top(); 82 optr.Pop(); 83 b = opnd.Top(); 84 opnd.Pop(); 85 a = opnd.Top(); 86 opnd.Pop(); 87 if (Compute(a, op, b, v)) { //计算v = a <op> b 88 opnd.Push(v); 89 break; 90 } 91 else { 92 result = 0; 93 return false; 94 } 95 } 96 } 97 else { //是数字 98 temp = ch - \'0\'; //将字符转换为十进制数 99 ch = str[i++]; 100 while (!IsOperator(ch) && ch != \' \') { 101 temp = temp * 10 + ch - \'0\'; //将逐个读入运算数的各位转化为十进制数 102 ch = str[i++]; 103 } 104 opnd.Push(temp); //数值入栈 105 } 106 } 107 result = opnd.Top(); 108 return true; 109 } 110 111 112 113 string IntToString(int & i) 114 { 115 string s; 116 stringstream ss(s); 117 ss << i; 118 return ss.str(); 119 } 120 121 122 void checkcon0(int &num,string chnum) 123 { 124 while(num!=2&&num!=4) 125 { 126 if(chnum=="否") 127 { 128 num=2; 129 } 130 else if(chnum=="是") 131 { 132 num=4; 133 } 134 else 135 { 136 cout<<"输入不合法,请重新输入: "; 137 cin>>chnum; 138 cout<<endl; 139 } 140 } 141 } 142 void checkcon1(int &num1,string chnum) 143 { 144 while(num1!=1&&num1!=0) 145 { 146 if(chnum=="否") 147 { 148 num1=1; 149 } 150 else if(chnum=="是") 151 { 152 num1=0; 153 } 154 else 155 { 156 cout<<"输入不合法,请重新输入: "; 157 cin>>chnum; 158 cout<<endl; 159 } 160 } 161 162 } 163 void check(int &num2,string chnum) 164 { 165 num2 = std::atoi(chnum.c_str() ); 166 while(num2<=0) 167 { 168 cout<<"输入不合法,请重新输入: "; 169 cin>>chnum; 170 cout<<endl; 171 num2 = std::atoi(chnum.c_str() ); 172 } 173 } 174 175 int main() 176 { 177 //数据定义部分 178 srand((int)time(NULL)); 179 int control[2],itemnum, num_max, num_min, num_num, bracket_num; 180 string chnum[5]; 181 string express = ""; 182 char symbol[4],c[20];; //随机计算符号数组 183 symbol[0] = \'+\'; 184 symbol[1] = \'-\'; 185 symbol[2] = \'*\'; 186 symbol[3] = \'/\'; 187 188 //输入及判断部分 189 cout << "是否有乘除(是/否): "; 190 cin >> chnum[0]; 191 checkcon0(control[0],chnum[0]); 192 cout << "是否有括号(是/否): "; 193 cin >> chnum[1]; 194 checkcon1(control[1],chnum[1]); 195 cout << "数字最大取值: "; 196 cin >> chnum[2]; 197 check(num_max,chnum[2]); 198 cout << "数字最小取值: "; 199 cin >> chnum[3]; 200 check(num_min,chnum[3]); 201 cout<<"式子数量: "; 202 cin>>chnum[4]; 203 check(itemnum,chnum[4]); 204 205 string *item=new string[itemnum]; 206 double *result = new double[itemnum]; 207 double *uans = new double[itemnum]; 208 int rightnum = 0; 209 210 //算式生成部分 211 for (int count = 0; count<itemnum; count++) 212 { 213 num_num = rand() % 10; 214 string *str = new string[num_num]; 215 if (num_num == 0 || num_num == 1) 216 { 217 count--; 218 continue; 219 } 220 221 //定义并初始化动态数组 num:数字数组 symnum:符号选择数组 sym:符号数组 222 int *num = new int[num_num]; 223 int *symnum = new int[num_num - 1]; 224 char *sym = new char[num_num - 1]; 225 226 int bracket_leftposition, bracket_rightposition; 227 int *bracket_left_time = new int[num_num]; //定义左、右括号生成次数数组,下标为数字位置 228 int *bracket_right_time = new int[num_num]; 229 string *bracket_left = new string[num_num](); //定义左右括号字符串型数组 230 string *bracket_right = new string[num_num](); 231 for (int rcount = 0; rcount<num_num; rcount++) //左、右括号生成次数初始化 232 { 233 bracket_left_time[rcount] = 0; 234 bracket_right_time[rcount] = 0; 235 } 236 237 //给参与计算的数赋值(指定数值范围) 238 for (int cnum = 0; cnum<num_num; cnum++) 239 { 240 num[cnum] = rand() % (num_max - num_min + 1) + num_min; 241 } 242 243 //随机生成式子的各个位置的符号 244 for (int snum = 0; snum<num_num - 1; snum++) 245 { 246 symnum[snum] = rand() % control[0]; 247 sym[snum] = symbol[symnum[snum]]; 248 } 249 250 251 if (control[1] == 0) 252 { 253 bracket_num = rand() % 7 + 1; 254 //生成括号次数 255 for (int bcount = 0; bcount<bracket_num; bcount++) 256 { 257 bracket_leftposition = rand() % num_num; //随机生成左右括号的位置 258 bracket_rightposition = rand() % num_num; 259 if ((bracket_leftposition >= bracket_rightposition)||((bracket_leftposition==0)&&(bracket_rightposition==num_num-1))) //先剔除部分一次性在一个数左右同时生成左右括号和在整个式子前后生成式子的情况 260 { 261 continue; 262 } 263 bracket_left_time[bracket_leftposition]++; //该位置数左括号生成次数+1 264 bracket_right_time[bracket_rightposition]++; 265 } 266 } 267 for (int stnum = 0; stnum < num_num-2; stnum++) 268 { 269 if ((symbol[symnum[stnum]] == \'/\') && (symbol[symnum[stnum + 1]] == \'/\')) 270 { 271 bracket_left_time[stnum]++; 272 bracket_right_time[stnum + 1]++; 273 } 274 } 275 for (int snum = 0; snum < num_num ; snum++) 276 { 277 278 if (bracket_left_time[snum] == 1) 279 { 280 bracket_left[snum] = "("; 281 } 282 if (bracket_left_time[snum] == 2) 283 { 284 bracket_left[snum] = "(("; 285 } 286 if (bracket_left_time[snum] == 3) 287 { 288 bracket_left[snum] = "((("; 289 } 290 if (bracket_right_time[snum] == 1) 291 { 292 bracket_right[snum] = ")"; 293 } 294 if (bracket_right_time[snum] == 2) 295 { 296 bracket_right[snum] = "))"; 297 } 298 if (bracket_right_time[snum] == 3) 299 { 300 bracket_right[snum] = ")))"; 301 } 302 for (int bpcount = 0; bpcount<num_num; bpcount++) //再次扫描数字左右括号生成次数相等的情况并排除 303 { 304 if (bracket_left_time[bpcount] == bracket_right_time[bpcount]) 305 { 306 bracket_right[bpcount] = ""; 307 bracket_left[bpcount] = ""; 308 } 309 } 310 } 311 312 王爽《汇编语言》第三版 第十五章 外中断