Vc++课程设计报告
题目名称:四则运算
班级:测控技术与仪器
姓名:***
学号:************
一、程序功能简介
该程序用字符串形式接受一个带括号的四则运算表达式,然后按照四则运算优先级的算法先括号,后乘方、乘除、加减这样的顺序将这个算式解出。
该程序的设计比较巧妙,是在主程序中反复查最后一对括号,将其中的结果计算出来,去掉括号,这样的过程持续下去,最后导致所有的括号都去除,解出算式。
二、课程设计要求
(1)用类的要求改写程序,将数据和函数封装到类中。
(2)修改主程序,使程序可以反复运算,直到选择退出为止。
(3)扩充程序功能,使程序适合浮点数运算。
(4)增加程序的判断功能,当有非法的输入时(如字母等),给出提示信息并退出运算,当输入带有空格时,能将空格滤除。
三、程序设计思想
(1)类的封装
实际上该字符串类基本类似于c++中的string类,比string类多定义了浮点数与字符串的相互转换的函数,输入输出友元函数,可以从string类派生出CStr类,这样,类的定义就更加简单,且可以利用很多现成的成员函数。
(2)主程序结构算法的设置
定义char类型的变量用来存储字符串,定义CStr类用于对字符串操作函数的引用。
先对输入字符串用Judge函数进行输入正确性的判断及取出空格内容;
然后用charinstr函数在字符串中反复查最后一对括号;
用midstr函数提取出来,用calculate函数进行计算;
并用left函数与right函数及addstrings函数将所到这对括号的左边、右边及运算结果以字符串的形式合并成一个新的字符串;
重复上述操作直至字符串中不再有括号;
最后用calculate函数进行最后的计算返回计算结果。
紧接着进行是否退出计算的输入判断,完成程序反复运算的功能。
四、详细设计
判断功能:用类中定义的judge函数实现,返回值为1即合法,为0即不合法。
      去除空格:定义p、s两个指针指向字符串,r指针指向p指针实现p、s指针在字符串中的
遍历,用p指针到第一处空格处,再用s指针到p指向位置以后最近一个不是空格处,赋值语句*p=*s,继续向下遍历字符串直至结束。
      非法输入:定义destination指向字符串,列举算式中出现的合法的字符,通过遍历字符串到非法输入字符,返回0;
      非法算式逻辑:包括运算符号相连,以及违背运算法则等现象,通过对运算符号的遍历比较实现;还有包括左括号前或右括号后紧挨数字,通过定义一个新字符串数组指向字符串来寻括号并判断括号前后是否合法;非法,返回0;
      全都合法返回1.
数字字符串转换成数字:用类中定义的val函数实现,扩充到浮点数的运算范围。
      定义char类型的source指针指向字符串,用charinstr函数寻字符串中小数点位置,以此判断整数还是浮点数,如果整数即用10的相应位数的乘方来乘以相应字符位置字符的数字,并进行累加,最后返回result;如果是浮点数,则分为整数与小数部分依次进行计算,整数同上,小数部分则用相应字符位置字符所代表的数字除以10的相应位数的乘方,并进行
累加,最后将整数小数部分的和返回result。
字符串的连接,通过类中定义的left、right、midstr、addstrings函数配合实现。
      通过left、right、midstr三个函数进行字符串的提取,addstrtings函数进行三个指针的遍历实现两个字符串的合并。
数字的字符串化,通过类中定义的str函数实现。
      类比val函数一样区分整数与浮点数,将数字的每一个数字单个提取出来通过与字符‘0’的比较转化为相应字符复制给递增的指针。
算式的计算,通过类中定义的calculate函数实现。
        依次按照^*/+-的顺序用charinstr函数寻运算符号,并用相应函数进行字符串与数字之间的转换,以及新的字符串的合并,返回计算结果。
友元函数的定义,定义输入输出友元函数,重载赋值运算符等,实现字符串之间的加法。
五、程序调试的过程
      出现问题:
开始编写完整个程序,出现许多编写错误,一个个改正;
          在实现浮点数的扩充过程中的小数部分,以及输入合法性的判断过程漏掉情况,指针的误用等;
          有时单独的一个函数不能搞懂或错误不能改正,就单独在编写一个类似程序,多次调试运行,来弄懂并加以改正;
