更新内容:
1.在之前基础上实现四个数的四则运算。
2.实现了带有括号的运算。
存在问题:
运算过程中偶尔会有-nan(ind)的结果,还在找原因。
部分代码如下:
1 //运算符栈的长度 2 #define OPSTACK_LENGTH 5 3 //操作数栈的长度 4 #define NUMSTACK_LENGTH 100 5 //输入串的最大长度 6 #define MAX_STRING_LENGTH 100 7 #pragma warning(disable:4996) 8 //表达式结构体 9 struct biaodashi 10 { 11 char word; 12 }; 13 //运算符结构体 14 struct operatorStruct 15 { 16 //运算符名称 17 char name; 18 //优先级 19 int priority; 20 //目数,即操作数个数,例如单目运算符为1,双目运算符2 21 int opnum; 22 }; 23 24 typedef struct operatorStruct OPERATOR; 25 26 //运算符栈 27 OPERATOR opStack[OPSTACK_LENGTH]; 28 //运算符栈顶指针 29 30 //操作数栈 31 double numStack[NUMSTACK_LENGTH]; 32 //操作数栈顶指针 33 int opStackTop = -1; 34 int numStackTop = -1; 35 36 //获取一个字符所代表的运算符的优先级 37 int getPriority(char name) 38 { 39 if (name == '(' || name == ')') 40 { 41 return 0; 42 } 43 if (name == '!') 44 { 45 return 3; 46 } 47 if (name == '*' || name == '/') 48 { 49 return 2; 50 } 51 if (name == '+' || name == '-') 52 { 53 return 1; 54 } 55 56 } 57 //获取一个字符所代表的运算符的目数 58 int getOpNum(char name) 59 { 60 if (name == '*' || name == '/' || name == '+' || name == '-') 61 { 62 return 2; 63 } 64 if (name == '!') 65 { 66 return 1; 67 } 68 if (name == '(' || name == ')') 69 { 70 return 0; 71 } 72 73 } 74 75 //运算符压栈 76 void pushOperator(OPERATOR op) 77 { 78 if (opStackTop < OPSTACK_LENGTH - 1) 79 { 80 opStack[++opStackTop] = op; 81 } 82 } 83 //运算符出栈 84 OPERATOR popOperator() 85 { 86 if (opStackTop >= 0) 87 { 88 return opStack[opStackTop--]; 89 } 90 } 91 //操作数压栈 92 void pushNumber(double num) 93 { 94 if (numStackTop < NUMSTACK_LENGTH - 1) 95 { 96 numStack[++numStackTop] = num; 97 } 98 } 99 //操作数出栈 100 double popNumber() 101 { 102 if (numStackTop >= 0) 103 { 104 return numStack[numStackTop--]; 105 } 106 } 107 108 //从操作数栈中弹出两个操作数,完成一次双目运算 109 double opertate2Num(OPERATOR op) 110 { 111 double num2 = popNumber(); 112 double num1 = popNumber(); 113 if (op.name == '+') 114 { 115 return num1 + num2; 116 } 117 if (op.name == '-') 118 { 119 return num1 - num2; 120 } 121 if (op.name == '*') 122 { 123 return num1 * num2; 124 } 125 if (op.name == '/') 126 { 127 return num1 / num2; 128 } 129 } 130 //从操作数栈中弹出一个操作数,完成一次单目运算 131 double opertate1Num(OPERATOR op) 132 { 133 double num = popNumber(); 134 if (op.name == '!') 135 { 136 double result = 1; 137 while (num > 1) 138 { 139 result *= num; 140 num--; 141 } 142 return result; 143 } 144 145 } 146 //完成一次运算 147 double operate(OPERATOR op) 148 { 149 if (op.opnum == 1) 150 { 151 return opertate1Num(op); 152 } 153 else if (op.opnum == 2) 154 { 155 return opertate2Num(op); 156 } 157 158 } 159 //四则运算计算器 160 double Calculate(struct biaodashi *string) 161 { 162 163 int i; 164 OPERATOR op, topOp;//op为从当前输入串中提取的一个运算符,topOp为运算符栈栈顶的运算符 165 166 topOp.name = '#'; 167 topOp.priority = 0; 168 topOp.opnum = 0; 169 pushOperator(topOp);//压入#作为初始运算符 170 171 for (i = 0; string[i].word != '=';i++) 172 { 173 //从输入串中取出一个字符作为开始,进行处理,直到表达式结束 174 if (string[i].word!='+' && string[i].word != '-'&& string[i].word != '*'&& string[i].word != '/'&& string[i].word != '('&& string[i].word != ')') 175 { 176 //如果是操作数,将整个操作数提取出来,压入操作数栈 177 pushNumber((double)(string[i].word)); 178 } 179 else 180 { 181 op.name = string[i].word; 182 op.priority = getPriority(string[i].word); 183 op.opnum = getOpNum(string[i].word); 184 topOp = popOperator(); 185 if (op.name == '(') 186 { 187 //如果是'(',将从栈顶弹出的运算符压回栈内,并将当前运算符则压栈 188 pushOperator(topOp); 189 pushOperator(op); 190 } 191 else if (op.name == ')') 192 { 193 //如果是')',则进行运算,每次运算结果作为一个操作数压入操作数栈,直到将'('弹出运算符栈 194 while (topOp.name != '(') 195 { 196 pushNumber(operate(topOp)); 197 topOp = popOperator(); 198 } 199 } 200 else 201 { 202 //如果是普通运算符 203 if (topOp.name != '#' && op.priority <= topOp.priority) 204 { 205 //如果运算符栈非空,且当前运算符的优先级大于栈顶运算符,则进行一次运算,将结果压入操作数栈 206 pushNumber(operate(topOp)); 207 } 208 else 209 { 210 //否则将从栈顶弹出的运算符压回 211 pushOperator(topOp); 212 } 213 //将当前运算符压栈 214 pushOperator(op); 215 } 216 } 217 218 } 219 //完成栈内剩余的运算 220 while ((topOp = popOperator()).name != '#') 221 { 222 pushNumber(operate(topOp)); 223 } 224 //操作数栈中剩下的最后一个数即为结果 225 return popNumber(); 226 }
这部分为计算器,主体来自http://blog.csdn.net/bhq2010/article/details/7516369,做了些必要的修改。
1 int N = 0, i = 0; 2 int optr1 = 0, optr2 = 0, optr3 = 0, kuohao = 0; 3 int num1, num2, num3, num4; 4 5 double answer1, answer2; 6 struct biaodashi string[15]; 7 char str[] = "+-*/", ch; 8 9 srand((unsigned)time(0)); 10 11 printf("请输入本次测试的题目数量:"); //手动输入题目数量 12 scanf("%d", &N); 13 ch = getchar(); 14 15 printf("保留两位小数\n"); //输入结果如果有小数,保留两位小数
部分主函数代码。
1 for (i = 0; i < N; i++) 2 { 3 num1 = rand() % 100 + 1; //生成随机数 4 num2 = rand() % 100 + 1; 5 num3 = rand() % 100 + 1; 6 num4 = rand() % 100 + 1; 7 optr1 = rand() % 4; 8 optr2 = rand() % 4; 9 optr3 = rand() % 4; 10 kuohao = rand() % 8; 11 if (num1 > 40) 12 { 13 printf("题号:%d\n", i + 1); 14 printf("%d %c %d %c %d %c %d=?\n", num1, str[optr1], num2, str[optr2], num3, str[optr3], num4); 15 string[0].word = num1; 16 string[1].word = str[optr1]; 17 string[2].word = num2; 18 string[3].word = str[optr2]; 19 string[4].word = num3; 20 string[5].word = str[optr3]; 21 string[6].word = num4; 22 string[7].word = '='; 23 answer1 = Calculate(string); 24 scanf("%lf", &answer2); 25 ch = getchar(); 26 if ((fabs(answer2-answer1))<0.01) 27 printf("正确\n"); 28 else printf("错误 正确答案是:%-10.2lf\n", answer1); 29 }
这部分为不带括号的出题方式,比例大小为60%
else { printf("题号:%d\n", i + 1); switch (kuohao) { case 1: printf("(%d %c %d) %c %d %c %d=?\n", num1, str[optr1], num2, str[optr2], num3, str[optr3], num4); string[0].word = '('; string[1].word = num1; string[2].word = str[optr1]; string[3].word = num2; string[4].word = ')'; string[5].word = str[optr2]; string[6].word= num3; string[7].word = str[optr3]; string[8].word = num4; string[9].word = '='; break; case 2: printf("(%d %c %d %c %d) %c %d=?\n", num1, str[optr1], num2, str[optr2], num3, str[optr3], num4); string[0].word = '('; string[1].word = num1; string[2].word = str[optr1]; string[3].word = num2; string[4].word = str[optr2]; string[5].word = num3; string[6].word = ')'; string[7].word = str[optr3]; string[8].word = num4; string[9].word = '='; break; case 3: printf("%d %c (%d %c %d) %c %d=?\n", num1, str[optr1], num2, str[optr2], num3, str[optr3], num4); string[0].word = num1; string[1].word = str[optr1]; string[2].word = '('; string[3].word = num2; string[4].word = str[optr2]; string[5].word = num3; string[6].word = ')'; string[7].word = str[optr3]; string[8].word = num4; string[9].word = '='; break; case 4: printf("%d %c (%d %c %d %c %d)=?\n", num1, str[optr1], num2, str[optr2], num3, str[optr3], num4); string[0].word = num1; string[1].word = str[optr1]; string[2].word = '('; string[3].word = num2; string[4].word = str[optr2]; string[5].word = num3; string[6].word = str[optr3]; string[7].word = num4; string[8].word = ')'; string[9].word = '='; break; case 5: printf("%d %c %d %c (%d %c %d)=?\n", num1, str[optr1], num2, str[optr2], num3, str[optr3], num4); string[0].word = num1; string[1].word = str[optr1]; string[2].word = num2; string[3].word= str[optr2]; string[4].word = '('; string[5].word = num3; string[6].word = str[optr3]; string[7].word = num4; string[8].word = ')'; string[9].word = '='; break; case 6: printf("(%d %c %d) %c (%d %c %d)=?\n", num1, str[optr1], num2, str[optr2], num3, str[optr3], num4); string[0].word = '('; string[1].word = num1; string[2].word = str[optr1]; string[3].word = num2; string[4].word = ')'; string[5].word = str[optr2]; string[6].word = '('; string[7].word = num3; string[8].word = str[optr3]; string[9].word = num4; string[10].word = ')'; string[11].word = '='; break; case 7: printf("(%d %c (%d %c %d)) %c %d=?\n", num1, str[optr1], num2, str[optr2], num3, str[optr3], num4); string[0].word = '('; string[1].word = num1; string[2].word = str[optr1]; string[3].word = '('; string[4].word = num2; string[5].word = str[optr2]; string[6].word = num3; string[7].word = ')'; string[8].word = ')'; string[9].word = str[optr3]; string[10].word = num4; string[11].word = '='; break; case 8: printf("%d %c (%d %c (%d %c %d))=?\n", num1, str[optr1], num2, str[optr2], num3, str[optr3], num4); string[0].word = num1; string[1].word = str[optr1]; string[2].word = '('; string[3].word = num2; string[4].word = str[optr2]; string[5].word= '('; string[6].word = num3; string[7].word = str[optr3]; string[8].word = num4; string[9].word = ')'; string[10].word = ')'; string[11].word = '='; break; default: printf("错误\n"); } answer1 = Calculate(string); scanf("%lf", &answer2); ch = getchar(); if ((fabs(answer2-answer1))<0.01) printf("正确\n"); else printf("错误 正确答案是:%-10.2lf\n", answer1); }
带括号的出题方式采用的枚举法,所以略长,比例为40%
输出结果:
结果:可以看到第6题出现了-nan(ind)的问题,百度一下意思是not a number,应该是计算过程中出了问题,但是还没找到。