本程序的设计过程主要从4个部分来说明,分别是头文件部分,也就是数据成员设计;String类的成员函数设计部分;String类的操作符重写部分以及主函数效果呈现部分,以下依次从这4个部分来介绍String类的设计过程。
(1)头文件部分:
头文件中声明了本类的数据成员主要由两部分组成,分别是char类型指针变量str和整型变量length。其中char类型指针变量str用于存储String类型变量所对应的字符串,使用时为char类型指针变量str分配空间,之后再将字符串的值进行存入。而整型变量length则在每次生成String类时存储自动计算出的字符串长度,以便进行之后的各种操作,就不再需要每一次都计算出长度了,因为长度本来就是String类的一部分,可以直接进行使用。
另外,头文件中还声明了之后所需设计的成员函数(除了构造函数、拷贝构造函数和析构函数之外,还需要设置字符串长度函数LenString、小写转换函数LwrString和大写转换函数UprString)以及所需要重写的操作符(分别是operator+、operator=、operator>、operator<、operator==、operator <<和operator >>)。
(2)String类的成员函数设计部分:
首先是构造函数的设计,定义无参构造函数,当创建String类型的实体时,如果不传参数时,就将该String类型实体的字符串指针属性str定义为空,并将长度属性length的初值设置为0。定义一个有参构造函数,当创建String类型的实体时传入参数一个字符串时,对传入的字符串进行遍历,每次循环的过程中增加长度变量length,当遍历到最后的\0时,停止遍历,也就求出了字符串的长度;利用之前得到的字符串长度为字符串指针属性str分配地址空间,再通过一次遍历,将传入字符串的值赋值给str,也就完成了有参构造函数的调用。以下为有参构造函数的程序:
之后是拷贝构造函数的编写,拷贝构造函数主要将传入的const类型String类实体的长度以及字符串指针属性str指向的字符串值拷贝给当前String类,用于复制新对象。析构函数编写的主要目的是在对象使用完之后,如果为对象分配过空间,则释放掉之前为该对象分配的空间,以达到节省空间的效果。以下为拷贝构造函数的程序:
最后是功能函数,先是用于求字符串长度的LenString函数,由于之前在构造函数中已经将字符串的长度值求出,并且放入整型变量length当中,因此在这个函数中也就不必再次计算字符串长度,直接将所需求长度的String变量所对应的length值返回即可,在调用时同样需要用一个整型变量来接收。
小写转换函数LwrString中需要输入一个String类型变量作为参数,在函数中需要先定义一个输出的String变量,将需要转换的String类型变量的length属性赋值给输出变量,并为其分配空间;再进行循环,每次循环进行判断,若所需转换字符串循环到的字符值大于97,也就是值为小写字母,则不再进行转换,直接将该字符赋值给输出变量,若所需转换字符串循环到的字符值小于等于97,则将大写字母的ascii码值增加32,转换成小写字母。
大写转换函数UprString中同样需要输入一个String类型变量作为参数,在函数中需要先定义一个输出的String变量,将需要转换的String类型变量的length属性赋值给输出变量,并为其分配空间;再进行循环,每次循环进行判断,如果所需转换字符串循环到的字符值小于91,也就是值为大写字母,则不再进行转换,直接将该字符赋值给输出变量,若所需转换字符串循环到的字符值大于等于91,则将小写字母的ascii码值减少32,转换成大写字母。
图1 LwrString运行流程图
(3)String类的操作符重写部分:
在操作符重写部分首先需要重写连接操作符operator+,首先需要将前一段String类型变量的长度和后一段String类型变量的长度相加赋给新定义String类型变量的length属性,并通过得到的length属性为新定义String变量分配空间。再进行两轮循环,第一轮循环是将前一段String类型变量的值依次赋值给新定义String变量;第二轮循环则是在前一轮循环的基础上将后一段String类型变量的值依次赋值给新定义String变量的后半部分,即可实现字符串的连接。
图2 连接操作符运行流程图
重写赋值操作符operator=时,需要将原String变量的length属性赋值给被赋值的String类型变量,并通过该length属性为被赋值的String类型变量分配地址空间。在进行循环,将原String变量str属性中的每一位字符赋值给被赋值的String类型变量,最后返回被赋值的String类型变量就实现了字符串赋值的功能。
图3 赋值操作符运行流程图
重写比较操作符operator>、operator<和operator==都比较类似,这里只介绍字符串大于比较符operator>,首先比较前一个String变量和后一个String变量的length属性,如果前一个String变量的length属性大于后一个String变量的length属性,则直接将用于保存结果的变量result置为1,表示前一个字符串大于后一个字符串;反之则将result置为-1,表示前一个字符串小于后一个字符串。若两个String变量的length属性相等,则进行循环,对每一位进行比较,若循环到前一个字符串的对应字符大于后一个字符串的,则将result置为1;若循环到前一个字符串的对应字符小于后一个字符串的,则将result置为-1;若循环到了最后也没有比出大小,则直接返回result等于0。
图4 大于比较操作符运行流程图
重写输出流操作符operator<<时,首先取出需输出字符串的length值,再利用该length值通过循环,将需输出字符串中的每一位字符进行输出,最后返回输出流对象以便进行连续输出。
图5 输出流操作符运行流程图
重写输入流操作符operator >>时,需要动态分配空间,首先将需输入字符串的length值置为-1,并为该字符串分配一个length+1长度的空间。通过输入流的get函数获取输入流中的单个字符,并对该单个字符进行判断,如果这个字符不为回车,则将length值自增1,并用一个临时指针指向原来存储的String变量的地址。为该字符串新分配一个length+1长度的空间,并通过循环将临时指针指向地址的字符串值赋给新分配空间的字符串,同时把从输入流中获取到的单个字符连接在新字符串尾部;最后再次通过输入流的get函数获取输入流中的下一个字符,并对该单个字符进行判断,一直到获取到的字符为回车时,则退出循环,从而就达到了输入流的效果。
图6 输入流操作符运行流程图
(4)主函数效果呈现部分:
主函数部分主要是用于显示String类的效果,首先需要调用system函数修改界面的宽高和颜色,然后用while(1)无限循环列表,输入选项,若输入1则提示输入大写字母,并将其转换成小写字母;若输入2则提示输入小写字母,并将其转换成大写字母;若输入3则提示输入任意字符串,同时调用长度计算函数计算输入的字符串长度;若输入4则提示输入两个字符串,则运用操作符+进行连接后赋值给另一字符串并输出;若输入5则提示输入任意字符串,并将其赋值给另一个字符串,最后输出;若输入6则提示输入两个字符串,运用操作符>对两个字符串进行比较,大于是返回1,等于时返回0,小于时返回-1;若输入7则提示输入两个字符串,运用操作符<对两个字符串进行比较,小于是返回1,等于时返回0,大于时返回-1;若输入8则提示输入两个字符串,运用操作符==对两个字符串进行比较,等于时返回1,大于或小于时返回-1;若输入9则任意输出一个String类型变量,用于检测输出流能否被正常使用;若输入10则提示输入一个字符串,并进行输出验证,用于检测输入流能否被正常使用。
图7 主函数运行流程图