题目要求:

  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的更多相关文章

  1. 四则运算三+psp0级表格

    一.题目 在四则运算二的基础上,选择一个方向进行拓展,我选择的是增加了答题模块 二.设计思路 1.在上次的基础上,增加了答题模块,每出现一道四则运算题目,便提醒输入结果,如果结果错误,就会提示错误 2 ...

  2. 四则运算2+psp0级表格

    四则运算2 一.题目和要求 题目:写一个能自动生成小学四则运算题目的程序,要求一次输出不少于30道,只能是整数100以内的四则运算(四则运算1升级版) 要求: 1.题目避免重复 2.可定制(数量/打印 ...

  3. 四则运算2+psp0

    程序要求: 1.题目避免重复 2.可定制(数量\打印方式) 3.可以一下控制参数 ① 是否有乘除法 ② 是否有括号(最多支持十个数参与运算) ③ 数值范围 ④加减有无负数 ⑤除法有无余数 分析:① 如 ...

  4. 撰写一篇博客要求讲述四则运算2的设计思想,源程序代码、运行结果截图、编程总结分析,并按照PSP0级的要求记录开发过程中的时间记录日志。

    一.撰写一篇博客要求讲述四则运算2的设计思想,源程序代码.运行结果截图.编程总结分析,并按照PSP0级的要求记录开发过程中的时间记录日志. 1.设计思想: ①创建test.jsp建立第一个前端界面,提 ...

  5. 四则运算2及PSP0设计项目计划

    时间比较紧,我简单写写我的设计思路: 题目在四则运算1的基础上控制产生题目的数量,这个可以用变量控制:打印方式也可选用变量控制,程序的关键是括号的生成.我们可以将整个四则运算式看成()+()的模型,然 ...

  6. 四则运算2及psp0设计

    随机生成运算式,要求: 1.题目避免重复. 2.可定制(数量/打印方式). 3.可以控制一下参数. 要求:是否有乘除法,是否有括号,数值范围,加减有无负数,除法有无余数. 刚开始看到这样一个题目感觉还 ...

  7. 软件工程课后作业——四则运算Ⅲ(C++)

    一.设计思路 题目:可以答题并判断对错,最后显示做对几道题. 在原有的基础上,又拓展了答题模块. 在结构体中添加了answer属性,把输入的答案与正确答案比较,若相等则计数加一. 二.源代码 (1)四 ...

  8. 软件工程随堂小作业——随机四则运算Ⅱ(C++)

    一.设计思路 设计思路已给出,此处不再赘述. 二.源代码 (1)四则运算2.cpp(源文件) // 四则运算2.cpp : Defines the entry point for the consol ...

  9. 软件工程——四则运算3(C#)

    一.设计思想 设计两个窗体,在第一个窗体中选择功能参数,在第二个窗体中显示所出题目. 二.源代码 Form1.cs: using System; using System.Collections.Ge ...

随机推荐

  1. Promise 的应用

    Promise 有三种状态,进行中(pending),已成功(fulfilled),已失败(rejected): 一旦状态改变,就不会再变,任何时候都可以得到这个结果.Promise对象的状态改变,只 ...

  2. 前端基础-HTTP协议

    一. HTTP协议简介 二. HTTP协议之请求Request 三. HTTP协议之响应Response 四. HTTP协议完整工作流程 五. HTTP协议关键性总结 六.自定义套接字分析HTTP协议 ...

  3. EDID的简介和解析

    去年对EDID做了一个解析,下面是学习EDID过程中整理的资料. 一.EDID简介 EDID: Extended Display Identification Data (外部显示设备标识数据)--- ...

  4. Python学习 :面向对象 -- 类的成员

    类的成员 一.字段 - 字段可以分为'普通字段'和'静态字段'两种 - 普通字段(保存在对象中,执行时只能通过对象来进行访问) - 静态字段(保存在类中,在内存中只保存一份数据(可以有效地节约内存的空 ...

  5. ruby安装devkit

    双击下载文件,指定解压路径,路径中不能有空格.如C:\DevKit,这个路径就是<DEVKIT_INSTALL_DIR>. > cd <DEVKIT_INSTALL_DIR&g ...

  6. web安全入门笔记

    0x01 前言 这正邪两字,原本难分. 正派弟子若是心术不正,便是邪徒. 邪派中人只要一心向善,便是正人君子. 0x01 信息安全的定义 信息安全,意为保护信息及信息系统免受未经授权的进入.使用.披露 ...

  7. 使用maven将GitHub上项目打包作为依赖添加

    Clone GitHub项目 git clone https://github.com/LeeKemp/UserAgentParser 将项目打成jar包,安装到maven仓库中 D:\Github ...

  8. Enable CSS active pseudo styles in Mobile Safari

    http://alxgbsn.co.uk/2011/10/17/enable-css-active-pseudo-styles-in-mobile-safari/ document.addEventL ...

  9. cgywin下 hadoop运行 问题

    1 cgywin下安装hadoop需要配置JAVA_home变量 ,  此时使用 window下安装的jdk就可以  ,但是安装路径不要带有空格.否则会不识别. 2  在Window下启动Hadoop ...

  10. 20155229 2016-2017-2 《Java程序设计》第十周学习总结

    20155229 2016-2017-2 <Java程序设计>第十周学习总结 教材学习内容总结 网络 网络分为局域网.广域网.城域网 一次HTTP请求包含3个部分:①方法--统一资源标识符 ...