《面向对象程序设计》——寒假作业3

《面向对象程序设计》——寒假作业3

1.合作者

林燊 031602325 https://www.cnblogs.com/linshen/

卢泽明 031602328 http://www.cnblogs.com/luzeming/

github连接:https://github.com/Travaill/arithmetic.git

2.设计思路

3.程序功能

  • 能对0--10之间的整数进行四则运算(加减乘除)

  • 能实现选择中文和英文两种语言

  • 程序能接收用户输入的整数答案,并判断对错

  • 程序结束时,统计出答对、答错的题目数量

4.算法分析

  • 类generate 实现随机算式的生成
  • 类calculate 计算算式的结果
  • 类control 控制题目生成的数量 控制生成符合要求的算式 控制程序的退出 控制程序的语言
  • 类printf 输出算式、判断结果、统计答题情况

5.代码规范

  • 函数的命名必须使用英文单词,不使用拼音缩写
  • 函数的命名如果一个单词的必须首字母大写,如果多个单词的用下划线隔开
  • 程序结构清析,简单易懂,单个函数的程序行数不得超过100行。
  • 要随意定义全局变量,尽量使用局部变量。
  • 函数的旁边必须注释上本函数的功能
  • 禁止GOTO语句。

6.代码展示

代码部分较长,所以仅截取程序最为核心的部分

随机生成表达式

#include "generate.h"
#include <iostream>
#include <stdlib.h>
#include <time.h> 
#include <string>
#include <sstream>
#include <string.h>
using namespace std;
int Generate::generate_rand(int low,int high)  //生成[low,high]随机数 
{
	return (rand()% (high - low+1) + low);
}  

string Generate::generate_operator(void)     //生成四则运算符 
{
	string ope;
    switch(generate_rand(1,4)) 
    {
    	case 1:ope='+'; break;
    	case 2:ope='-'; break;
    	case 3:ope='*'; break;
    	case 4:ope='/'; break;
	}
	return ope;
}

string Generate::generate_polynomial(void)  //生成多项式 
{
	int a,b,c;
    stringstream ss;
	a=generate_rand(0,10);    
    b=generate_rand(0,10);
    c=generate_rand(1,3);  
   if(c==1) 
  {
  	ss << '(' << a<<generate_operator()<<b<<')';
  } 
    if(c==2)
  {
    ss<<a<< generate_operator()<<b;
  }
    if(c==3)	
  {
	ss<<a;
  }
  	string str = ss.str();  
  	ss.str("");
    return str;
}

string Generate::generate_formula(void)     //生成算式 
{
	stringstream ss;
	ss<<generate_polynomial();
	for(int i=1;i<generate_rand(2,4);i++)
	{
		ss<<generate_operator()<<generate_polynomial();
	}
	string str = ss.str();  
	ss.str("");
    return str;
}

计算表达式结果

#include "calculate.h"
#include "generate.h"
#include <iostream>
#include <stdlib.h>
#include <string>
#include <stack>
using namespace std;
stack<double> num_stk;
stack<char> ope_stk;
void Calculate::calculate_polynomial()      //计算多项式结果 
{
	char ope=ope_stk.top();
    double a,b,res;
    b=num_stk.top();
    num_stk.pop();
    a=num_stk.top();
    num_stk.pop();
    switch(ope)
    {
        case '+':res=a+b; break;
        case '-':res=a-b; break;
        case '*':res=a*b; break;
        case '/':res=a/b; break;
        default: break;
    }
    num_stk.push(res);
    ope_stk.pop();
}

int Calculate::Rank(char x)                //计算优先级 
{
    if(x=='(')
        return 0;
    else if(x=='+')
        return 1;
    else if(x=='-')
        return 2;
    else if(x=='*')
        return 3;
    else if(x=='/')
        return 4;
}

double Calculate::calculate_formula(string str)     //计算算式 
{
	
	int x=0;
	int  num_flag=0;
	for(int i=0;i<str.size();i++)
	{
        if((str[i]>='0')&&(str[i]<='9'))
		{
            x=x*10+str[i]-'0';
            num_flag=1;
            if(i==str.size()-1)
            num_stk.push(x);
        }
        else{
            if(x)
			{
                num_stk.push(x);
                x=0;
                num_flag=0;
            }
            if(ope_stk.empty())
                ope_stk.push(str[i]);
            else if(str[i]=='(')
                ope_stk.push(str[i]);
            else if(str[i]==')')
            {
                while(ope_stk.top()!='(')
                    calculate_polynomial();                
                    ope_stk.pop();
            }
            else if((Rank(str[i]))<=Rank(ope_stk.top()))
            {
                calculate_polynomial();
                ope_stk.push(str[i]);
            }
            else
			{
                ope_stk.push(str[i]);
            }
        }
    }
    while(!ope_stk.empty())
    calculate_polynomial();
    double res=num_stk.top();
    return res;
}

过滤不符合要求的表达式

