C++(六)复合类型(结构体,共用体,枚举)

一、结构体

C/C++语言本身提供了很多基本数据类型,例如:int、float、char、double、long int 等供我们使用。但是程序编写的过程中问题往往比较复杂,基本的数据类型有时候不能满足我们的需求,比如:我们需要管理学校所有学生的信息,除了学号、还有姓名、性别、各科的成绩分数等。这样同时需要几个数据类型来表示,于是引出了接下来要讲解的结构体struct。
初此之外,我们还需要其它的数据类型比如:联合体union、枚举类型enum,类类型class 等就是用户自定义的数据类型。这些用户自定义的数据类型跟C/C++语言提供的基本类型一样,都可以用来定义变量。只不过在这些自定义数据类型在使用之前要先由用户声明出来才行。

1.1 结构体类型的声明

struct 结构体类型名
{
  //成员表;
};

举例:学生的信息管理系统中休要定义一个学生的信息:包括:学号,姓名,性别,年龄,成绩 等等。如下声明了一个结构体类型 Student,struct 是结构体类型的关键字,不能省略

struct Student
{
    string name;
    int num;
    char sex;
    int age;
    double score;
};

备注:C语言中结构体的成员只能是数据,C++对此进行了扩充,结构体的成员既可以包含数据,也可以包含函数,其实在C++中 struct 跟 class 从使用角度来说差别不大。

1.2 结构体类型变量的定义及初始化

定义:结构体类型声明完了之后就可以定义变量了,如下:
Student zhangsan, lisi;
这种是非常常用的一种定义结构体类型变量的方法。
当然也可以在声明结构体类型的时候就定义变量(不常用):

struct Student
{
    string name;
    int num;
    char sex;
    int age;
    double score;
} zhangsan, lisi;

初始化:Student zhangsan = {“张三”, 1001, ‘m’, 25,80.5};
备注:初始化参数的顺序一定要和结构体类型声明的成员表顺序一致才行,不然会报错而且会错误的赋值。

1.3 结构体类型变量成员的访问

访问:结构体变量名.成员名

例如:
Student zhangsan = {“张三”, 1001, ‘m’, 25,80.5};
zhangsan.num = 1001;

1.4 结构体类型和数组配合使用

一般情况下,学生的信息都是这种格式,比如学校一共1-6年级,我们定义500个学生:
之前在python中,numpy中也有结构化数组,或者直接使用pandas,函数方法多,拿来就用,并且快速高效。

#include <iostream>
#include <string>
using namespace std;

struct Student
{
	string name;
	int num;
	char sex;
	int age;
};

int main()
{
	Student stu[500];

	//输入
	for (int idx = 0; idx < 500; ++idx)
	{
		cin >> stu[idx].name;
		cin >> stu[idx].num;
		cin >> stu[idx].sex;
		cin >> stu[idx].age;
	}

	//输出
	for (int idx = 0; idx < 500; ++idx)
	{
		cout << stu[idx].name << " " << stu[idx].num << " " << stu[idx].sex << " " << stu[idx].age << endl;
	}

	return 0;
}
1.5 结构体变量作为函数参数

结构体变量跟其他类型的变量一样使用,作为函数的参数直接传递进去,以值传递的方式传递。

struct Student
{
	string name;
	int num;
	char sex;
	int age;
};

void set_num(Student stu)
{
	static int stu_num = 10001;  //初始学号,整个程序生命周期只初始化一次。
	stu.num = stu_num++;
}

int main()
{
	Student stu[4] = 
	{
		{ "zhangsan", 0, 'm', 10 },
		{ "lisi", 0, 'm', 12 },
		{ "wangwu", 0, 'm', 10 },
		{ "zhaoliu", 0, 'm', 11 }
	};

	//遍历
	for (int idx = 0; idx < 4; ++idx)
	{
		set_num(stu[idx]);
		cout << stu[idx].name << " " << stu[idx].num << " " << stu[idx].sex << " " << stu[idx].age << endl;
	}
    return 0;
}

二、共用体

共用体(union)是一种数据格式,它能够存储不同的数据类型,但只能同时存储其中的一种类型,也就是说,共用体只能存储 int 或 long 或 double;而结构体可以同时存储 int 和 long 和 double。共用体的语法与结构体相似,但含义不同。

共用体的结构与结构体的结构类似,但是它的所有成员变量,都只有一个起始地内存地址,储存在同一段内存中。
这样导致的结果就是,你每次只能给一个变量赋值,就算给其他变量赋值,它就会覆盖上一个变量的值。

#include "stdafx.h"
#include <iostream>
using namespace std;

union one4all
{
	int int_val;
	long long_val;
	double double_val;
};

int main()
{
	one4all pall;
	pall.int_val = 15;         //sore an int
	cout << "pall.int_val=" << pall.int_val << endl;

	pall.double_val = 1.38;    //sore a double,int value is lost
	cout << "pall.int_val= " << pall.int_val << endl;
	cout << "pall.double_val=" << pall.double_val << endl;
	return 0;
}

==========运行输出=========
pall.int_val=15
pall.int_val= -515396076   //执行完pall.double_val = 1.38 这一步后,pall.int_val的值就被清空了。
pall.double_val=1.38
请按任意键继续. . .

