第二周,老师接着上次的程序有对四则运算的程序,做出来一些要求,这次要求可以控制乘除法,有无括号,控制输出方式,控制结果有无负数,有无余数。
我在对原先的程序分析了一下,发现我原先的程序可扩展性特别差,完全不能再原先的基础上叠加功能,所以我又重新写了一个程序。
思路分析:
1、控制乘除法
2、括号添加。思路:题中只要求添加括号,所以我的括号添加方法是:把所有数放入一个数组中,‘+-*/’都用数字化表示,使用随机函数实现随机选择在哪个运算符左边加上左括号,右括号统一加在右边,其中括号最多只有2层嵌套。
3、判断重复:先生成所有运算式子,然后使用循环判断有无重复。
4、结果有无负数和余数:没任何技巧使用循环里面在加循环,先找到最里面的括号,先乘除再加减,然后消括号重复加减最后得出结果,根据最后结果得出结果。
5、输出方式:使用fstream类把结果输出到1.txt中
#include<iostream>
#include"time.h"
#include<fstream>
#define SUM 1000
#define SUMS 300
using namespace std;
int Results[SUM][SUMS] = { }; void Input(int &base, int &top){
cout << "\n请输入下限(正数) ";
cin >> base;
cout << "\n请输入上限(正数) ";
cin >> top;
}
//生成四则运算公式
void Combination1(int time, int base,int top,int add,int dec,int mul,int div,int equ){
int choose;
int amount;
amount = + rand() % ;
Results[time][] = + rand() % top;
while (Results[time][] <= base){
Results[time][] = + rand() % top;
}
amount--;
int count = ;
while (true){
choose = + rand() % ;
if (choose == ){
Results[time][count] = add;
}
if (choose == ){
Results[time][count] = dec;
}
if (choose == ){
Results[time][count] = mul;
}
if (choose == ){
Results[time][count] = div;
}
count++;
Results[time][count] = + rand() % top;
while (Results[time][count] <= base){
Results[time][count] = + rand() % top;
}
count++;
amount--;
if (amount == ){
break;
}
}
Results[time][count] = equ; }
//生成二则运算公式
void Combination2(int time, int base, int top, int add, int dec, int mul, int div, int equ){
int choose;
int amount;
amount = + rand() % ;
Results[time][] = + rand() % top;
while (Results[time][] <= base){
Results[time][] = + rand() % top;
}
amount--;
int count = ;
while (true){
choose = + rand() % ;
if (choose == ){
Results[time][count] = add;
}
if (choose == ){
Results[time][count] = dec;
}
count++;
Results[time][count] = + rand() % top;
while (Results[time][count] <= base){
Results[time][count] = + rand() % top;
}
count++;
amount--;
if (amount == ){
break;
}
}
Results[time][count] = equ;
}
//cmd
void Output(int time, int top,int add, int dec, int mul, int div, int equ,int LBra,int RBra){
int count = ;
while (true){
if (Results[time][count] <= top){
cout << Results[time][count];
}
if (Results[time][count] == add){
cout << "+";
}
if (Results[time][count] == dec){
cout << "-";
}
if (Results[time][count] == mul){
cout << "*";
}
if (Results[time][count] == div){
cout << "/";
}
if (Results[time][count] == LBra){
cout << "(";
}
if (Results[time][count] == RBra){
cout << ")";
}
if (Results[time][count] == equ){
cout << "=";
break;
}
count++;
}
}
//文件流
void OutputFile(int time, int top, int add, int dec, int mul, int div, int equ, int LBra, int RBra){
ofstream out("1.txt", ios::out);
int count;
for (int i = ; i < time; i++){
count = ;
while (true){ if (Results[i][count] <= top){
out << Results[i][count];
}
if (Results[i][count] == add){
out << "+";
}
if (Results[i][count] == dec){
out << "-";
}
if (Results[i][count] == mul){
out << "*";
}
if (Results[i][count] == div){
out << "/";
}
if (Results[i][count] == LBra){
out << "(";
}
if (Results[i][count] == RBra){
out << ")";
}
if (Results[i][count] == equ){
out << "=";
break; }
count++;
}
out << endl;
}
out.close(); }
//添加括号
void AddBrackets(int time, int add, int dec, int mul, int div, int equ, int LBra,int RBra){
int place;
int level=;
int sumNum,sumNum1;
int count;
int BracketNum;
BracketNum = + rand() % ;
for (int i = ; i < SUMS; i++){
if (Results[time][i] >= add&&Results[time][i] <= div){
level++;
}
if (Results[time][i] == equ){
sumNum = i;
break;
}
}
int BracketNum1;
BracketNum1 = BracketNum;
//随机在运算公式中生成左括号
for (int j = ; j < BracketNum; j++){
sumNum1 = sumNum;
if (level == ){
break;
}
place = + rand() % (level - );
count = ;
while (true){
if (Results[time][count] >= add&&Results[time][count] <= div){
place = place - ;
if (place == ){
break;
}
}
count++;
}
if (Results[time][count + ] == LBra){
BracketNum1--;
break;
}
while (true){
Results[time][sumNum + ] = Results[time][sumNum];
if (sumNum - == count){
Results[time][sumNum] = LBra;
break;
}
sumNum--;
}
sumNum = sumNum1 + ;
}
//直接在等式右边生成相同数量的有括号
for (int k = ; k < BracketNum1; k++){
if (level == ){
break;
}
Results[time][sumNum + ] = Results[time][sumNum];
Results[time][sumNum] = RBra;
sumNum++;
}
if (Results[time][sumNum] != equ){
AddBrackets(time, add, dec, mul, div, equ, LBra, RBra);
}
sumNum1 = sumNum-;
count = ;
while (true){
if (Results[time][sumNum1] == RBra){
count++;
}
sumNum1--;
if (sumNum1 == sumNum - ){
break;
}
}
sumNum1 = ;
while (true){
if (Results[time][sumNum1] == LBra){
count--;
}
if (sumNum1 == sumNum){
break;
}
sumNum1++;
}
if (count < ){
AddBrackets(time, add, dec, mul, div, equ, LBra, RBra);
}
}
//判断有误重复
int Replay(){
int i, j,k;
int charge;
for (i = ; i < SUM; i++){
charge = ;
for (j = i+; j < SUM; j++){
for (k = ; k < SUMS; k++){
if (Results[i][k] != Results[j][k]){
charge = ;
break;
}
}
if (charge == ){
return ;
}
}
}
return ;
} //判断有无余数和是否正数
//把公式化成float型,有利于进行判断有无余数,而且计算更准确
void Judge(int time, int equ, int add, int dec, int mul, int div, int LBra, int RBra, int &pos, int &integer){
float calculate[SUMS];
int Bracket[] = { }; //用于记录括号位置
int count = ;
int sumNum, sumNum1, sumNum2;
for (int i = ; i < SUMS; i++){
if (Results[time][i] == LBra){
Bracket[count] = i;
count++;
}
if (count == ){
break;
}
if (Results[time][i] == RBra){
break;
}
}
for (int i = ; i < SUMS; i++){
if (Results[time][i] == RBra){
sumNum = i;
break;
}
}
for (int i = ; i < sumNum; i++){
calculate[i] = float(Results[time][i]);
}
int Has = ;
int place;
//双括号
if (count == ){
sumNum1 = Bracket[]; //sumNum2 = sumNum1;
while (true){
Has = ;
for (int i = sumNum1 + ; i < sumNum; i++){
if (calculate[i] == mul)
{
calculate[i - ] = calculate[i - ] * calculate[i + ];
Has = ;
place = i;
break;
}
if (calculate[i] == div)
{
calculate[i - ] = calculate[i - ] / calculate[i + ];
Has = ;
place = i;
break;
}
}
if (Has == ){
while (true){
if ((place + ) == sumNum){
break;
}
calculate[place] = calculate[place + ];
place++; }
sumNum -= ;
}
if (Has == ){
break;
}
}
sumNum1 += ;
sumNum2 = sumNum1;
while (true){
if (sumNum1 + >= sumNum){
break;
}
if (calculate[sumNum1 + ] == add){
calculate[sumNum2] = calculate[sumNum2] + calculate[sumNum1 + ];
sumNum1 += ;
}
if (calculate[sumNum1 + ] == dec){
calculate[sumNum2] = calculate[sumNum2] - calculate[sumNum1 + ];
sumNum1 += ;
}
}
calculate[sumNum2 - ] = calculate[sumNum2];
sumNum = sumNum2;
count = count - ;
}
if (count == ){ //单括号
sumNum1 = Bracket[];
while (true){
Has = ;
for (int i = sumNum1 + ; i < sumNum; i++){
if (calculate[i] == mul)
{
calculate[i - ] = calculate[i - ] * calculate[i + ];
Has = ;
place = i;
break;
}
if (calculate[i] == div)
{
calculate[i - ] = calculate[i - ] / calculate[i + ];
Has = ;
place = i;
break;
}
}
if (Has == ){
while (true){
if ((place + ) == sumNum){
break;
}
calculate[place] = calculate[place + ];
place++; }
sumNum -= ;
}
if (Has == ){
break;
}
}
sumNum1 += ;
sumNum2 = sumNum1;
while (true){
if (sumNum1 + >= sumNum){
break;
}
if (calculate[sumNum1 + ] == add){
calculate[sumNum2] = calculate[sumNum2] + calculate[sumNum1 + ];
sumNum1 += ;
}
if (calculate[sumNum1 + ] == dec){
calculate[sumNum2] = calculate[sumNum2] - calculate[sumNum1 + ];
sumNum1 += ;
}
}
calculate[sumNum2 - ] = calculate[sumNum2];
sumNum = sumNum2;
}
for (int i = ; i < sumNum; i++){
if (calculate[i] == mul){
calculate[i - ] *= calculate[i + ];
place = i;
while (true){
if (place + >= sumNum){
sumNum -= ;
break;
}
calculate[place] = calculate[place + ];
place += ;
}
}
if (calculate[i] == div){
calculate[i - ] /= calculate[i + ];
place = i;
while (true){ if (place + >= sumNum){
sumNum -= ;
break;
}
calculate[place] = calculate[place + ];
place += ;
}
}
}
for (int i = ; i < sumNum; i++){
if (calculate[i] == add){
calculate[] = calculate[] + calculate[i + ];
}
if (calculate[i] == dec){
calculate[] = calculate[] + calculate[i + ];
}
}
//结果判断
if (calculate[] >= ){
pos = ;
}
else{
pos = ;
}
if ((calculate[]-int(calculate[]))!=)
{
integer = ;
}
else{
integer = ;
} }
int main(){
srand((unsigned)time(NULL));
int add;
int dec;
int mul;
int div;
int equ;
int base;
int top;
int LBra;
int RBra;
int MulAndDiv;
int HaveBracket;
int AboveZero;
int Isint;
int Isrepeat;
int Isfile;
int sum;
int integer;
int pos;
cout << "是否使用乘除?1表示是,0表示不是: ";
cin >> MulAndDiv;
cout << "\n是否有括号?1表示是,0表示不是: ";
cin >> HaveBracket;
cout << "\n结果能否有负数?1表示能,0表示不能: ";
cin >> AboveZero;
cout << "\n结果能否有余数? 1表示能,0表示不能: ";
cin >> Isint;
cout << "请输入题目数量:";
cin >> sum;
cout << "是否输出到文件? 1表示是,0表示否: ";
cin >> Isfile;
Input(base, top);
add = top + ;
dec = top + ;
mul = top + ;
div = top + ;
equ = top + ;
LBra = top + ;
RBra = top + ;
//判断乘除和有无括号
for (int j = ; j < sum; j++){
if (MulAndDiv == ){
Combination2(j, base, top, add, dec, mul, div, equ);
}
else
Combination1(j, base, top, add, dec, mul, div, equ);
if (HaveBracket == ){
AddBrackets(j, add, dec, mul, div, equ, LBra, RBra);
} }
//判断有无负数和余数
for (int j = ; j < sum; j++){
pos = ;
integer = ;
Judge(j, equ, add, dec, mul, div, LBra, RBra, pos, integer);
if (Isint == ){
while (integer == ){
if (MulAndDiv == ){
Combination2(j, base, top, add, dec, mul, div, equ);
}
else
Combination1(j, base, top, add, dec, mul, div, equ);
if (HaveBracket == ){
AddBrackets(j, add, dec, mul, div, equ, LBra, RBra);
}
Judge(j, equ, add, dec, mul, div, LBra, RBra, pos, integer);
}
}
if (AboveZero == ){
while (pos == ){
if (MulAndDiv == ){
Combination2(j, base, top, add, dec, mul, div, equ);
}
else
Combination1(j, base, top, add, dec, mul, div, equ);
if (HaveBracket == ){
AddBrackets(j, add, dec, mul, div, equ, LBra, RBra);
}
Judge(j, equ, add, dec, mul, div, LBra, RBra, pos, integer);
}
}
}
//查重
while(true){
if (Replay() == ){
if (Isfile == ){
OutputFile(sum, top, add, dec, mul, div, equ, LBra, RBra);
}
else{
for (int j = ; j < sum; j++){
Output(j, top, add, dec, mul, div, equ, LBra, RBra);
cout << endl;
}
}
break;
}
else
{
for (int j = ; j < sum; j++){
if (MulAndDiv == ){
Combination2(j, base, top, add, dec, mul, div, equ);
}
else
Combination1(j, base, top, add, dec, mul, div, equ);
if (HaveBracket == ){
AddBrackets(j, add, dec, mul, div, equ, LBra, RBra);
} }
}
}
return ;
}
运行结果如下:
cmd输出:
1.txt文件输出:
总结:这一次的实验我感觉蛮难的,我差不多花了4个晚上外加一个星期六才写完,而且这也是勉强实现功能,在编写功能模块时,总是单独测试都运行十分OK,但是几个功能一迭加就老是BUG,然后花1-2小时去调试解决,好麻烦,当然在实现真分数插入括号时老是出现错误,我都不知道该怎么办了-_-!! 总之,这次的程序不能说完美吧,但还是勉强能实现功能。
项目计划总结:
日期\任务 | 听课 | 编写程序 | 查阅资料 | 日总计 |
星期一 | 2 | 1 | 1 | 4 |
星期二 | 2 | 2 | ||
星期三 | 2 | 1 | 3 | |
星期四 | 2 | 2 | 4 | |
星期五 | 3 | 1 | 4 | |
星期六 | 5 | 5 | ||
星期日 | ||||
周总计 | 4 | 15 | 3 |
22 |
时间记录日志:
日期 | 开始时间 | 结束时间 | 中断时间 | 静时间 | 活动 | 备注 |
3/7 | 14:00 | 15:50 | 10 | 100 | 听课 | 软件工程 |
19:30 | 21:50 | 10 | 130 | 编写程序 | 编写第二次程序&查资料 | |
3/8 | 19:20 | 21:45 | 10 | 135 | 编写程序 | |
3/9 | 16:30 | 17:40 | 10 | 60 | 查阅资料 | 查资料和同学间交流 |
19:20 | 21:50 | 20 | 130 | 编写程序 | ||
3/10 | 14:00 | 15:50 | 10 | 100 | 听课 | 软件工程 |
19:20 | 21:20 | 120 | 编写程序 | 调试程序寻找错误地方 | ||
3/11 | 18:10 | 21:40 | 20 | 190 | 编写程序 | 调试程序为主 |
7:30 | 9:00 | 10 | 80 | 看书 | 看数据结构书寻找解决办法 | |
3/12 | 8:00 | 15:00 | 50 | 370 | 调试 | 最终调试 |
16:00 | 17:00 | 60 | 博客 | 撰写博客 |
缺陷记录日志:
日期 | 编号 | 引入阶段 | 排除阶段 | 修复时间&问题描述 |
3/7 | 1 | 编码 | 编译 | 1小时,真分数叠加,后来发现是输出时除号和正分数符号弄反了 |
3/8 | ||||
3/9 | ||||
3/10-3/11 | 2 | 编码 | 编译 | 4小时,循环叠加混乱,不是忘记赋值就是忘记跳出循环 |
3/11-3/12 | 3 | 编码 | 编译 | 4小时,括号添加数量不对,后来发现是数组越界 |