定义一个集合类setColour,要求元素为枚举类型值
目录
题目
前言
集合的实现的两种方法:
枚举类型:
方式一
总体实现原理
各函数实现
构造函数
拷贝构造函数和赋值运算符重载
“>>”的 重载
“<<”的重载
集合运算符重载
总体实现代码
方式二
总体实现原理
各函数实现
“>>”的 重载
“<<”的重载
集合运算符重载
总体实现代码
测试主函数
测试用例与结果
题目
定义一个集合类setColour,要求元素为枚举类型值。例如,
enum colour { red, yellow, blue, white, black };
集合类实现交、并、差、属于、蕴含、输入、输出等各种基本运算。设计main函数测试setColour类的功能。
前言
集合的实现的两种方法:
1.用bool数组每个数组元素存储一种集合元素
2.用一个unsigned int存储,每一个二进制位代表一个集合元素
从实现上,方法一更好理解,但无论是从时间角度、空间角度还是代码量(行数足足有二倍之差)方法二都有明显优势。
下文将分别对两种方法进行讲解,除集合的实现原理不同,在方式二的实现过程中,还进行了实现方式的优化和代码拓展性的延申,可以在宏变量增加元素。
枚举类型:
在枚举类型中,共五种颜色,若不进行初始化,其默认从0开始向后累加1,如下测试:
方式一
总体实现原理
1.我们定义一个bool型数组作为成员变量,长度为4,每个位置作为以一种颜色,此颜色在集合中,就置1,否则为0,如下:
2.接下来,各种集合运算就可以通过遍历数组,对每一个元素进行逻辑运算操作而实现。
各函数实现
class setColour
{
public:setColour();//构造函数setColour(const setColour& c);//拷贝构造函数setColour& operator=(const setColour& c);//赋值运算符重载setColour operator+(setColour& c2);//并集setColour operator*(setColour& c2);//交集setColour operator-(setColour& c2);//差集friend bool operator<(colour c, setColour& c2);//属于bool operator<=(setColour& c2);//包含于friend ostream& operator<<(ostream& output, const setColour& c);//流插入运算符重载friend istream& operator>>(istream& input, setColour& c);//流提取运算符重载
private:bool* _colourStatus;
};
为使集合的运算更直观,我们对“ * + - <= < ”等符号进行重载,用来代表交、并、差、蕴含、属于等集合运算。
* | + | - | <= | < |
交集(两个集合同时存在的元素集合) |
并集(两个集合的所有元素集合) | 差集(前一个集合有后一个集合没有的元素集合) | 蕴含(右蕴含左) | 属于(左侧元素属于右侧集合) |
构造函数
构造数组,并将每个元素初始化为0:
setColour::setColour()
{_colourStatus = new bool[5];for (int i = 0; i < 5; i++){_colourStatus[i] = 0;}
}
拷贝构造函数和赋值运算符重载
由于我们的成员变量是动态开辟的,但编译器给的默认拷贝构造函数和赋值重载只会进行浅拷贝,在对象析构的时候,会出现两个对象delete同一块内存的情况,而引发报错,所以我们要自己写两个深拷贝的,保证复制出的数组和原来的数组不是同一块空间:
setColour::setColour(const setColour& c)
{_colourStatus = new bool[5];for (int i = 0; i < 5; i++){_colourStatus[i] = c._colourStatus[i];}
}
setColour& setColour::operator=(const setColour& c)
{if (this != &c){_colourStatus = new bool[5];for (int i = 0; i < 5; i++){_colourStatus[i] = c._colourStatus[i];}return *this;}
}
“>>”的 重载
在输入时,我们会输入一个字符串来表示这个集合,或添加某个元素,所以我们要用到strstr()这个函数进行颜色元素的检索,再进行数组写入:
istream& operator>>(istream& input, setColour& c)
{char inColour[30] = { 0 };cin.getline(inColour, 30);if (strstr(inColour, "red")){c._colourStatus[(int)red] = 1;}if (strstr(inColour, "yellow")){c._colourStatus[(int)yellow] = 1;}if (strstr(inColour, "blue")){c._colourStatus[(int)blue] = 1;}if (strstr(inColour, "white")){c._colourStatus[(int)white] = 1;}if (strstr(inColour, "black")){c._colourStatus[(int)black] = 1;}return input;
}
“<<”的重载
循环数组每一个元素,若此元素为1,则对这个下标表示的颜色进行输出(counter是用于格式控制的)
ostream& operator<<(ostream& output, const setColour& c)
{cout << "{ ";int counter = 0;for (int i = 0; i < 5; i++){if (c._colourStatus[i]){switch (i){case 0:cout << "red, ";break;case 1:cout << "yellow, ";break;case 2:cout << "blue, ";break;case 3:cout << "white, ";break;case 4:cout << "black, ";break;default:break;}counter++;}}if (counter > 0){cout << "\b\b }";}else{cout << "\b}";}return output;
}
集合运算符重载
实现大致相同,都是遍历每一个元素进行逻辑运算:
setColour setColour::operator*(setColour& c2)
{setColour newSet;for (int i = 0; i < 5; i++){newSet._colourStatus[i] = _colourStatus[i] && c2._colourStatus[i];}return newSet;
}
setColour setColour::operator+(setColour& c2)
{setColour newSet;for (int i = 0; i < 5; i++){newSet._colourStatus[i] = _colourStatus[i] || c2._colourStatus[i];}return newSet;
}
setColour setColour::operator-(setColour& c2)
{setColour newSet;for (int i = 0; i < 5; i++){newSet._colourStatus[i] = _colourStatus[i] && !c2._colourStatus[i];}return newSet;
}
bool operator<(colour c, setColour& c2)
{if (c2._colourStatus[(int)c])return 1;elsereturn 0;
}
bool setColour::operator<=(setColour& c2)
{for (int i = 0; i < 5; i++){if (_colourStatus[i] && !c2._colourStatus[i]){return 0;}}return 1;
}
总体实现代码
#include <assert.h>
#include <string.h>
#include <iostream>
using namespace std;
enum colour { red, yellow, blue, white, black };
class setColour
{
public:setColour();setColour(const setColour& c);setColour& operator=(const setColour& c);//赋值setColour operator+(setColour& c2);//并集setColour operator*(setColour& c2);//交集setColour operator-(setColour& c2);//差集friend bool operator<(colour c, setColour& c2);//属于bool operator<=(setColour& c2);//包含于friend ostream& operator<<(ostream& output, const setColour& c);friend istream& operator>>(istream& input, setColour& c);
private:bool* _colourStatus;
};
setColour::setColour()
{_colourStatus = new bool[5];for (int i = 0; i < 5; i++){_colourStatus[i] = 0;}
}
setColour::setColour(const setColour& c)
{_colourStatus = new bool[5];for (int i = 0; i < 5; i++){_colourStatus[i] = c._colourStatus[i];}
}
setColour& setColour::operator=(const setColour& c)
{if (this != &c){_colourStatus = new bool[5];for (int i = 0; i < 5; i++){_colourStatus[i] = c._colourStatus[i];}return *this;}
}
setColour setColour::operator*(setColour& c2)
{setColour newSet;for (int i = 0; i < 5; i++){newSet._colourStatus[i] = _colourStatus[i] && c2._colourStatus[i];}return newSet;
}
setColour setColour::operator+(setColour& c2)
{setColour newSet;for (int i = 0; i < 5; i++){newSet._colourStatus[i] = _colourStatus[i] || c2._colourStatus[i];}return newSet;
}
setColour setColour::operator-(setColour& c2)
{setColour newSet;for (int i = 0; i < 5; i++){newSet._colourStatus[i] = _colourStatus[i] && !c2._colourStatus[i];}return newSet;
}
bool operator<(colour c, setColour& c2)
{if (c2._colourStatus[(int)c])return 1;elsereturn 0;
}
bool setColour::operator<=(setColour& c2)
{for (int i = 0; i < 5; i++){if (_colourStatus[i] && !c2._colourStatus[i]){return 0;}}return 1;
}
ostream& operator<<(ostream& output, const setColour& c)
{cout << "{ ";int counter = 0;for (int i = 0; i < 5; i++){if (c._colourStatus[i]){switch (i){case 0:cout << "red, ";break;case 1:cout << "yellow, ";break;case 2:cout << "blue, ";break;case 3:cout << "white, ";break;case 4:cout << "black, ";break;default:break;}counter++;}}if (counter > 0){cout << "\b\b }";}else{cout << "\b}";}return output;
}
istream& operator>>(istream& input, setColour& c)
{char inColour[30] = { 0 };cin.getline(inColour, 30);if (strstr(inColour, "red")){c._colourStatus[(int)red] = 1;}if (strstr(inColour, "yellow")){c._colourStatus[(int)yellow] = 1;}if (strstr(inColour, "blue")){c._colourStatus[(int)blue] = 1;}if (strstr(inColour, "white")){c._colourStatus[(int)white] = 1;}if (strstr(inColour, "black")){c._colourStatus[(int)black] = 1;}return input;
}
方式二
总体实现原理
1.这里我们只定义了一个unsigned int(这里size_t就是unsigned int)类型,用它的32个二进制位进行集合元素的存储。(此时这种方式的劣势也显现出来,定义的集合只能有32种元素,其实也可以申请一块连续空间(数组)拓展元素个数,实现了“站着挣钱”,但后续将不能直接对一个int直接进行位运算,还需进行额外实现,各位大神如果想进行实现或有任何见解欢迎评论区一起探讨)。
2.接下类的集合运算就可以通过对这个整形进行位运算而实现。
各函数实现
1. 前面的两个宏用来进行元素扩充,COLOUR_NUM用来更改元素个数,COLOUR_STR是元素对应的字符串,在后面cin/cout会用到,再对枚举类型进行元素添加即可实现集合元素扩充
2.由于没有动态开辟空间,这里将不再需要自己写拷贝构造,赋值重载。
“>>”的 重载
1.在输入时,我们会输入一个字符串来表示这个集合,或添加某个元素,所以我们要用到strstr()这个函数进行颜色元素的检索,再进行数组写入:
2.很明显,相较方法一,这里的输入重载明显变短,那么是怎么做到的的呢?
我们定义一个字符串数组,用输入的字符串循环对这个数组进行匹配判断,从而对集合进行写入
3.如果匹配成功,这时的“ i ”就代表字符串数组的元素下标,同时也是这个颜色对应的enum赋值,也就是i代表了对应的颜色,这时我们将数字1进行左移 i 位,使它只有第 i 个二进制位是1,其他位都是0,再将这个数与原集合数字进行按位或,就可以将这一位赋值位真。
istream& operator>>(istream& input, setColour& c)
{const char* colourIn[COLOUR_NUM] = { COLOUR_STR };char inColour[30] = { 0 };cin.getline(inColour, 30);for (int i = 0; i < COLOUR_NUM; i++){if (strstr(inColour, colourIn[i])){c._colourStatus |= (1 << i);}}return input;
}
“<<”的重载
输出函数原理大致与输入函数相同,只不过这次是循环检查哪一位是1,并打印第i位对应的字符串。
ostream& operator<<(ostream& output, const setColour& c)
{const char* colourOut[COLOUR_NUM] = { COLOUR_STR };cout << "{ ";int counter = 0;size_t colour_test = 1;for (int i = 0; i < COLOUR_NUM; i++){if (c._colourStatus & colour_test){cout << colourOut[i] << ", ";counter++;}colour_test <<= 1;}if (counter > 0){cout << "\b\b }";}else{cout << "\b}";}return output;
}
集合运算符重载
实现大致相同,都是对元素进行位运算。
其他都好理解,这里差集要进行着重解释一下,差集就是被减集合减去交集,即:a & ~(a & b),但为什么写了a & ~b呢?这里就需要大家有一点位运算或者离散数学的知识了,运算过程如下:
a & ~(a & b) <==> a&(~a | ~b) <==> (a & ~a) | (a & ~b) <==> 1 | (a & ~b) <==> a & ~b
setColour setColour::operator*(setColour& c2)
{return setColour(_colourStatus & c2._colourStatus);
}
setColour setColour::operator+(setColour& c2)
{return setColour(_colourStatus | c2._colourStatus);
}
setColour setColour::operator-(setColour& c2)
{return setColour(_colourStatus & ~c2._colourStatus);
}
bool operator<(colour c, setColour& c2)
{return c2._colourStatus & (1 << c);
}
bool setColour::setColour::operator<=(setColour& c2)
{return (_colourStatus | c2._colourStatus) == c2._colourStatus;
}
总体实现代码
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <errno.h>
#include <iostream>
using namespace std;
#define COLOUR_NUM 5
#define COLOUR_STR "red","yellow","blue","white","black"
enum colour { red, yellow, blue, white, black };
class setColour
{
public:setColour(size_t cS = 0);setColour operator+(setColour& c2);//并集setColour operator*(setColour& c2);//交集setColour operator-(setColour& c2);//差集friend bool operator<(colour c, setColour& c2);//属于bool operator<=(setColour& c2);//包含于friend ostream& operator<<(ostream& output, const setColour& c);friend istream& operator>>(istream& input, setColour& c);
private:size_t _colourStatus;
};
setColour::setColour(size_t cS)
{_colourStatus = cS;
}
setColour setColour::operator*(setColour& c2)
{return setColour(_colourStatus & c2._colourStatus);
}
setColour setColour::operator+(setColour& c2)
{return setColour(_colourStatus | c2._colourStatus);
}
setColour setColour::operator-(setColour& c2)
{return setColour(_colourStatus & ~c2._colourStatus);
}
bool operator<(colour c, setColour& c2)
{return c2._colourStatus & (1 << c);
}
bool setColour::setColour::operator<=(setColour& c2)
{return (_colourStatus | c2._colourStatus) == c2._colourStatus;
}
ostream& operator<<(ostream& output, const setColour& c)
{const char* colourOut[COLOUR_NUM] = { COLOUR_STR };cout << "{ ";int counter = 0;size_t colour_test = 1;for (int i = 0; i < COLOUR_NUM; i++){if (c._colourStatus & colour_test){cout << colourOut[i] << ", ";counter++;}colour_test <<= 1;}if (counter > 0){cout << "\b\b }";}else{cout << "\b}";}return output;
}
istream& operator>>(istream& input, setColour& c)
{const char* colourIn[COLOUR_NUM] = { COLOUR_STR };char inColour[30] = { 0 };cin.getline(inColour, 30);for (int i = 0; i < COLOUR_NUM; i++){if (strstr(inColour, colourIn[i])){c._colourStatus |= (1 << i);}}return input;
}
测试主函数
void test1()
{setColour colour1;setColour colour2 = colour1;cout << "请输入两行颜色集合:(如:{red, yellow, blue})" << endl;cin >> colour1;cin >> colour2;setColour colour3 = colour1 * colour2;cout << "交集:" << colour3 << endl;colour3 = colour1 + colour2;cout << "并集:" << colour3 << endl;colour3 = colour1 - colour2;cout << "差集:" << colour3 << endl;if (red < colour1){cout << "red属于第一个集合" << endl;}else{cout << "red不属于第一个集合" << endl;}if (colour1 <= colour2){cout << "集合一包含于集合二" << endl;}else{cout << "集合一不包含于集合二" << endl;}
}
int main()
{test1();return 0;
}
测试用例与结果
定义一个集合类setColour,要求元素为枚举类型值相关推荐
- 12.定义一个集合类SET,处理整型数组。
12.定义一个集合类SET,处理整型数组.通过成员函数重载运算符"==",判断一个数是否属于集合;通 过友元重载运算符"==",判断两个集合是否相同,即集合中的 ...
- java 整型数组定义_在Java中定义一个具有10个元素的整型数组a的语句是:___
在Java中定义一个具有10个元素的整型数组a的语句是:___ 答: int [] arr = new int[10] 在借贷记账法下() 答:在账户结构上,"借"和"贷 ...
- cpp课程设计实验题:定义一个描述学生(Student)基本情况的类,数据成员包括姓名(name)、学号(num)、数学成绩(mathScore)、英语成绩(englishScore)、人数(coun
CPP实验题:定义一个描述学生(Student)基本情况的类,数据成员包括姓名(name).学号(num).数学成绩(mathScore).英语成绩(englishScore).人数(count).数 ...
- C++实验编程题:.定义一个描述学生(Student)基本情况的类,数据成员包括姓名(name)、学号(num)、数学成绩(mathScore)、英语成绩(englishScore)、人数(count
题目描述: *6.定义一个描述学生(Student)基本情况的类,数据成员包括姓名(name).学号(num).数学成绩(mathScore).英语成绩(englishScore).人数(count) ...
- 类与对象实验:定义一个描述学生(Student)基本情况的类,数据成员包括姓名(name)、学号(num)、数学成绩(mathScore)、英语成绩(englishScore)、人数(count)……
定义一个描述学生(Student)基本情况的类,数据成员包括姓名(name).学号(num).数学成绩(mathScore).英语成绩(englishScore).人数(count).数学总成绩(ma ...
- 定义一个集合类Set,(考察动态数组的建立)
完整题目 定义一个整形数集合类Set,请通过创建动态分配的整数数组(使用new运算符)存放整数值,且数组的大小要能够根据包含元素的个数动态的变化.集合中,元素的顺序无关紧要,每个元素至多出现一次.实现 ...
- 7.定义一个有80个元素的字符数组,从键盘输入一串字符,将其中的大写字母转换为小写字母,而将原来为小写的字母转换为大写字母,其他字符不变。
#include<stdio.h> #define N 80 void main(void) {int i=0;char a[N],b;printf("输入字符串:") ...
- 3.定义一个有10个元素的数组,用其代表10个学生的考试成绩,从键盘输入10个成绩,统计平均成绩。
#include<stdio.h> #define N 10 void main(void) {int i;float a[N],ave;ave=0;for(i=0;i<N;i++) ...
- python定义一个1xn矩阵_Python实现的矩阵类实例
本文实例讲述了Python实现的矩阵类.分享给大家供大家参考,具体如下: 科学计算离不开矩阵的运算.当然,python已经有非常好的现成的库: 我写这个矩阵类,并不是打算重新造一个轮子,只是作为一个练 ...
最新文章
- 在Elasticsearch中对 text 类型的字段进行聚合异常Fielddata is disabled,Set fielddata=true
- 使用supervisor支持Python3程序 (解决找不到Module的问题)
- R语言绘制空间热力图
- 征战蓝桥 —— 2015年第六届 —— C/C++A组第5题——九数组分数
- CDN(内容分发网络)技术原理(转)
- 李佳琦公益助力乡村教育 为学生送上开学礼物
- C#实现文件下载的几种方式
- Android平台视频开发
- ORACLE异常处理及函数
- verilog语法实例学习(3)
- 简单网页-------课程表
- 计算机病毒进化趋势,人类进化趋势是什么?
- java快速开发项目_GitHub - Johnnyzhoutq/X-SpringBoot: X-SpringBoot是一个轻量级的Java快速开发平台,能快速开发项目并交付【接私活利器】...
- Sign In with Apple - 使用苹果账号登录你的应用
- 裸板 nand flash K9F2G08U0C --- 读取ID
- Delphi @ ^
- 香农采样定理和奈奎斯特采样定理
- python 图片库_最新PHP+Python开源版在线浏览美女图片美女套图源码带数据库
- 我的世界观——阿尔伯特·爱因斯坦
- 机器学习算法分析汇总
热门文章
- 02.The Window 补充——experimenting
- 2021年10月31日
- python士兵突击_10天带你玩转python2020版
- Java毕业设计_ 基于SSM的JSP教学网站的设计与实现
- 会声会影X9快进和慢动作效果如何制作及2020版下载
- 【故障诊断】基于负熵诱导灰狼优化算法的多目标信息频带选择用于滚动轴承故障诊断(Matlab代码实现)
- 关于戴尔电脑一直显示“正在关机”的问题解决记录
- Minecraft 1.12.2 生化8 模组 2.1版本 新建筑+红黑球+支持服务器联机
- js之拖动div(进行了范围控制,速度计算)
- 原创:学习英语小助手(阅读粘贴的英文,使用MVVM)