1、结构体基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
2、结构体定义和使用
语法: struct 结构体名 {结构体成员列表};
通过结构体创建变量的方式(3种)
- struct 结构体名 变量名
#include <iostream>
#include <string>
using namespace std;
//1、创建学生数据类型:学生包括(姓名,年龄,分数)
struct Student
{
//成员列表
string name;
int age;
int score;
};
//2、通过学生类型创建具体学生
int main() {
//2.1数据类型 变量名--》struct Student s1
struct Student s1;
//给S1属性赋值,访问结构体变量中的属性来选择赋值
s1.name = "张三";
s1.age = 19;
s1.score = 99;
//访问信息
cout << "姓名:" << s1.name << " "
<< "年龄:" << s1.age << " "
<< "分数:" << s1.score << " " << endl;
system("pause");
return 0;
}
-
数据类型 变量名={ …(包含初始值)}
#include <iostream> #include <string> using namespace std; //1、创建学生数据类型:学生包括(姓名,年龄,分数) struct Student { //成员列表 string name; int age; int score; }; //2、通过学生类型创建具体学生 int main() { //2.2数据类型 变量名={..赋初值} struct Student s2 ={.....} struct Student s2 = { "李四",20,89 }; //访问信息 cout << "姓名:" << s1.name << " " << "年龄:" << s1.age << " " << "分数:" << s1.score << " " << endl; system("pause"); return 0; }
- 定义结构体时顺便创建变量
#include <iostream>
#include <string>
using namespace std;
//1、创建学生数据类型:学生包括(姓名,年龄,分数)
struct Student
{
//成员列表
string name;
int age;
int score;
}s3;//顺便创建结构体变量
//2、通过学生类型创建具体学生
int main() {
//2.3在定义结构体时顺便创建结构体变量
s3.name = "老马";
s3.age = 20;
s3.score = 89;
cout << "姓名:" << s3.name << " " << "年龄:" << s3.age << " " << "分数:" << s3.score << " " << endl;
system("pause");
return 0;
}
总结:(1)定义结构体时的关键字是struct,不可以省略
(2)创建结构体变量时,关键字struct可以省略
(3)结构体变量使用操作符号”.“访问成员
3、结构体数组
**作用:**将自定义的结构体放入到数组中方便维护
**语法:**struct 结构体名 数组名[元素个数]={{},{}, … {}}
示例
#include <iostream>
#include <string>
using namespace std;
//结构体数组
//
//1、定义结构体
struct Student
{
//成员列表
string name;
int age;
int score;
};
//2、创建结构体数组
struct Student studArry[3] =
{
{"张三",19,98},
{"李四",20,88},
{"小马",21,100}
};
int main() {
//3、结构体数组中的元素赋值
//重新给数组下标为2的数组内容赋值
studArry[2].name = "赵三";
studArry[2].age = 30;
studArry[2].score = 90;
//4、遍历结构体数组
for (int i = 0; i < 3; i++) {
cout << "姓名:" << studArry[i].name
<< "年龄" << studArry[i].age
<< "分数" << studArry[i].score<< endl;
}
system("pause");
return 0;
}
4、结构体指针
作用:通过指针访问结构体中的成员
- 利用操作符->可以通过结构体指针访问结构体属性
**总结:**结构体指针可以通过->操作符来访问结构体中的成员
示例
#include<iostream>
#include <string>
using namespace std;
//结构体指针
//定义学生结构体
struct Student
{
string name;
int age;
int score;
};
int main() {
//1、创建学生结构体变量
struct Student s={"张三",19,90};
//2、通过指针指向结构体变量
struct Student *p = &s;
//3、通过指针访问结构体变量中的数据
//要通过结构体指针访问结构体中的属性,就需要利用"->"
cout << "姓名" << p->name << "年龄" << p->age << "分数" << p->score << endl;
system("pause");
return 0;
}
5、结构体嵌套结构体
**作用:**结构体中的成员可以是另一个结构体
**例如:**每个老师辅导一个学员,一个老师的结构体中,记录了一个学生的结构体
示例:
#include<iostream>
#include <string>
using namespace std;
//定义学生结构体-->因为在教师结构体里面嵌套学生结构体,所以就需要在教师结构体前面建立学生结构体
struct student
{
string name;
int age;
int score;
};
//定义老师结构体
struct teacher
{
int id;
string name;
int age;
struct student stu; //辅导的学生
};
int main() {
teacher t;
t.id = 63127;
t.name = "苟老师";
t.age = 22;
t.stu.name = "张三";
t.stu.age = 19;
t.stu.score=99;
cout << "老师姓名:" << t.name << "老师年龄:" << t.age << "老师工号:" << t.id<<endl
<< "学生名字:" << t.stu.name << "学生年龄:" << t.stu.age << "学生分数:" << t.stu.score << endl;
system("pause");
return 0;
}
6、结构体做函数参数
**作用:**将结构体作为参数像函数中传递
传递方式:(1)值传递、(2)地址传递
示例
(1)值传递
#include <iostream>
#include <string>
using namespace std;
//结构体做函数参数
//将学生传入到一个参数中,打印学生身上的所有信息
//定义学生结构体
struct student
{
string name;
int age;
int score;
};
//值传递
void printStudent1(struct student s) {
s.age = 200;
cout << "子函数中打印 姓名" << s.name << "年龄" << s.age << "分数" << s.score << endl;
}
int main() {
//创建结构体变量
struct student s;
s.name = "张三";
s.age = 20;
s.score = 99;
cout << "main函数中打印 姓名" << s.name << "年龄" << s.age << "分数" << s.score << endl;
printStudent1(s);
system("pause");
return 0;
}
(2)地址传递
#include <iostream>
#include <string>
using namespace std;
//结构体做函数参数
//将学生传入到一个参数中,打印学生身上的所有信息
//定义学生结构体
struct student
{
string name;
int age;
int score;
};
//打印学生信息的函数
//1、地址传递
void printStudent1(struct student *p) {
p->age = 300; //通过值传递方式改变了形参也就改变了实参
cout << "子函数中打印 姓名" << p->name << "年龄" << p->age << "分数" << p->score << endl;
}
int main() {
//创建结构体变量
struct student s;
s.name = "张三";
s.age = 20;
s.score = 99;
printStudent1(&s);
cout << "main函数中打印 姓名" <<s.name << "年龄" << s.age << "分数" << s.score << endl;
system("pause");
return 0;
}
**总结:**如果不修改主函数中的数据,用值传递,反之则用地址传递
7、结构体中const使用场景
**作用:**const来防止误操作
示例:
#include <iostream>
#include <string>
using namespace std;
//结构体做函数参数
//将学生传入到一个参数中,打印学生身上的所有信息
//定义学生结构体
struct student
{
string name;
int age;
int score;
};
//将函数中的形式参数改为指针,可以减少内存空间,而且不会复制新的副本出来
void printStudent(student *s) {
//未加入const
s->age = 350;
cout << "子函数中 姓名:" << s->name << "年龄:" << s->age << "得分:" << s->score << endl;
}
int main() {
//创建结构体变量
struct student s;
s.name = "张三";
s.age = 20;
s.score = 99;
//通过函数打印结构体变量信息
printStudent(&s);
cout << "main函数中 姓名" << s.name << "年龄" << s.age << "分数" << s.score << endl;
system("pause");
return 0;
}
由于使用地址传递,子函数修改了形式参数导致实参也发生了改变,为了避免由于地址传递修改了源数据,因此就需要引入const
加入const后
#include <iostream>
#include <string>
using namespace std;
//结构体做函数参数
//将学生传入到一个参数中,打印学生身上的所有信息
//定义学生结构体
struct student
{
string name;
int age;
int score;
};
//将函数中的形式参数改为指针,可以减少内存空间,而且不会复制新的副本出来
void printStudent(const student *s) {
//未加入const
//s->age = 350; //加入const之后,一旦修改的操作就会报错,可以防止我们的误操作
cout << "子函数中 姓名:" << s->name << "年龄:" << s->age << "得分:" << s->score << endl;
}
int main() {
//创建结构体变量
struct student s;
s.name = "张三";
s.age = 20;
s.score = 99;
//通过函数打印结构体变量信息
printStudent(&s);
cout << "main函数中 姓名" << s.name << "年龄" << s.age << "分数" << s.score << endl;
system("pause");
return 0;
}
8、结构体案例
(1)案例1
案例描述:学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员学生的成员有姓名,考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值最终打印出老师数据以及老师所带学生数据
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
struct student
{
string Sname;
int score;
};
struct teacher {
string Tname;
struct student Sarr[5];
};
//给老师和学生赋值
void allocateSpace(struct teacher Tarr[],int len) {
//给老师赋值
string nameSeed = "ABCDE";
for (int i = 0; i < 3; i++) {
Tarr[i].Tname = "Teacher_";
Tarr[i].Tname += nameSeed[i];
//通过循环给每名老师所带的学生赋值
for (int j = 0; j < 5; j++) {
Tarr[i].Sarr[j].Sname = "Student_";
Tarr[i].Sarr[j].Sname += nameSeed[j];
//生成随机数分数,范围为40~100之间
int random = rand() % 61 + 40;
Tarr[i].Sarr[j].score = random;
}
}
}
//打印所有人信息的函数
void printInfo(struct teacher Tarr[], int len){
for (int i = 0; i < len; i++) {
cout << "老师姓名:" << Tarr[i].Tname << endl;
for (int j = 0; j < 5; j++) {
cout << "\t学生姓名:" << Tarr[i].Sarr[j].Sname
<<"考试分数:" << Tarr[i].Sarr[j].score << endl;
}
}
}
int main() {
//随机数种子
srand((unsigned int)time(NULL));
//1、创建3名老师的数组
struct teacher Tarr[3];
int len = sizeof(Tarr) / sizeof(Tarr[0]);
//2、通过函数给3名老师的信息赋值,并给老师带的学生信息赋值
//开辟一段空间存放老师信息
allocateSpace(Tarr, len);
//3、打印所有老师及所带的学生信息
printInfo(Tarr, len);
system("pause");
return 0;
}
案例2
案例描述:
设计一个英雄的结构体,包括成员姓名,年龄,性别,创建结构体数组存放5名英雄。通过冒泡排序算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果
#include <iostream>
#include <string>
using namespace std;
//1、创建英雄属性结构体
struct herO{
string name;
int age;
string sex;
};
//3、冒泡排序,实现年龄升序排列
void bubbleSort(struct herO tarr[], int len) {
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - i - 1; j++) {
if (tarr[j].age > tarr[j + 1].age) {
struct herO temp = tarr[j ];
tarr[j] = tarr[j + 1];
tarr[j + 1] = temp;
}
}
}
}
//4、将排序后结果打印输出
void peintH(struct herO tarr[], int len) {
for (int i= 0; i < len; i++) {
cout << "姓名:" << tarr[i].name << "年龄:" << tarr[i].age << "性别:" << tarr[i].sex << endl;
}
}
int main() {
//2、创建数组存放5名英雄
struct herO tarr[5] = {
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",20,"男"},
{"赵云",21,"男"},
{"貂蝉",19,"女"}
};
int len = sizeof(tarr) / sizeof(tarr[0]);
//调用冒泡排序,实现年龄升序排列函数
bubbleSort(tarr, len);
//调用将排序后结果打印输出函数
peintH(tarr, len);
system("pause");
return 0;
}