如上:给pall.double赋值后,pall.int的值将丢失,也就是说共用体里虽然有三个类型,但每次只能存在一个类型。因此,pall有时可以是int变量,而有时又可以是double变量,成员名称标识了变量的容量。由于共用体每次只能存储一个值,因此它必须有足够的空间来存储最大的成员,所以,共用体的长度为最大成员长度

三、枚举

如果一个变量只能有几种可能的值,这样的变量可以定义成枚举类型。所谓的 “枚举” 是指可以将变量的值一一列举出来(为一个固定的数量)。例如:一周只有星期一到星期日、性别男或女、一年的月份 等等。枚举类型也是一种自定义类型。

3.1 枚举类型的声明

声明枚举类型用 enum 开头,例如:
enum Em_Sex
{
  Em_Male,  //男性
  Em_FMale  //女性
};

以上就是定义了一个枚举类型 Em_Sex,大括号内部的 Em_Male、Em_FMale称为枚举元素。

注意事项:
①、枚举元素按常量处理,所以称作枚举常量。不要对他们进行赋值,即枚举元素的值是固定的;
②、枚举元素是常量,所以其也是有值的,他们的值是一个整数,按照元素声明时候的顺序从0开始依次进行+1操作,默认的值就是:0,1,2,3,…
例如,上面的ESex枚举类型中,Em_Male的值默认是0,Em_FMale的默认值是1,依此类推。
③、枚举元素有默认的值,但也可以在声明的时候指定值。(如下例子)
其中从 EWeekDay_4 开始未赋值,所以按照他的上一个元素的值+1的规则进行默认赋值,也就是 EWeekDay_3 + 1 = 6。
这里面有个注意事项,即,上面赋值的最好是依次增大,不然有可能会造成两个枚举元素是一样的值。
④、枚举值可以用来进行跟整数一样的判断,比较,switch-case 等操作,例如:

#include <iostream>
using namespace std;


enum EWeekDay    // 枚举元素里面是逗号分割
{
	Sunday = 0,
	Monday = 1,
	Tuesday,
	Wednesday,
	Thursday,
	Friday,
	Saturday,
};
void chooseday(EWeekDay temp_day);

int main()
{
	int today;
	cout << "请输入0-6之间的整数!" << endl;
	cin >> today;
	chooseday(EWeekDay(today));
}

void chooseday(EWeekDay temp_day)
{
	switch (temp_day)
	{
	case Sunday:
		cout << "haha,go shopping!" << endl;
		break;
	case Monday:
		cout << "workding!" << endl;
		break;
	case Tuesday:
		cout << "workding!" << endl;
		break;
	case Wednesday:
		cout << "workding!" << endl;
		break;
	case Thursday:
		cout << "workding!" << endl;
		break;
	case Friday:
		cout << "workding!" << endl;
		break;
	case Saturday:
		cout << "haha,go shopping!" << endl;
		break;
	default:
		cout << "Wrong input!" << endl;
		break;
	}
}
3.2 枚举类型和结构体类型结合
struct Student
{
    string name;
    int num;
    Em_Sex sex;
    int age;
};

Student stu;
stu.sex = Em_Male;
3.3 typedef 类型声明新的类型名字:

除了可以用 struct 结构体,union 联合体,enum 枚举 等自定义类型以外,还可以使用 typedef 声明一个新的类型名字来代替已有的类型名。注意是新的类型名字,只是名字而已,不是一种全新的类型,只是改个名字而已。
例如,我们定义一个无符号的整型int变量可以这样来定义:unsigned int a = 5;
类型的名字比较长,为了方便使用 typedef 对 unsigned int 改个名字,将 unsigned int 都可以改成 uint 了。同理,其他的类型也都可以使用 typedef 改名,例如:

typedef unsigned int uint;   //对数据类型名unsigned int 起个别名uint,用起来方便
uint a = 5;

typedef unsigned long ulong;
typedef Student Stu;
typedef EWeekDay EWDay;

四、结构体数组与指针

在标题1.5的代码示例中,我们使用.运算符访问成员变量,其实在C/C++中规定结构体类型的指针变量可以用 -> 符号来引用其成员
Student stu;
Student* pstu = &stu;
pstu->num = 102;

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;


struct Student
{
	string name;
	int num;
	char sex;
	int age;
};

void set_num(Student* ptr_stu)
{
	static int stu_num = 10001;  //初始学号,整个程序生命周期只初始化一次。
	ptr_stu->num = stu_num++;
}

int main()
{
	Student stu[4] =
	{
		{ "zhangsan", 0, 'm', 10 },
		{ "lisi", 0, 'm', 12 },
		{ "wangwu", 0, 'm', 10 },
		{ "zhaoliu", 0, 'm', 11 }
	};
	
	//遍历
	for (int idx = 0; idx < 4; ++idx)
	{
		set_num(&stu[idx]);
		cout << stu[idx].name << " " << stu[idx].num << " " << stu[idx].sex << " " << stu[idx].age << endl;
	}

	return 0;
}

================运行输出:================
zhangsan 10001 m 10
lisi 10002 m 12
wangwu 10003 m 10
zhaoliu 10004 m 11
发布了387 篇原创文章 · 获赞 594 · 访问量 72万+

猜你喜欢

转载自blog.csdn.net/wsp_1138886114/article/details/104292477
今日推荐