文章目录
一、结构体
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