四则运算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:主函数所在的头文件,主要功能是和用户进行交互。
工作照:

代码:
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 ;
}
截图:





项目计划总结:
| 日期\任务 | 听课/时 | 编写程序/时 | 查阅资料/时 | 日总计/时 | 
| 星期一 | 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+ | 利用“(” 和 “)”来识别 | 
四则运算3+psp0的更多相关文章
- 四则运算三+psp0级表格
		
一.题目 在四则运算二的基础上,选择一个方向进行拓展,我选择的是增加了答题模块 二.设计思路 1.在上次的基础上,增加了答题模块,每出现一道四则运算题目,便提醒输入结果,如果结果错误,就会提示错误 2 ...
 - 四则运算2+psp0级表格
		
四则运算2 一.题目和要求 题目:写一个能自动生成小学四则运算题目的程序,要求一次输出不少于30道,只能是整数100以内的四则运算(四则运算1升级版) 要求: 1.题目避免重复 2.可定制(数量/打印 ...
 - 四则运算2+psp0
		
程序要求: 1.题目避免重复 2.可定制(数量\打印方式) 3.可以一下控制参数 ① 是否有乘除法 ② 是否有括号(最多支持十个数参与运算) ③ 数值范围 ④加减有无负数 ⑤除法有无余数 分析:① 如 ...
 - 撰写一篇博客要求讲述四则运算2的设计思想,源程序代码、运行结果截图、编程总结分析,并按照PSP0级的要求记录开发过程中的时间记录日志。
		
一.撰写一篇博客要求讲述四则运算2的设计思想,源程序代码.运行结果截图.编程总结分析,并按照PSP0级的要求记录开发过程中的时间记录日志. 1.设计思想: ①创建test.jsp建立第一个前端界面,提 ...
 - 四则运算2及PSP0设计项目计划
		
时间比较紧,我简单写写我的设计思路: 题目在四则运算1的基础上控制产生题目的数量,这个可以用变量控制:打印方式也可选用变量控制,程序的关键是括号的生成.我们可以将整个四则运算式看成()+()的模型,然 ...
 - 四则运算2及psp0设计
		
随机生成运算式,要求: 1.题目避免重复. 2.可定制(数量/打印方式). 3.可以控制一下参数. 要求:是否有乘除法,是否有括号,数值范围,加减有无负数,除法有无余数. 刚开始看到这样一个题目感觉还 ...
 - 软件工程课后作业——四则运算Ⅲ(C++)
		
一.设计思路 题目:可以答题并判断对错,最后显示做对几道题. 在原有的基础上,又拓展了答题模块. 在结构体中添加了answer属性,把输入的答案与正确答案比较,若相等则计数加一. 二.源代码 (1)四 ...
 - 软件工程随堂小作业——随机四则运算Ⅱ(C++)
		
一.设计思路 设计思路已给出,此处不再赘述. 二.源代码 (1)四则运算2.cpp(源文件) // 四则运算2.cpp : Defines the entry point for the consol ...
 - 软件工程——四则运算3(C#)
		
一.设计思想 设计两个窗体,在第一个窗体中选择功能参数,在第二个窗体中显示所出题目. 二.源代码 Form1.cs: using System; using System.Collections.Ge ...
 
随机推荐
- Ubuntu 16 Java Develop环境快速搭建
			
安装JDK 1. 更新apt-get: $ sudo apt-get update 2. 安装jdk: $ sudo apt-get install openjdk-8-jdk 部分eclipse现只 ...
 - [示例] Firemonkey TreeView 父项勾选子项连动
			
效果: 代码: procedure TForm1.TreeView1ChangeCheck(Sender: TObject); var i: Integer; t: TTreeViewItem; be ...
 - Docker集群部署SpringCloud应用
			
整体架构 docker环境准备 # linux下的安装,自行百度 # windows docker toolbox下载地址 https://download.docker.com/win/stable ...
 - 批量删除C#注释
			
批量删除C#注释(适用于vs开发环境) 方法: 第一步:使用Ctrl+H快捷键,打开查询替换窗口 第二步:在‘查找选项’中,勾选‘使用’‘正则表达式’ 第三步:在‘查找内容’中,填写正则表达式[\t] ...
 - P145MathTool测试类的编写
			
如果我们在方法的自变量个数事先无法决定如何处理,比如: System.out.printf("%d",10); System.out.printf("%d %d" ...
 - C语言 迭代部分的代码编写
			
C语言代码学习 迭代部分 迭代要用到函数部分的知识,一开始我写了计算n!的计算,代码和运行结果如下: 结果只能单一的计算出整数内的值,如果输入负值则结果为返回值1,显然是不对的,根据查书学习以后,知道 ...
 - 20155321 2016-2017-2 《Java程序设计》第四周学习总结
			
20155321 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 第六.七章 继承 多态 接口 相应的语法细节 继承 关键字 extends 格式 class ...
 - Win SERVER 2008 许可证激活失败,系统重启问题
			
服务器系统win server2008 R2 SP1,频繁重启,查看日志 有显示 许可证激活(slui.exe)失败,错误代码如下:0x800401F9 和 Windows 许可证激活失败.错误 0x ...
 - Lite OS学习之事件EVENT
			
1. Lite OS的事件EVENT,就是一个任务向另外一个任务通知事件的,不能数据传输.看下有的函数,实际比较复杂 2. 具体还是看编程,先全局结构体整个事件变量 /*事件控制结构体*/ EVENT ...
 - LAUNCHXL-28379D入门学习-第一篇
			
1. 首先安装controlSUITE或者C2000ware软件,TI官网下载,安装后包括C2000的函数库和例程之类的,还可以和CCS搭配使用.controlSUITE安装完之后大约4个G,所以我安 ...