一.结构体基本概念
是用户自定义的一种数据类型
二.结构体的定义和使用
定义:struct 结构体名{结构体成员列表};
这里本身不分配空间,只有创建了变量才会分配空间
结构体变量的创建(三种方式)
1.struct 结构体名 变量名;
2.struct 结构体名 变量名={成员1;成员2;成员3...}
3.定义结构体时顺便创建变量
struct makabaka
{int num;
char【12】name;
}wuxidixi;
三.结构体数组
作用:将自定义的结构体放入到数组中方便维护
语法:struct 结构体名 数组名【元素个数】={ {},{},{} }
#include<iostream>
#include<cstring>
using namespace std;
//结构体数组
//1.定义结构体
struct student
{
string name;
int age;
int score;
} ;
int main()
{
//2.创建结构体数组
struct student stuarray[3]=
{
{"zhangsan",18,100 },{"lisi",28,99},{"wangwu",38,66}
};
//3.给结构体中的元素赋值(后期修改)
stuarray[2].name="zhaoliu";
stuarray[2].age=80;
//4.遍历结构体数组 (利用for循环)
for(int i=0;i<3;i++)
{
cout<<"姓名"<<stuarray[i].name<<endl;
cout<<"年龄"<<stuarray[i].age<<endl;
cout<<"分数"<<stuarray[i].score<<endl;
}
return 0;
}
三.结构体指针
作用:通过指针访问结构体中的成员
·利用操作符->可以通过结构体指针访问结构体属性
用指针来使用变量时,作实参,则修改形参能达到修改实参的作用。直接用变量则不具有此效果。因为指针作实参传递的是地址。(可以直接修改变量)
int i=10; //定义一个整型变量i值为10
int *p=&i; //定义一个整型指针变量p并指向变量i,注意只有类型相同的才可以指。
cout<<*p<<endl; //输出p指向的变量i的值,加*号就表示输出的是指针指向变量的值。
cout<<p<<endl; //输出p指向变量i的地址,不加* 号代表的是p本身的值。
*p=20; //因为加了* 号代表的是p指向变量的值,所以可能通过这样修改变量i的数据。
//此时i的值就通过指针p修改为20
#include<iostream>
#include<iomanip>
using namespace std;
//结构体指针
struct student
{
string name;
int age;
int sorce;
};
int main(){
//创建学生结构体变量
struct student s={"张三",18,100};
//通过指针指向结构体变量
//int*p=&s;(不可以,等号左右侧不兼容)
struct student*p=&s;//struct可以省略 ,必须是同种变量才可以用指针
//通过指针访问结构体变量中的数据
//如果要访问结构体变量
cout<<s.name<<endl;
//如果是指针
cout<<"姓名"<<p->name<<"年龄"<<p->age<<"分数"<<p->sorce<<endl;
return 0;
}
)运行结果如下
四.结构体嵌套结构体(禁止套娃!!!)
作用:结构体中的成员可以是另一个结构体
eg:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
#include<iostream>
#include<iomanip>
using namespace std;
//需要 先定义 学生结构体
struct student
{
string name;
int age;
int sorce;
};
//定义老师结构体
struct teacher
{
int id;
string name;
int age;
struct student stu;//辅导的学生
} ;
int main(){
//创建老师
teacher t;
t.id=10000;
t.name="老王";
t.age=50;
t.stu.age=18;
t.stu.name="小王";
t.stu.sorce=60;
cout<<"老师姓名"<<t.name<<"老师编号"<<t.id<<"老师年龄"<<t.age<<endl;
cout<<"老师辅导学生的姓名"<<t.stu.name;
return 0;
}
五.结构体作函数参数
作用:将结构体作为参数向函数中传递
传递方式:1.值传递 (形参改变实参不变)
2.地址传递(形参改变实参也改变)
1.值传递
#include<iostream>
#include<iomanip>
using namespace std;
struct student
{
string name;
int age;
int score;
};
//定义一个函数(要放在结构体后面)
void student1(struct student s)
{
//1.值传递
s.age=100;//将变量进行修改,子函数打印是100,但是在main函数中打印仍为20
cout<<"子函数中姓名"<<s.name<<"年龄"<<s.age<<"分数"<<s.score <<endl;
}
int main()
{
//将学生传入到一个参数中,打印学生身上的所有信息
struct student s;
s.name="张三";
s.age=20;
s.score=85;
cout<<"main函数中打印 姓名 "<<s.name<<"年龄"<<s.age<<"分数"<<s.score<<endl;
//将学生传入到一个参数中,通过函数打印
student1(s);
return 0;
}
运行结果
2.地址传递
#include<iostream>
#include<iomanip>
using namespace std;
struct student
{
string name;
int age;
int score;
};
//2.地址传递
void student2(struct student*p) //利用指针来接收地址
{
p->age=200;
cout<<"子函数2中姓名"<<p->name<<"年龄"<<p->age<<"分数"<<p->score<<endl;
}
int main()
{
//将学生传入到一个参数中,打印学生身上的所有信息
struct student s;
s.name="张三";
s.age=20;
s.score=85;
student2(&s);//地址传递首先要取指
cout<<"main函数中打印 姓名 "<<s.name<<"年龄"<<s.age<<"分数"<<s.score<<endl;
//将学生传入到一个参数中,通过函数打印
return 0;
}
运行结果
六.结构体中const使用场景
作用:只读状态,用const来防止误操作
加入const之后,一旦有修改的操作就会报错,提示你不可修改
一般用于函数调用时
#include<iostream>
#include<cstring>
using namespace std;
//const
struct student
{
string name;
int age;
int score;
};
//void print(student s)
//{ //是值传递,不改变实参 但是如果数据量大,占用内存空间多
// cout<<"姓名"<<s.name<<"年龄"<<s.age<<"得分"<<s.score<<endl;
//}
//int main()
//{
// struct student s={"zhangsan",15,70};
// print(s);
// return 0;
// //通过函数打印结构体变量信息
//
// }
void print(const student *s) //一个指针只占四个字节 ,将函数中的形参改为指针,可以减少内存空间而且不会复制新的副本
{ s->age=150; //但是地址传递不小心把实参给改了为了避免用const
cout<<"姓名"<<s->name<<"年龄"<<s->age<<"得分"<<s->score<<endl;
}
int main()
{
struct student s={"zhangsan",15,70};
print(&s);
return 0;
//通过函数打印结构体变量信息
}
注:指针可以减少内存占用量
运行结果:报错