1.9 结构,共用和自定义
结构体
- 结构体是由多种类型的数据(变量)组成的整体.组成结构类型的各个分量称为结构的数据成员(简称成员,或称为成员变量)
1.结构类型声明
struct [结构类型名]
{
<成员定义1>;
<成员定义2>;
...
<成员定义n>;
};
- 注意:
- 成员的数据类型可以是基本数据类型,也可以是数组,结构等构造类型或其他已声明的合法的数据类型
- 结构类型的声明仅仅是一个数据类型的声明,编译不会为其分配内存空间,只有当用结构类型定义结构类型的变量时,编译才会为这种变量分配内存空间
- 结构类型声明中最后有分号”
;
” - 结构体中成员变量的定义的次序只会影响在内存空间中的分配顺序(当定义该结构类型变量时),而对所声明的结构类型没有影响.
- 结构类型名是区分不同类型的标志,一般结构类型名用大写来表示
struct STUDENT
{
int num; // 学号
float score[3]; // 三门课程成绩
float edit[3]; // 三门课程的学分
float total,ave; // 总成绩和平均成绩
float alledit; // 总学分
};
2.结构类型变量的定义
在C++中,定义一个结构类型变量有三种方式:
1.先声明结构类型,再定义结构类型变量,称为声明之后定义方式(推荐)
[struct] <结构类型名> <变量名 1>[,<变量名 2>,...<变量名 n>];
如:
struct STUDENT stu1,stu2;//其中,struct可以省略
- 一旦定义了结构类型变量,编译器就会为其分配内存空间,其内存空间的大小就是声明时指定的各个成员所占的内存空间的大小.
2.在结构类型声明的同时定义结构类型变量,称为声明之时定义方式 - 被定义的结构类型变量应写在最后的花括号和分号之间,多个变量名之间用逗号隔开.
struct STUDENT
{
//...
}stu1,stu2;
3.在声明结构类型时,省略结构类型名,直接定义结构类型变量,不再二次使用该结构类型,称为一次性定义方式
struct{
// ...
}stu1,stu2;
3.结构类型变量的初始化
- 一般形式:在定义的结构类型变量后面加上”
={<初始列表>};
”
STUDENT stu1 = {1001,90,95,75,3,2,2}; // 它会将花括号里面的值按其成员变量定义的顺序依次给成员变量赋初值
// 其他成员变量的初值未被指定,则它们的值未被指定或不确定
- 结构类型中成员的数据类型还可以是另一个已定义的结构类型.
struct POINT
{
int x;
int y;
};
struct RECT
{
POINT ptLeftTop;
int aWidth;
int nHeight;
};
// 初始化,可以使用花括号增强可读性
RECT re1 = {{20,30},100,80};
4.结构类型变量的引用
1.只能引用结构类型变量中的成员变量,并使用一下格式:
<结构体变量名>.<成员变量名>
struct POINT
{
int x,y;
}spot={20,30};
cout << spot.x << spot.y;
- 其中,”
.
“是成员运算符,它的优先级仅次于域运算符”::
”
2.若成员本身又是一个结构类型变量,则引用时需要用多个成员运算符一级一级地找到最低一级的成员
struct RECT
{
POINT ptLeftTop;
POINT ptRightDown;
}rc = {{10,20},{40,50}};
cout << rc.ptLeftTop.x << rc.ptLeftTop.y;
3.结构类型相同的变量之间可以直接赋值,这种赋值等效于各个成员的依次赋值
struct POINT
{
int x,y;
};
POINT p1 = {10,20};
POINT p2 = p1; //等效于 pt2.x = p1.x; p2.y = p1.y;
cout << p2.x << "\t" << p2.y << endl; //输出 10 20
结构数组
- 由结构类型的元素组成的数组称为结构数组
1.结构数组的初始化
- 由于结构类型声明的是一条记录信息,而一条记录信息在二维线性表中就表示一个行,因此一维结构数组的初始化形式应与二维普通数组相同
struct STUDENT
{
int num; // 学号
float score[3]; // 三门课程成绩
float edit[3]; // 三门课程的学分
float total,ave; // 总成绩和平均成绩
float alledit; // 总学分
};
STUDENT stu[3]={{1001,900,95,75,3,2},
{1002,80,90,78,3,2,2},
{1003,75,80,72,3,2,2}};
- 凡成员未被指定初值,这些成员的初值均为0
2.结构数组元素的引用
- 格式:
<结构数组名>[<下标表达式>].<成员>
for(int i =0;i< sizeof(stu)/sizeof(STUDENT);i++)
{
stu[i].total = stu[i].score[0] + stu[i].score[1] + stu[i].score[2];
stu[i].ave = stu[i].total/3.0;
stu[i].alledit = stu[i].edit[0] + stu[i].edit[1] + stu[i].edit[2];
if(stu[i].ave > stu[nMax].ave) nMax = i;
}
结构和函数
- 当结构类型变量作为函数的参数时,传递的方式是值传递方式,整个结构都会复制到形参中
#include <iostream>
using namespace std;
struct PERSON
{
int age;//年龄
int weight;//体重
char name[25];//姓名
};
void print(PERSON one)
{
cout << one.name << "\t"
<< one.age << "\t"
<< one.weight << endl;
}
PERSON all[4] = { {20,60,"Zhang"},{28,50,"Fang"},{33,78,"Ding"},{19,65,"Chen"} };
int main()
{
for (int i = 0; i < 4; i++)
{
print(all[i]);
}
system("pause");
return 0;
}
/*
Zhang 20 60
Fang 28 50
Ding 33 78
Chen 19 65
*/
- 结构体还可以作为一个函数的返回值
#include <iostream>
using namespace std;
struct PERSON
{
int age;//年龄
int weight;//体重
char name[25];//姓名
};
void print(PERSON one)
{
cout << one.name << "\t"
<< one.age << "\t"
<< one.weight << endl;
}
PERSON getperson()
{
PERSON temp;
cout << "请输入姓名,年龄,体重: ";
cin >> temp.name >> temp.age >> temp.weight;
return temp;
}
int main()
{
PERSON one = getperson();
print(one);
system("pause");
return 0;
}
/*
请输入姓名,年龄,体重: ding 41 90
ding 41 90
*/
结构指针
- 当定义一个指针变量的数据类型是结构类型时,这样的指针变量称为结构指针变量,它指向结构体类型变量
#include <iostream>
#include <string.h>
using namespace std;
struct PERSON
{
int age;//年龄
char sex;//性别
float weight;//体重
char name[25];//姓名
};
int main()
{
struct PERSON one;
struct PERSON *p;//指向PERSON类型的指针变量
p = &one;
p->age = 32;
p->sex = 'M';
p->weight = (float)80.2;
strcpy(p->name, "LiMing");
cout << "姓名: " << (*p).name << endl;
cout << "性别: " << (*p).sex << endl;
cout << "年龄: " << (*p).age << endl;
cout << "体重(kg): " << (*p).weight << endl;
system("pause");
return 0;
}
/*姓名: LiMing
性别: M
年龄: 32
体重(kg): 80.2
*/
->
称为指向运算符,它的左边必须是一个指针变量,它等效于指针变量所指向的结构体类型变量,如p->name
等价于(*p).name
共用体
- 共用体的功能与语句都和结构体相同,它们的区别是:共用体在任一时刻只有一个成员处于活动状态,且共用体变量所占用的内存长度等于各个成员中最长成员的长度.
- 格式:
union <共用体>
{
<成员定义 1>;
<成员定义 2>;
...
<成员定义 n>;
}[共用体变量名表]; //注意后面的分号不能省略
如:
// 系统为NumericType开辟了8字节的内存空间
union NumericType
{
int iValue; // 整型变量,4字节
long lValue; // 长整型变量,4字节
float fValue; //实型,8字节
};
#include <iostream>
#include <string.h>
using namespace std;
union PERSON
{
int age;//年龄
float weight;//体重
char name[25];//姓名
};
void print(PERSON one)
{
cout << one.name << "\t"
<< one.age << "\t"
<< one.weight << endl;
}
int main()
{
PERSON all = { 33 }; // all.age=33
print(all); // 只有all.age有效
all.weight = 80;
print(all); // 只有all.weight有效
strcpy(all.name, "ding");
print(all); // 只有all.name有效
system("pause");
return 0;
}
/*!
33 4.62428e-44
1117782016 80
ding 1735289188 1.12587e+24
*/
使用typedef
- C++中使用
typedef
类为一个已定义的合法的类型名增加新名称,从而使相同类型具有不同的类型名.这样的好处:
- 可以按照统一的命名规则定义一套类型名称体系,从而可以提高程序的移植性
- 可以将一些难以理解的,冗长的数据类型名重新命名,使其变得容易理解和阅读
1.为基本数据类型名添加新的类型名
- 格式:
typedef <基本数据类型> <新的类型名>;
其功能是将新的类型名赋予基本数据类型的定义
typedef int Int;
typedef unsigned UInt;
typedef const int CInt;
- 注意: 一条
typedef
语句只能定义一个新的类型名 - 定义完后就可以直接使用这些新的类型名来定义变量了.
2.为数组类型名增加新的类型名
- 格式:
typedef <数据类型名> <新的类型名>[<下标>];
其功能是将新的类型名作为一个数组类型名,下标用来指定数组的大小,如:
typedef int Ints[10]; // Ints代表具有10个元素的整型数组
typedef float Floats[20]; // Floats代表具有20个元素的单精度实型数组
Ints a; // 等效于 int a[10];
Floats b; // 等效于 float b[20];
3.为结构类型名增加新的类型名
- 格式:
typedef struct [结构类型名]
{
<成员定义>;
...
}<新的类型名>;
这种格式是在结构类型声明的同时进行的,其功能是将新的类型名作为此结构类型的一个新的名称,如:
typedef struct student
{
...
}STUDENT;
STUDENT stu1; // 等效于 struct student stu1;
4.为指针类型名增加新的类型名称
typedef int* PInt;
typedef float* PFloat;
typedef char* String;
PInt a,b; //等效于 int *a,*b;
用typedef
为一个已有的类型名声明新的类型名称的方法时,可以按下列步骤进行:
- 用已有的类型名写出定义一个变量的格式,如
int a;
- 在格式中将变量名换成要声明的新的类型名称,如
int Int;
- 在最前面添加上关键字
typedef
即可完成声明,如typedef int Int;
- 之后就可以使用新的类型名定义变量了