string Control::judge_formula(void)               //生成的算式是否合法 
{
	string str=Generate().generate_formula();
	char ptr[35];
    strcpy(ptr,str.c_str()); 
	const char *substr1="/0";
	const char *substr2="/(1-1)";
	const char *substr3="/(2-2)";
	const char *substr4="/(3-3)";
	const char *substr5="/(4-4)";
	const char *substr6="/(5-5)";
	const char *substr7="/(6-6)";
	const char *substr8="/(7-7)";
	const char *substr9="/(8-8)";
	const char *substr10="/(9-9)";
	const char *substr11="/(10-10)";
	const char *substr12="0*";
	const char *substr13="0/";
    char *s1 = strstr(ptr, substr1);
    char *s2 = strstr(ptr, substr2);
    char *s3 = strstr(ptr, substr3);
    char *s4 = strstr(ptr, substr4);
    char *s5 = strstr(ptr, substr5);
    char *s6 = strstr(ptr, substr6);
    char *s7 = strstr(ptr, substr7);
    char *s8 = strstr(ptr, substr8);
    char *s9 = strstr(ptr, substr9);
    char *s10 = strstr(ptr, substr10);
    char *s11 = strstr(ptr, substr11);
    char *s12 = strstr(ptr, substr12);
    char *s13 = strstr(ptr, substr13);
     if(s1==NULL&&s2==NULL&&s3==NULL&&s4==NULL&&s5==NULL&&s6==NULL&&s7==NULL&&s8==NULL&&s9==NULL&&s10==NULL&&s11==NULL&&s12==NULL&&s13==NULL)
     {
     	return str;
	 }
	 else
	 {
	 	return judge_formula();
	 }
    
}
string Control::judge_result(void)          //判断结果是否为整数  
{
  	string str=Control().judge_formula();
  	double res=Calculate().calculate_formula(str);
  	if((int)res==res)
  	{
  		return str;
	}
	else
	{
		return Control().judge_result();
	}
}

7.合作证明

8.程序测试结果

9.个人感受

此次的作业对于我一个刚接触C++来说的人确实挑战挺大,刚开始的几天还在看视频学习C++,后面开始动手写程序的时候,我们先建立了一个大概的思路,发现计算算式的结果是最为复杂的一个部分,所以我们的分工就是,一个人负责算式计算的实现,另一个人负责算式生成和检验,控制语言等等.

那么刚开始我不知道如何用类的写我的代码,所以就把所有的函数写在一个CPP文件中,直到我想要的功能全部都能实现的时候,便思考着如何去把这个程序,转变为面对对象的思想.也请教了很多人,阅读了很多资料.现在这里感谢那些帮助我很多的人,感谢畅畅和燊哥还有齐老大等等...

先从程序本身的功能开始说起就有很多值得为记录的东西

随机数生成

首先就是这个随机数生成的办法,使用rand()函数来生成随机数,那么想要生成[low,high]的随机数有一个公式rand()% (high - low+1) + low

其次便是要使用srand((unsigned)time(NULL));以及头文件 < time.h >将系统的时间作为种子,才能保证随机数是真的随机生成

string的应用

C++和C语言相比多了一个string的类型,头文件为 < string >,让我们对字符串的操作更加的方便。比如说我们string str=“HELLO”,那么str[0]就为"H"

stringstream的应用

当我用随机数的办法生成随机的表达式的时候,我能够随机生成的只是一个多项式而已,那么如何把他们连接起来变成一个算式呢?

这个问题困扰了我很久,后来找到了stringstream这个东西,头文件为

< sstream > 通过使用stringstream,创造了一个临时的数据流,可以让我使用非常简单的语法,例如 :

stringstream ss

ss << '(' << a<<generate_operator()<<b<<')';

通过这样就可以把这些字符串连接在一起了,不过要提醒大家的是,由于这只是一个临时的字符串操作完要返回的时候,不能直接返回,要通过string str=ss.str()的方式存储,然后使用ss.str("")来清空,不然很容易发生数据的错误,最后return str

判断生成的算式是否符合要求

刚开始使用的是string自带的find(substr,pos)函数,可是find的函数的使用机制是在源串中从位置pos起往后查找,只要在源串中遇到一个字符,该字符与目标串中任意一个字符相同,就停止查找,返回该字符在源串中的位置;若匹配失败,返回npos。

那么后来通过网上资料的查找,找到了C语言< string.h >库中的,strstr(str,substr)这个函数是非常严格的查找,如果没有找到则返回NULL,使用这个函数就满足了我的需求

面对对象的思想

在上述的难题都解决了之后,我就开始思考,如何将这个程序转变为面对对象的思想,首先我思考整个程序的结构,将程序按功能分为两个大类,一个是对象,一个控制,对象是生成我所需要,而控制类是控制整个程序

比如说输入数值来控制我所需要的题目的量,输入E控制程序结束,这都是属于一个大类中的。

再说到对象类,对象中,按照功能,我分为了三个类,一个是生成,一个是计算,一个是输出。

多个文件引用

在头文件也就是.h的文件中,使用class来定义类,可以简单的理解为,需要和其他类进行变量的传递的就写在public中,只是在类中进行操作的就可以写在private中.

同时然后.h写完之后需要有一个.cpp的实现文件,在实现文件中函数名应该加上类::才能被调用.

例如 在Control类中,我写函数应该是 void Control::chosse(void)

如有不同意见欢迎在我的博客下面评论指出!

原文地址:https://www.cnblogs.com/linshen/p/6413718.html