一、结构体的基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
二、结构体定义和使用
语法:struct 结构体名 {结构体成员列表};
- struct 结构体名 变量名
- struct 结构体名 变量名 = {成员1值,成员2值}
- 定义结构体时顺便创建变量
1、创建学生数据j结构类型 : 学生包括(姓名, 年龄, 分数)
//自定义数据类型,一些类型集合组成的一个类型
//语法 struct 类型名称 { 成员列表}
struct student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
}s3;
2、通过学生结构类型从创建具体学生
int main()
{
//2.1 struct 结构体名 变量名
(struct) student s1;
//给s1属性赋值,通过.访问结构体变量中的属性
s1.name = "张三";
s1.age = 18;
s1.score = 100;
cout<<"姓名:"<<s1.name<<"年龄:"<<s1.age<<"分数:"<<s1.score<<endl;
//2.2 struct 结构体名 变量名 = { 成员1值,成员2值}
(struct) student s2 = { "李四", 19, 90};
cout<<"姓名:"<<s2.name<<"年龄:"<<s2.age<<"分数:"<<s2.score<<endl;
//2.3 定义结构体时顺便创建变量
s3.name = "王五";
s3.age = 20;
s3.score = 70;
cout<<"姓名:"<<s3.name<<"年龄:"<<s3.age<<"分数:"<<s3.score<<endl;
}
也可以通过下面方式为学生结构体成员赋初值:
struct student
{
string name;
int age;
int score;
}stu = { "ZhangSan" , 18, 100}; //定义类型的同时 定义变量并初始化
或
struct student
{
string name;
int age;
int score;
student() :name("ZhangSan"), age(18),score(100)
{
}
};
三、结构体数组
1、定义结构体
struct student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
};
2.、创建结构体数组并给结构体中的元素赋初值
int main()
{
struct student stuArray[3] =
{
{ "张三", 19, 90},
{ "李四", 18, 100},
{ "王五", 20, 80},
}
}
3、遍历结构体数组
for (int i = 0; i<3; i++)
{
cout<<"姓名:"<<stuArray[i].name<<"年龄:"<<stuArray[i].age<<"分数:"<<stuArray[i].score<<endl;
}
四、结构体指针
struct student
{
string name;
int age;
int score;
}stu= { "张三", 19, 90},*pStu ; //定义类型的同时 定义变量和赋初始值 并定义指针
int main()
{
pStu = &stu
cout<<"姓名:"<<pStu->name<<"年龄:"<<pStu->age<<"分数:"<<pStu->score<<endl;
}
结构体指针的一般形式为:struct 结构名 *结构变量指针名
这里注意的是结构体指针变量需要先赋值之后才可以去使用。pStu = &stu 是正确的,但 pStu =&student 是错误的。
因为结构名和结构变量是两个不同的概念。结构名只能表示一个结构形式,编译系统并不对它分配内存空间。只有当某变量被说明为这种类型的结构时,才对该变量分配存储空间。因此上面&Teacher这种写法是错误的,不可能去取一个结构名的首地址。有了结构指针变量,就能更方便地访问结构变量的各个成员。
五、结构体嵌套结构体
定义学生结构体:
struct student
{
string name;
int age;
int score;
}
定义老师结构体:
//定义老师结构体
struct teacher
{
int id;
string name;
int age;
student stu;
}
//访问老师中的结构体成员:
int main()
{
teacher t;
t.id = 10086;
t.name = "老王";
t.age = 50;
t.stu.name = "小王";
t.stu.age = 20;
t.stu.score = 90;
cout<<"老师编号:"<<t.id<<"老师姓名:"<<t.name<<"老师年龄:"<<t.age"老师学生姓名:"<<t.stu.name<<endl;
}
六、结构体做函数参数
作用:将结构体作为参数向函数传递
传递方式有两种:
- 值传递
- 地址传递
定义学生结构体:
struct student
{
string name;
int age;
int score;
}
打印学生信息的子函数(值传递)
void printStudent1(student s)
{
s.age = 40; //这里修改结构成员age 的值后,主函数调用该函数时,age 的值更新为40,但最终打印s1.age时,age 值不会改变。
cout<<"姓名:"<<s.name<<"年龄:"<<s.age<<"分数:"<<s.score<<endl;
}
打印学生信息的子函数(地址传递)
void printStudent1(student * s)
{
s->age = 40;//这里修改结构成员age 的值后,主函数调用该函数和最终打印s1->age时,age的值都会更新为40.
cout<<"姓名:"<<s->name<<"年龄:"<<s->age<<"分数:"<<s->score<<endl;
}
主函数调用子函数,打印学生信息的三种方式
int mian
{
student s1;
s1.name = "张三";
s1.age = 18;
s1.score = 100;
//法一:值传递
printStudent1(s1);
//法二:地址传递
printStudent1(&s1);
//法三:直接打印,使用值传递时,这里不会改变;使用地址传递时,如果子函数中成员发生改变,这里也会相应改变
cout<<"姓名:"<<s1.name<<"年龄:"<<s1.age<<"分数:"<<s1.score<<endl;
}
值传递和地址传递的区别就是,使用值传递时,如果在子函数中对结构成员变量数值进行更改,不会更新结构成员的初始值,只会在调用该子函数的时候,更新结构成员的初始值。而地址传递在子函数中对结构成员变量数值进行更改,函数的初始值会相应更新。
总结:如果不想修改主函数中的值,用值传递,反之用地址传递。
七、结构体中const使用场景
作用:用const来防止误操作()
const 使用场景:
struct student
{
string name;
int age;
int score;
}stu = { "张三", 19, 90} ;
这里采用地址传递,将函数中的形参改为指针,这样可以减少内存,因为指针只占四个字节,而且不会像值传递那样,复制一个新的结构成员副本出来。
但是虽然使用地址传递可以不用将成员信息全部都复制一遍,减少内存,但是为了防止在子函数中修改成员变量的值,导致主函数中成员变量的值发生改变,这里可以加上const
void printStudents(const student *s)
{
//s->age = 35; //加入const ,这时修改age的值就会报错,可以防止我们的误操作
cout<<"姓名:"<<s->name<<"年龄:"<<s->age<<"分数:"<<s->score<<endl;
}
总结:const 的使用就是又想使用指针传递,又怕误操作修改了子函数中的结构成员参数值,导致主函数中的结构成员参数值发生改变,即结构成员初始值发生改变。所以加上了const ,保证子函数只读不写(写的时候s->age会提示报错)。
戳戳小手帮忙点个免费的赞和关注吧,嘿嘿。 |