解决办法:查阅书籍,上网搜索,独立思考,询问同学老师,多次上机调试等;
六、输入输出数据
开始界面:
非法输入判断:
  非法字母:运算符紧挨:
  括号前或右括号后为数字:
  括号为中文符号:
清理空格:
运算第一个输入字符串算式结果:
退出判断:继续运算:
退出运算:
浮点数的加入:
七、课程设计总结
        经过这次庞大复杂的课程设计过程,是我对c++知识有了更加深刻的理解,引起了我对c++语言世界的无限好奇心和探索欲,感慨到了世界的神奇与微妙,程序控制的无限用途以及自身的渺小;
        在其中编写判断括号前后是否合法语句时,指针遍历不易实现,于是经过多次调试后重新定义了一个字符串数组来实现,这给了我很大的启示,只要努力并不断尝试新的东西一定会成功;
还有程序中友元函数与运算符重载部分,由于知识掌握不够牢固,反复调试查阅书籍,最终得到了解决,也使得我对这方面的知识获得了更为深刻的理解与认知;
浮点数的加入要进行小数点数位的取舍,函数中设定为小数点儿后六位,因此浮点数运算过程中每次都会出现六位小数的现象,使得结果有0.000001的误差,通过单独编写类似函数多次调试,使得我对c++语言中对double型向int型变量转化的规律的理解获得了更深层次的理解;
通过编写过程,体会到了细节的厉害,有时一个微小的错误就能使整个程序而不能正确运行;
八、源程序注解
#include<iostream.h>
#include<string.h>
#include<stdlib.h>
    char pause;
int len(char*source)    //算出字符串的长素
{  int retval=0;   
    while(*(source+retval++)!=0){}
字符串长度算不算空格
    return --retval;
}
class CStr    //定义字符串类
private:
    int nlen;    //字符串长度 
    char *pstr;    //字符串首地址
public:
    CStr(){};
    CStr(char *str) {nlen=len(str);pstr=str;}
    int Getlen(){return nlen;}        //返回字符串长度
    char*Getstr(){return pstr;}        //返回字符串首地址
    CStr(CStr&str){nlen=str.Getlen();pstr=str.Getstr();}    //拷贝构造函数
    char*Getpstr(){return pstr;}
    void midstr(CStr & str1,int start,int length);        /*返回指定字符串类中从nStart序号开始nLength长度的字符*/ 
    void left(CStr & str1,int length);        /*返回指定字符串中从左边开始nLength个字符*/   
    void right(CStr & str1,int length);        /*返回指定字符串中从右边开始nLength个字符*/
 
    calculate();    //计算该字符串所代表的四则运算的值(内无括号)
    friend int charinstr(char);        //友元函数,判断字符是否在字符串中
    double val();        //求字符串代表的数字字符的数值
    str(double val);        //将数值表示成字符串的形式 
    friend istream &operator>>(istream &,CStr &);        //重载输入运算符
    int Judge();    //判断输入是否合法,滤除空格
};
void CStr::left(CStr & str1,int length)        //从参数指向的地址左边取Length个字符赋给目的字符串
{    char*destination=pstr;
    char *source=str1.Getstr();
    *(destination+--length+1)=0;    //目的字符串以0 结尾 
    while(length>=0)    //赋值Length个字符
    {    *(destination+length)=*(source+length--);  }
}
void CStr::midstr(CStr & str1,int start,int length)        //从参数指向的地址处从start位置开始取length个字符赋给目的字符串
{    char *source=str1.Getstr();
    source+=start-1;    //开始赋值处的地址
    char*destination=pstr;
    *(destination+--length+1)=0;    //目的字符串以0 结尾
    while(length>=0)    //赋值Length个字符
    {    *(destination+length)=*(source+length--);  }
}
void CStr::right(CStr & str1,int length)        //从参数指向的地址右边取Length个字符赋给目的字符串
{    char *source=str1.Getstr();
    while(*source!=0){  source++; }        //移至字符串尾部
    char*destination=pstr;
    source-=length;        //跳至欲赋值的首地址
    *(destination+--length+1)=0;        //目的字符串以0 结尾
    while(length>=0)    //赋值Length个字符
    {  *(destination+length)=*(source+length--); }
}
int charinstr( char *destination,char char_to_find)        //判断字符串char_to_find是否在目的字符串中,若在,返回其所在位置,若不再返回0

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。