软工第二次作业

GIT地址 https://github.com/Cpu8285
GIT名称 Cpu8285
学号后五位 64222
博客地址 https://www.cnblogs.com/565118008a/
作业地址 https://www.cnblogs.com/ChildishChange/p/10398212.htm

 

 

 

 

 

1.配置环境

试了很多钟方法,VS2017无法安装,可能我的电脑不适配,然后改下VS2015,居然这么久,惊了。。。

 

 2.代码

 

 

 

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 mt19937 mt(time(0)); // 随机数生成器
  6 
  7 map<int, char> op; // 运算符id及其符号映射
  8 map<int, int> pri; // 运算符id及其优先级映射
  9 // 10表示加号   运算优先级为 0
 10 // 11表示减号   运算优先级为 0
 11 // 12表示乘号   运算优先级为 1
 12 // 13表示除号   运算优先级为 1
 13 // 14表示左括号 运算优先级为 2
 14 // 15表示右括号 运算优先级为 2
 15 
 16 // 运算数结构体,id为运算数的位置,val为运算数的值
 17 struct node{
 18     int id, val;
 19     node(int id = -1, int val = -1):id(id), val(val){}
 20 };
 21 
 22 // tot:逆波兰表达式的长度,operatorNum:运算符个数
 23 // operandNum:运算数的个数,bracketNum:括号对数,ans:运算式最终答案
 24 // hasBracket:某个数字处是否有括号,-1表示无括号,14表示左括号,15表示右括号
 25 // operators:对应位置的运算符种类 operands:表示对应位置运算数的值
 26 // RPN:存储逆波兰表达式 fac:存储某个数的约数
 27 // opr:中缀表达式转后缀表达式时的运算符栈
 28 // opd:中缀表达式转后缀表达式时的运算数栈
 29 
 30 int tot, operatorNum, operandNum, bracketNum, ans;
 31 int hasBracket[15], operators[15], operands[15];
 32 int RPN[55], fac[105];
 33 stack<int> opr;
 34 stack<node> opd;
 35 
 36 // 初始化函数零:初始化运算符 id 符号 以及运算优先级,并且重定向输出
 37 void init0(){
 38     op[10] = '+', op[11] = '-';
 39     op[12] = '*';
 40     op[14] = '(', op[15] = ')';
 41     pri[10] = 0, pri[11] = 0;
 42     pri[12] = 1, pri[13] = 1;
 43     pri[14] = 2, pri[15] = 2;
 44     freopen("../result.txt", "w", stdout);
 45 }
 46 
 47 // 初始化函数一:在每次调用solve()时进行初始化
 48 void init1(){
 49     tot = 0;
 50     for(int i = 0; i < 15; ++i){
 51         operators[i] = -1;
 52         operands[i] = -1;
 53         hasBracket[i] = -1;
 54     }
 55     while(!opr.empty()) opr.pop();
 56     while(!opd.empty()) opd.pop();
 57 }
 58 
 59 // 初始化函数二:在每次调用getOperands()时进行初始化
 60 void init2(){
 61     tot = 0;
 62     while(!opr.empty()) opr.pop();
 63     while(!opd.empty()) opd.pop();
 64 }
 65 
 66 // 获取运算数的值的函数,如果返回 true 则表示获取成功,否则表示获取失败
 67 bool getOperands(){
 68     init2();
 69     // 将中缀表达式转换成后缀表达式(也就是逆波兰表达式)
 70     if(hasBracket[0] != -1) opr.push(hasBracket[0]);
 71     RPN[tot++] = 0;
 72     for(int i = 1; i < operandNum; ++i){
 73         while(true){
 74             if(opr.empty() || opr.top() == 14 || pri[operators[i - 1]] > pri[opr.top()]){
 75                 opr.push(operators[i - 1]);
 76                 break;
 77             }
 78             RPN[tot++] = opr.top();
 79             opr.pop();
 80         }
 81         if(hasBracket[i] == 14){
 82             opr.push(hasBracket[i]);
 83         }
 84         RPN[tot++] = i;
 85         if(hasBracket[i] == 15){
 86             while(opr.top() != 14){
 87                 RPN[tot++] = opr.top();
 88                 opr.pop();
 89             }
 90             opr.pop();
 91         }
 92     }
 93     while(!opr.empty()){
 94         RPN[tot++] = opr.top();
 95         opr.pop();
 96     }
 97     // 转换成逆波兰表达式后便可以进行尝试填数
 98     for(int i = 0; i < tot; ++i){
 99         // 如果为运算数则随机为其赋值
100         if(RPN[i] < 10){
101             int x = mt()%66 + 1;
102             operands[RPN[i]] = x;
103             opd.push(node(RPN[i], x));
104             continue;
105         }
106         //如果为除法,要将除数随机分配为被除数的一个因子
107         //如果为减法,要注意减数不能大于被减数
108 
109         if(RPN[i] == 13){
110             node b = opd.top(); opd.pop();
111             node a = opd.top(); opd.pop();
112             if(a.val%b.val == 0){
113                 opd.push(node(-1, a.val/b.val));
114                 continue;
115             }
116             if(b.id == -1) return false;
117             int cnt = 0;
118             for(int j = 1; j <= a.val; ++j){
119                 if(j >= 100) break;
120                 if(a.val%j) continue;
121                 fac[cnt++] = j;
122             }
123             int x = mt()%cnt;
124             operands[b.id] = fac[x];
125             opd.push(node(-1, a.val/fac[x]));
126         }else if(RPN[i] == 11){
127             node b = opd.top(); opd.pop();
128             node a = opd.top(); opd.pop();
129             int dt = a.val - b.val;
130             if(dt <= 0) return false;
131             opd.push(node(-1, dt));
132         }else{
133             node b = opd.top(); opd.pop();
134             node a = opd.top(); opd.pop();
135             if(RPN[i] == 10) opd.push(node(-1, a.val + b.val));
136             if(RPN[i] == 12) opd.push(node(-1, a.val*b.val));
137         }
138     }
139     ans = opd.top().val; opd.pop();
140     //控制最终运算结果的范围,可根据需要进行调节
141     if(ans < 0 || ans > 1000) return false;
142     return true;
143 }
144 
145 bool solve(){
146     init1();
147     // 随机生成运算符的个数 3~5 ,及运算数个数 4~6
148     operatorNum = mt()%3 + 3;
149     operandNum = operatorNum + 1;
150     // 随机生成括号个数
151     bracketNum = min((int)(operandNum/2), (int)(mt()%3 + 2));
152     // 随机生成运算符的种类
153     for(int i = 0; i < operatorNum; ++i) operators[i] = mt()%4 + 10;
154     // 随机生成括号位置
155     for(int i = 0; i < bracketNum*2; ++i){
156         int x = mt()%operandNum;
157         while(hasBracket[x] != -1) x = mt()%operandNum;
158         hasBracket[x] = 0;
159     }
160 
161     // 根据相对位置确定括号为左括号还是右括号
162     bool lf = true;
163     for(int i = 0; i < operandNum; ++i){
164         if(hasBracket[i] == -1) continue;
165         if(lf) hasBracket[i] = 14;
166         else hasBracket[i] = 15;
167         lf = (!lf);
168     }
169 
170     // 到这里已经将等式预处理成了(a+b)/c*(d-e)的类似形式
171     // 预处理结束之后,我们就要尝试将 a b c d e 确定为具体的数
172     if(!getOperands()) return false;
173 
174     // 在获取完运算数之后,便可以输出我们得到的等式了
175     if(hasBracket[0] != -1) printf("(");
176     printf("%d", operands[0]);
177     for(int i = 1; i < operandNum; ++i){
178         if(operators[i - 1] == 13) printf("÷");
179         else printf("%c", op[operators[i - 1]]);
180         if(hasBracket[i] == 14) printf("(");
181         printf("%d", operands[i]);
182         if(hasBracket[i] == 15) printf(")");
183     }
184     printf("=%d\n", ans);
185     return true;
186 }
187 
188 
189 int main(){
190     // 初始化函数零:初始化运算符 id 符号 以及运算优先级,并且重定向输出
191     init0();
192     //读入需要生成的运算式数量
193     int n;
197     while(n--) while(!solve()) ;
198 
199     return 0;
200 }

3.GIT软件上传GITHUB,VS2017无法下载,所以暂时无从下手。

4·感想

完成质量有点差,早上八点到晚上九点一直再赶,到后面只是把代码研究了出来,其他根本无从下手,

融入新事物的能力差,已经养成依赖老师讲解的思维,到自己做的时候就无所适从,这是我的一个很大

问题。

 

 

 

posted @ 2019-09-21 21:23  陈星鑫  阅读(166)  评论(1编辑  收藏  举报