四则运算3+psp0

题目要求:

  1.程序可以判断用户的输入答案是否正确,如果错误,给出正确答案,如果正确,给出提示。

  2.程序可以处理四种运算的混合算式。

  3.要求两人合作分析,合作编程,单独撰写博客。

团队成员:张绍佳、杜文星(博客:http://www.cnblogs.com/duwenxing/p/5294508.html

设计思路:

代码分写于不同的文件中;

① head.h:在头文件head.h中,将其他.cpp文件中所需要的头文件、全局变量的声明、函数的声明都写在此文件中。

② fraction.cpp:此文件中主要定义了一些与分数有关的函数,如分数的生成化简、加减乘除、分数的输出、分数转字符串等。

③ stack.cpp:此文件的主要功能是将所给的运算式的结果计算出来,主要思路是利用栈先将运算式转化为后缀式,然后再利用栈将后缀式的结果求出,重难点是转化后缀式时如何将真分数当做一个整体,我们的解决方法是通过识别 “(” 和 “)” 来识别;同时在计算时即使是整数我们也将其转化为分数处理,故调用了fraction中的一些方法来进行加减乘除。

④yunsuan.cpp:这个文件的主要功能是实现运算式的生成,并判断使用者输入的结果和题目的答案是否相同来判断对错,并输出正确数与错误数。

⑤main.cpp:主函数所在的头文件,主要功能是和用户进行交互。

工作照:

四则运算3+psp0

代码:

head.h

 #pragma once
#include<iostream>
#include<ctime>
#include<strstream>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstdio>
#include<cmath>
#define random(l,h) (rand()%(h-l+1)+l)//宏定义
#define maxsize 1000
using namespace std;
extern int flag;
/*stack.cpp*/
struct Fraction
{
int up, down;
string high, low;
};
void trans(string exp, char postexp[]);
Fraction compvalue(char postexp[]);//计算后缀表达式的值
/*fraction.cpp*/
int gcd(int a, int b);//求a,b的最大公约数
int max(int a, int b);
int min(int a, int b);
Fraction fraction(int up, int down);//生成分数
Fraction fra(int d, int u);//生成真分数;
Fraction reduction(Fraction result);//分数的化简
Fraction add(Fraction f1, Fraction f2);//分数的加法
Fraction minus1(Fraction f1, Fraction f2);//分数的减法
Fraction multi(Fraction f1, Fraction f2);//分数的乘法
Fraction divide(Fraction f1, Fraction f2);//分数的除法
void ShowResult(Fraction f);//输出分数
string FraToString(Fraction f);//将分数转换为string类型
/*yunsuan.cpp*/
int suiji(int down, int up);//随机生成1至n的整数
bool is_unique(string str, vector <string> s);//判断生成的运算式是否重复
void yunsuan(int time, int low, int high, int fl1, int fl2, int fl3);

fraction.cpp

 #include"head.h"
int gcd(int a, int b)//求a,b的最大公约数
{
if (b == ) return a;
else return gcd(b, a%b);
} int max(int a, int b)//返回两个整数中较大的整数
{
int h = a >= b ? a : b;
return h;
}
int min(int a, int b)//返回两个整数中较小的整数
{
int l = a <= b ? a : b;
return l;
}
Fraction fraction(int up, int down)//生成分数
{
Fraction result;
result.up = up;
result.down = down;
strstream ss, kk;
ss << result.up; ss >> result.high;
kk << result.down; kk >> result.low;
return result;
}
Fraction fra(int d,int u)//生成真分数
{
Fraction result;
int temp1 = suiji(d, u);//调用function函数随机生成两个随机整数
int temp2 = suiji(d, u);
result.up = min(temp1, temp2);
result.down = max(temp1, temp2);
strstream s1, s2;
s1 << result.up; s1 >> result.high;
s2 << result.down; s2 >> result.low;
return result;
}
Fraction reduction(Fraction result)//分数的化简
{
if (result.down < )
{
result.up = -result.up;
result.down = -result.down;
}
if (result.up == )
{
result.down = ;
}
else
{
int d = gcd(abs(result.up), abs(result.down));
result.up /= d;
result.down /= d;
}
strstream s3, s4;
s3 << result.up; s3 >> result.high;
s4 << result.down; s4 >> result.low;
return result;
}
Fraction add(Fraction f1, Fraction f2)//分数的加法
{
Fraction result;
result.up = f1.up*f2.down + f1.down * f2.up;
result.down = f1.down*f2.down;
return reduction(result);
}
Fraction minus1(Fraction f1, Fraction f2)//分数的减法
{
Fraction result;
result.up = f1.up*f2.down - f1.down*f2.up;
result.down = f1.down*f2.down;
return reduction(result);
}
Fraction multi(Fraction f1, Fraction f2)//分数的乘法
{
Fraction result;
result.up = f1.up*f2.up;
result.down = f1.down*f2.down;
return reduction(result);
}
Fraction divide(Fraction f1, Fraction f2)//分数的除法
{
Fraction result;
result.up = f1.up*f2.down;
result.down = f1.down*f2.up;
return reduction(result);
}
void ShowResult(Fraction f)//输出分数
{
f = reduction(f);
if (f.down == ) cout << f.up;
else cout << f.up << "\\" << f.down;
}
string FraToString(Fraction f)//将分数转换为string类型
{
string result;
if (f.down == ) result = f.high;
else result = f.high + "\\" + f.low;
return result;
}

stack.cpp

 #include"head.h"
struct
{
char data[maxsize];//存放运算符
int top;//栈顶指针
}op;//定义运算符栈
void trans(string exp, char postexp[])//exp[]为算数表达式,postexp[]为后缀表达式
{
char ch;
int i = , j = ;//i作为exp的下标,j作为postexp的小标
op.top = -;
ch = exp[i];
i++;
while (ch != '\0')//exp表达式未扫描完时循环
{
switch (ch)
{
case'['://判定为左括号
{
op.top++;
op.data[op.top] = ch;
}break;
case']'://判定为右括号,此时将’[‘之前的运算符依次出栈并存放到postexp中
{
while (op.data[op.top] != '[')
{
postexp[j] = op.data[op.top];
j++;
op.top--;
}
op.top--;//将’[‘删除
}break;
case'+'://为’+‘或’-‘时,其优先级不大于栈顶的任何运算符,直到’]‘为止
case'-':
{
while (op.top != - && op.data[op.top] != '[')
{
postexp[j] = op.data[op.top];
j++;
op.top--;
}
op.top++;
op.data[op.top] = ch;
}break;
case'*'://为’*‘或’/’时,其优先级不大于栈顶为‘*’或‘/‘的优先级,直到’['
case'/':
{
while (op.top != - && op.data[op.top] != '[' && (op.data[op.top] == '*' || op.data[op.top] == '/'))
{
postexp[j] = op.data[op.top];
j++;
op.top--;
}
op.top++;
op.data[op.top] = ch;
}break;
case' ':break;//过滤掉空格
case'('://将分数当成一个整体放到postexp中
{
while (ch != ')')
{
postexp[j]=ch;
j++;
ch = exp[i];
i++;
}
postexp[j]=ch; j++;//将')'放到postexp中
}break;
default:
{
while (ch >= ''&&ch <= '')//判定为数字
{
postexp[j] = ch;
j++;
ch = exp[i];
i++;
}
i--;
postexp[j] = '#';//用#标示一个数值的结束
j++;
}
}
ch = exp[i];
i++;
}
while (op.top != -)//此时exp扫描完毕,栈不空时出栈并存放到postexp中
{
postexp[j] = op.data[op.top];
j++;
op.top--;
}
postexp[j] = '\0';//给postexp表达式添加结束标识
}
struct
{
Fraction data[maxsize];//存放数值
int top;//栈顶指针
}st;
Fraction compvalue(char postexp[])//计算后缀表达式的值
{
double d;
char ch;
int i = ;//postexp的下标
st.top = -;
ch = postexp[i];
i++;
while (ch != '\0')//postexp字符串未扫描完事完成循环
{
switch (ch)
{
case'+':
{
st.data[st.top - ] = add(st.data[st.top - ], st.data[st.top]);
st.top--;
}break;
case'-':
{
st.data[st.top - ] = minus1(st.data[st.top - ], st.data[st.top]);
st.top--;
}break;
case'*':
{
st.data[st.top - ] = multi(st.data[st.top - ], st.data[st.top]);
st.top--;
}break;
case'/':
{
st.data[st.top - ] = divide(st.data[st.top - ], st.data[st.top]);
st.top--;
}break;
case'(':
{
double high = , low = ;
ch = postexp[i]; i++;//删除‘(‘
while (ch != '\\')
{
high = * high + ch - '';
ch = postexp[i];
i++;
}
ch = postexp[i]; i++;//删除’\’
while (ch != ')')
{
low = * low + ch - '';
ch = postexp[i];
i++;
}
st.top++;
Fraction re = fraction(high, low);
st.data[st.top] = re;
}break;
default:
{
d = ;
while (ch >= ''&&ch <= '')//将数字字符转化为对应的数值存放到d中
{
d = * d + ch - '';
ch = postexp[i];
i++;
}
st.top++;
Fraction re = fraction(d, );
st.data[st.top] = re;
}
}
ch = postexp[i];
i++;
}
return st.data[st.top];
}

yunsuan.cpp

 #include"head.h"
int flag = ;
int suiji(int down, int up)//随机生成1至n的整数
{
int low = down, high = up;
if (flag)
{
flag = ;
srand((unsigned)time(NULL));//种子
}
int result = random(down, up);
return result; }
bool is_unique(string str, vector <string> s)//判断生成的运算式是否重复
{
int count = ;
for (int i = ; i < s.size(); i++)
{
if (str!=s[i])
{
count++;
}
else break;
}
bool flag0 = count == s.size() ? true : false;
return flag0;
}
void yunsuan(int time, int low, int high, int fl1, int fl2, int fl3)//根据参数要求生成四则运算式
{
int integer1, integer2;
int ch1, ch2, ch3, ch4;//switch语句的选项
char sign;//运算符号
int times = time;//题目数
vector <string> str;//str用来保存生成的题目
int right = , wrong = ;
for (int i = ; i <= times;)
{
int flag4 = ;//flag4用来标记运算式是否是刚开始生成
string first, second, cal;//四则运算的第一个运算数和第二个运算数
int number = suiji(, );//number为参与运算的参数个数
for (int j = ; j <= number;)
{
//-------------------------------------------------------------------------------------
if (fl1 == )//允许乘除发参与运算的情况
{
ch1 = suiji(, );//随机生成运算符号
switch (ch1)
{
case :sign = '+'; break;
case :sign = '-'; break;
case :sign = '*'; break;
case :sign = '/'; break;
default:cout << "有错误!" << endl; break;
}
}
else//不允许乘除法参与运算的情况
{
ch1 = suiji(, );//随机生成运算符号
switch (ch1)
{
case :sign = '+'; break;
case :sign = '-'; break;
default:cout << "有错误!" << endl; break;
}
}
//-------------------------------------------------------------------------------------
if (fl3 == )//允许真分数参与运算
{
ch2 = suiji(, );//四则运算题目的三种情况
switch (ch2)
{
case ://整数和整数
{
strstream si, so;
integer1 = suiji(low, high);
si << integer1; si >> first;
integer2 = suiji(low, high);
so << integer2; so >> second;
}break;
case ://整数和真分数
{
strstream ss;
integer1 = suiji(low, high);
ss << integer1; ss >> first;
Fraction f = reduction(fra(low, high));
second = "(" + f.high + "\\" + f.low + ")";
}break;
case ://真分数和真分数
{
Fraction f1 = reduction(fra(low, high));
Fraction f2 = reduction(fra(low, high));
first = "(" + f1.high + "\\" + f1.low + ")";
second = "(" + f2.high + "\\" + f2.low + ")";
}break;
default:cout << "有错误!" << endl; break;
}
}
else//不允许真分数参与运算
{
strstream si, so;
integer1 = suiji(low, high);
si << integer1; si >> first;
integer2 = suiji(low, high);
so << integer2; so >> second;
}
//-------------------------------------------------------------------------------------
if (fl2 == )//允许括号(【】)参与运算
{
ch4 = suiji(, );
switch (ch4)
{
case :
{
if (flag4 == )//flag4为1表示运算式还未生成前两个运算数
{
cal = first + sign + second;
flag4 = ;
}
else
{
cal = cal + sign + first;//将以生成的运算式个新生成的运算数连接起来
}
}break;
case :
{
if (flag4 == )
{
cal = second + sign + first;
flag4 = ;
}
else
{
cal = second + sign + cal;
}
}break;
case :
{
if (flag4 == )
{
cal = "[" + first + sign + second + "]";//添加括号【】的情况
flag4 = ;
}
else
{
cal = "[" + cal + sign + first + "]";
}
}break;
case :
{
if (flag4 == )
{
cal = "[" + second + sign + first + "]";
flag4 = ;
}
else
{
cal = "[" + second + sign + cal + "]";
}
}break;
default:cout << "有错误!" << endl; break;
}
}
else//不允许括号(【】)参与运算
{
ch4 = suiji(, );//输出的两种情况
switch (ch4)
{
case :
{
if (flag4 == )
{
cal = first + sign + second;
flag4 = ;
}
else
{
cal = cal + sign + first;
}
}break;
case :
{
if (flag4 == )
{
cal = second + sign + first;
flag4 = ;
}
else
{
cal = second + sign + cal;
}
}break;
default:cout << "有错误!" << endl; break;
}
}
j++;
}
//------------------------------------------------------------------------------
if (str.empty())//若sr为空,则将第一个生成的运算式添加到vector中
{
str.push_back(cal);
cout << "(" << i << ")." << cal << "="; string answer;
cin >> answer;
char postexp[maxsize];
trans(cal, postexp);
Fraction re = compvalue(postexp);
string result = FraToString(re);
if (answer == result)
{
cout << "正确!" << endl;
right++;
}
else
{
cout << "错误!,正确答案为:" << result << endl;
wrong++;
}
i++;
}
if (is_unique(cal, str))//判断生成的运算式和之前已经生成的运算式是否重复
{
str.push_back(cal);//将生成的运算式添加到str中
cout << "(" << i << ")." << cal << "=";
string answer;
cin >> answer;
char postexp[maxsize];
trans(cal, postexp);
Fraction re = compvalue(postexp);
string result = FraToString(re);
if (answer == result)
{
cout << "正确!" << endl;
right++; }
else
{
cout << "错误!,正确答案为:" << result << endl;
wrong++;
}
i++;
}
else {}
}
cout << "**********************************************************************************" << endl;
cout << "你做对了" << right << "道题,做错了" << wrong << "道题" << endl;
}

main.cpp

 #include"head.h"
int main()
{
cout << "请输入题目数(1~100):";
int times, down, up, flag1, flag2, flag3, flag4;
cin >> times;//times至题目数
cout << "请输入数值绝对值范围:";
cin >> down >> up;//[down,up]为运算数范围
cout << "是否允许乘除发参与运算(y/n):";
char yn1;
cin >> yn1;
yn1 == 'y' || yn1 == 'Y' ? flag1 = : flag1 = ;
cout << "是否允许括号([])参与运算(y/n):";
char yn2;
cin >> yn2;
yn2 == 'y' || yn2 == 'Y' ? flag2 = : flag2 = ;//flag2判断是否允许括号参与运算
cout << "是否允许真分数参与运算(y/n):";
char yn3;
cin >> yn3;
yn3 == 'y' || yn3 == 'Y' ? flag3 = : flag3 = ;//flag3判断是否允许真分数参与运算
cout << "**********************************************************************************" << endl;
yunsuan(times, down, up, flag1, flag2, flag3);
system("pause");
return ;
}

截图:

四则运算3+psp0

四则运算3+psp0

四则运算3+psp0

四则运算3+psp0

四则运算3+psp0

项目计划总结:

日期\任务 听课/时 编写程序/时 查阅资料/时 日总计/时
星期一 2 2   4
星期二   2   2
星期三   3 1 4
星期四 2 3   5
星期五   4   4
星期六   5  2 7
星期日        
周总计 4 19 3

26

时间记录日志:

日期 开始时间 结束时间 中断时间 净时间/分 活动 备注
3/14 14:00 15:50 10 100 听课 软件工程上课
  19:00 21:00   60 编写程序 作业
  21:00 21:30   30 阅读书籍 《构建之法》
3/15 19:00 21:00  20 90 查资料,编写程序 作业
3/16  15:00  16:30  15  90 编写程序  作业
   17:00  18:00    60  查阅资料和阅读构建之法  
   21:00  22::00   60   编写程序  作业
3/17 14:00 15:50  10 100 听课 软件工程上课
  18:30 22:10   50 查资料,编写程序 作业
3/18 16:20 18:30  10 120 编程  
  19:10 21:45   145 查阅资料+编程  
3/19 9:00 11:40   160 编程 作业
   12:20  15:00    160  调试程序  
   15:00        写博客  

缺陷日志:

日期 编号 缺陷内容 引入阶段 排除阶段 修复时间 修复缺陷
3月14日 1

如何计算运算

编写代码 思考、查资料 80+ 利用栈来实现
3月18日 2

如何识别真分

编写代码 思考、查资料 120+ 利用“(” 和 “)”来识别
上一篇:bzoj5164: 餐厅计划问题(三分+贪心)


下一篇:MVC3+EF4.1学习系列(二)-------基础的增删改查和持久对象的生命周期变化