目录
1.2.2 struct 结构体名称 变量名 = { 成员1值,成员2值...};
1结构体
1.1 概念
属于用户自定义的一种数据类型,不同于内置类型(int
整型,float
浮点型这种)
可在其中存储不同的数据类型
1.2 语法与使用
语法:
struct + 名称 { 成员列表 };
举例:
struct Student
{
// 成员列表
string name; // 名字
int age; // 年龄
int score; // 分数
};
这就是一个数据类型,相当于int、double
等,接下来使用该数据类型定义一个变量
1.2.1 struct 结构体名称 变量名;
struct Student s1; // 创建变量s1
s1.name = "Joyce"; // 变量s1中的name赋值
s1.age = 20; // 变量s1中的age赋值
s1.score = 100; // 变量s1中的score赋值
cout << s1.name << " " << s1.age << " " << s1.score << endl;
访问结构体中的成员,用 .
符号
1.2.2 struct 结构体名称 变量名 = { 成员1值,成员2值...};
struct Student s2 = { "Tatina",21,99 };
cout << s2.name << " " << s2.age << " " << s2.score << endl;
1.2.3 定义结构体变量时直接创建变量
struct Student
{
// 成员列表
string name; // 名字
int age; // 年龄
int score; // 分数
}s3; // 这里直接创建变量 s3
然后是赋值,访问
s3.name = "Rose";
s3.age = 35;
s3.score = 98;
cout << s3.name << " " << s3.age << " " << s3.score << endl;
同时:定义完数据类型后,使用结构体数据类型创建变量时可以不写struct,定义结构体时不能
如:
Student s4; // 而不是 struct Student s4;
1.3 结构体数组
作用:将结构体放入数组中以便使用
语法:struct 结构体名称 数组名称 [ 元素个数 ] = { { 值1 },{ 值2 }... };
举例:
首先是结构体类型的定义
struct Student
{
// 成员列表
string name; // 名字
int age; // 年龄
int score; // 分数
};
然后使用该类型创建结构体数组
// 创建结构体数组,并直接初始化
struct Student StrArray[3]
{
{"Joyce",21,200},
{"Tatina",20,190},
{"Rose",35,150}
};
打印成员
for (int i = 0; i < 3; i++)
{
cout << StrArray[i].name << " "
<< StrArray[i].age << " "
<< StrArray[i].score << endl;
}
同时,还可以在初始化后,再进行赋值
StrArray[2] = { "Baby",3,100 }; // 赋值
// 下面打印
for (int i = 0; i < 3; i++)
{
cout << StrArray[i].name << " " << StrArray[i].age << " " << StrArray[i].score << endl;
}
1.4 结构体指针
作用:使用指针访问结构体中的成员
ps:使用 操作符->
来访问结构体
首先,对于int a=20;
这样的变量a
,我们创建指针是int *p=&a;
表示数据类型是int
,所以用int*
类型的指针
因此:
struct Student s1 = { "Joyce",21,100 };
struct Student* ps = &s1;
s1
是struct Student
类型的,因此指针就是struct Student*
类型的,同时,可以省略struct
cout << ps->name << " " << ps->age << " " << ps->score << endl;
1.5 结构体嵌套结构体
原理:结构体中的成员可以是其他结构体
直接举例:一个老师带一个50人学生的班级。老师自己有姓名,id和年龄,以及学生结构体数组
首先是定义学生结构体类型
struct Student
{
// 成员列表
string name; // 名字
int age; // 年龄
int score; // 分数
};
然后定义老师结构体类型
struct Teacher
{ // 老师的成员列表
string name;
int id;
int age;
struct Student Array[50]; // 学生结构体数组
};
下面使用这两个类型来创建变量
Teacher T;
T.age = 35; T.id = 1993232913; T.name = "Knaz"; // 老师自己的数据
T.Array[0].age = 21; T.Array[0].name = "Tatina"; T.Array[0].score = 98; // 学生1
T.Array[1].age = 20; T.Array[1].name = "Joyce"; T.Array[1].score = 100; // 学生2
下面进行访问,打印
cout << T.age << " " << T.id << " " << T.name << endl; // 打印老师的数据
for (int i = 0; i < 50; i++)
{ // 打印老师里学生的数据
cout << T.Array[i].name << " " << T.Array[i].age << " " << T.Array[i].score << endl;
}
1.6 结构体做函数参数
作用:结构体作为参数向函数中传递
方式:值传递 / 址传递
举例:
首先创建结构体并创建变量并赋值
struct Student
{
// 成员列表
string name; // 名字
int age; // 年龄
int score; // 分数
};
Student s1 = { "Joyce",21,100 };
接下来,不在主函数中使用cout来打印s1中的数据,创建专门的Print打印函数
1.6.1 值传递
void Print1(Student s1)
{
s1.age = 100; // 修改age为100
cout << s1.age <<" "<< s1.name <<" "<< s1.score; // 直接打印传过来的s1中的数据
}
由此可见,在Print函数里进行修改,不会改变外面主函数的值
1.6.2 址传递
void Print2(Student *s1) // 传过来地址,所以要指针接收
{
s1->age = 200; // 修改age为200
cout << s1->age << " " << s1->name << " " << s1->score; // 直接打印传过来的s1中的数据
}
可以看到,主函数中age
也被修改
1.7 结构体中使用const
作用:使用const防止误改数据
举例
定义结构体并创建变量与初始化
struct Student
{
string name; // 名字
int age; // 年龄
int score; // 分数
};
Student s1 = { "Joyce",21,100 };
接下来使用值传递Print1
打印函数来查看s1
中的数据
void Print1(Student s1)
{
s1.age = 100;
cout << s1.age <<" "<< s1.name <<" "<< s1.score;
}
使用的是值传递,不会修改数据
但是,值传递的原理是拷贝一份数据的副本出来。当数据有成千上万份时,拷贝将会占用大量内存空间,降低运行效率。因此,我们采用址传递,这样,无论结构体中有多少数据,传过来并接收的只是一个指针,只需要4/8个字节空间
使用址传递:
void Print2(Student *s1)
{
s1->age = 200;
cout << s1->age << " " << s1->name << " " << s1->score;
}
不过,由于是址传递,如果里面有修改的操作,将使外面的数据发生改变,而我们本意并不想改变只是print
打印数据。
所以,在此基础上,我们在接收参数的地方加上const
void Print2(const Student *s1) // 加上const
{
// s1->age = 200;
cout << s1->age << " " << s1->name << " " << s1->score;
}
这时,s1
将无法被修改,若有修改的操作出现将直接报错,避免了对数据的误修改
1.8 示例
1.8.1 示例1
创建一个有3名老师的数组,每位老师是一个包含名字和学生结构体的结构体,学生结构体中有名字和分数。
学生与老师结构体:
struct Student // 学生结构体
{
string Sname;
int score;
};
struct Teacher // 老师结构体
{
string Tname;
struct Student Sarray[5];
};
给学生与老师赋值的函数
void AllocatorSpace(Teacher Tarray[], int size)
{
string NameSeed = "ABCDE";
for (int i = 0; i < size; i++)
{
// 给老师名字赋值
Tarray[i].Tname = "Teacher_";
Tarray[i].Tname += NameSeed[i];
// 给老师的学生赋值
for (int j = 0; j < 5; j++)
{
// 姓名赋值
Tarray[i].Sarray[j].Sname = "Student_";
Tarray[i].Sarray[j].Sname += NameSeed[j];
// 成绩赋值
int random = rand() % 61 + 40;
// 代表随机数40~100,不+40,则是0~60,不过要提前加随机数种子
Tarray[i].Sarray[j].score = random;
}
}
}
打印函数
void Print(Teacher Tarray[],int size)
{
for (int i = 0; i < size; i++)
{ // 先打印老师名字
cout << Tarray[i].Tname << endl;
for (int j = 0; j < 5; j++)
{ // 再打印学生数据
cout << "\t";
cout << Tarray[i].Sarray[j].Sname << " ";
cout << Tarray[i].Sarray[j].score << endl;
}
cout << endl;
}
}
主函数
srand((unsigned int)time(NULL)); // 随机数种子
Teacher Tarray[3];
int size = sizeof(Tarray) / sizeof(Tarray[0]);
AllocatorSpace(Tarray, size);
Print(Tarray,size);
1.8.2 示例2
创建一个包含5个人的结构体,内有姓名、性别与年龄,按照年龄大小进行升序排列,并打印输出
定义结构体
struct Hero
{
string name;
int age;
string sex;
};
主函数内创建结构体数组并赋值
struct Hero HeroArray[5]
{
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",20,"男"},
{"赵云",21,"男"},
{"貂蝉",19,"女"}
};
int size = sizeof(HeroArray) / sizeof(HeroArray[0]);
进行冒泡排序,以及打印函数
void BubbleSort(Hero HeroArray[], int size)
{
for (int i = 0; i < size - 1; i++)
{
for (int j = 0; j < size - i - 1; j++)
{
if (HeroArray[j].age > HeroArray[j + 1].age)
{
Hero tmp = HeroArray[j];
HeroArray[j] = HeroArray[j + 1];
HeroArray[j + 1] = tmp;
}
}
}
}
void Print(Hero HeroArray[], int size)
{
for (int i = 0; i < size; i++)
{
cout << HeroArray[i].name << " " << HeroArray[i].age << " " << HeroArray[i].sex << endl;
}
cout << endl;
}
主函数
Print(HeroArray, size);
cout << "排序后:" << endl << endl;
BubbleSort(HeroArray, size);
Print(HeroArray,size);