C++学习笔记(6)
学习是一件任重而道远的事情,与其焦虑不如动手起来,借助平台记录自己学习笔记,希望和大家多多交流,今天又是努力成为程序媛的一天!
13.结构体
13.1结构体基本概念
作用:结构体是用户自定义的数据类型,允许用户存储不同的数据类型
13.2结构体定义和使用
语法:struct 结构体名 {结构体成员列表};
通过结构体创建变量的方式有三种:
- struct 结构体名 变量名
- struct 结构体名 变量名 = {成员1值,成员2值…}
- 定义结构体时顺便创建变量
#include<iostream>
using namespace std;
#include<string>
//结构体定义
//1.创建学生数据类型;学生包括(姓名,年龄,分数)
//自定义数据类型 一些类型
struct student {
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
}s3;//顺便创建变量
int main(void) {
//2.创建结构体变量
//2.1 struct 结构体名 变量名
//struct创建变量可以省略,定义时不可省
struct student s1;
s1.name = "张三";
s1.age = 20;
s1.score = 69;
cout << "姓名:" << s1.name << " " << "年龄:" << s1.age << " " << "分数:" << s1.score;
cout << endl;
//2.2 struct 结构体名 变量名 = {值1,值2...}
struct student s2 = { "李四",22,89 };
cout << "姓名:" << s2.name << " " << "年龄:" << s2.age << " " << "分数:" << s2.score;
cout << endl;
//2.3定义结构体顺便创建变量
s3.name = "王五";
s3.age = 22;
s3.score = 109;
cout << "姓名:" << s3.name << " " << "年龄:" << s3.age << " " << "分数:" << s3.score;
cout << endl;
return 0;
}
运行结果:
注意:
- 定义结构体时关键词struct不可以省略
- 创建结构体变量时,关键词struct可以省略
- 结构体变量利用操作符“."访问成员
13.3结构体数组
意义:将自定义的结构体放入数组中方便维护
语法:
struct 结构体名 数组名[元素个数] = { {},{},…{} }
#include<iostream>
using namespace std;
#include<string>
//结构体数组
//1.定义结构体
//1.创建学生数据类型;学生包括(姓名,年龄,分数)
//自定义数据类型 一些类型
struct student {
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
};//顺便创建变量
int main() {
//2.创建结构体数组
struct student stArray[3] = { {"张三",22,96},{"李四",21,65},{"王五",25,76} };
//3.给结构体数组中元素赋值或更改初始值
stArray[2].name = "赵六";
stArray[2].age = 23;
stArray[2].score = 89;
//4.遍历结构体数组
for (int i = 0; i < 3; i++) {
cout << "姓名:" << stArray[i].name << " 年龄:" << stArray[i].age << " 分数:" << stArray[i].score << endl;
}
system("pause");
return 0;
}
运行结果:
13.4结构体指针
作用:通过指针访问结构体中的成员
- 使用操作符->
- 可以通过结构体指针访问结构体属性
- 由于s是struct student数据类型的,所以指针前面返回应该也是这个数据类型,其次,struct在创建和指针指向时都可以省略不写
#include<iostream>
using namespace std;
#include<string>
//结构体数组
//1.定义结构体
//1.定义学生数据类型;学生包括(姓名,年龄,分数)
//自定义数据类型 一些类型
struct student {
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
};
int main() {
//2.创建结构体变量
struct student s = {"张三",22,96};
//3.通过指针指向结构体变量
student* p = &s;//由于s是struct student数据类型的,所以指针前面返回应该也是这个数据类型,其次,struct在创建和指针指向时都可以省略不写
//4.通过指针访问结构体里的变量
//->符号用来指针访问结构体变量
cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl;
system("pause");
return 0;
}
运行结果:
13.5结构体嵌套结构体
作用:结构体的成员可以是另一个结构体
举例:每个老师辅导一个学员,一个老师的结构体,记录一个学生的结构体
#include<iostream>
using namespace std;
#include<string>
//学生结构体定义
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 = 10086;
t.name = "芳老师";
t.age = 45;
t.stu.age = 22;//前面struct Student是自定义的数据类型;t.即定位到教师结构体中,再t.stu就可以创建学生结构体变量了
t.stu.name = "小王";
t.stu.score = 89;
cout << "姓名: " << t.name << " 职工编号:" << t.id << " 年龄:" << t.age
<< " 学生姓名:" << t.stu.name << " 学生年龄:" << t.stu.age << " 分数:" << t.stu.score << endl;
system("pause");
return 0;
}
运行结果:
- 在结构体中可以定义另一个结构体作为成员,解决实际问题
13.6结构体做函数参数
作用:将结构体作为参数向函数中传递
传递方式:
1.值传递 2.地址传递
#include<iostream>
using namespace std;
#include<string>
//学生结构体定义
struct Student {
//成员列表
string name;
int age;
int score;
};
//创建一个函数
//1.值传递
void Return1(Student t) {
//在值传递中修改变量值
//t.age = 200;//结果该函数打印发生了变化,主函数实参依旧不变
cout << "Return1函数打印结果:\t " << " 姓名: " << t.name << " 年龄:" << t.age
<< " 分数:" << t.score << endl;
}
//2.指针传递
void Return2(Student* p) {
//在指针传递中修改变量值
//p->age = 33;//结果该函数和实参main函数打印都变了
cout << "Return2函数打印结果:\t " << " 姓名: " << p->name << " 年龄:" << p->age
<< " 分数:" << p->score << endl;//记住指针用的是->符号
}
int main() {
//使用结构体作为函数参数
struct Student t = { "张三",22,96 };
Return1(t);//调用函数
Return2(&t);//指针传递传入地址
cout << "主函数打印结果: \t " << " 姓名: " << t.name << " 年龄:" << t.age
<< " 分数:" << t.score << endl;
system("pause");
return 0;
}
运行结果:
- 在值传递中修改变量值年龄为200,看main函数和值传递函数结果:
【主函数没有改变,仅定义函数改变】
- 在指针传递中修改变量值年龄为100,看main函数和值传递函数结果:
【主函数和定义函数全改变】
运行结果:
- 如果不想修改主函数的数据就用值传递,否则用指针传递
13.7结构体中const使用场景
作用:用const来防止误操作
#include<iostream>
using namespace std;
#include<string>
//学生结构体定义
struct Student {
//成员列表
string name;
int age;
int score;
};
void Return(const Student *t) {//加上const变为常量指针
//使用指针传递
//t->age = 200;//将函数形参改为指针,可以减少内存空间,不会复制新的副本出来
//加入const之后,一旦修改t操作就会报错,防止wucaoz
cout << "Return函数打印结果:\t " << " 姓名: " << t->name << " 年龄:" << t->age
<< " 分数:" << t->score << endl;
}
int main() {
//结构体中const使用场景
//创建结构体变量
struct Student t = { "张三",22,96 };
Return(&t);//调用函数
cout << "主函数打印结果: \t " << " 姓名: " << t.name << " 年龄:" << t.age
<< " 分数:" << t.score << endl;
system("pause");
return 0;
}
运行结果:
几点注意:
- 函数参数使用结构体采取值传递时,会复制很多和结构体相同的变量用来存储即产生很多副本,里面含有和结构体同样的大小,而使用指针作为函数形参,可以减少内存空间,一个指针占8个字节(64位系统,32位是4),极大地减少内存空间
- 在形参中使用const即常量指针,之后函数中就不可以修改指针的属性,只能对它进行读的操作,无法更改,会报错
- 加入const,一旦有修改就报错,防止误操作,把主函数原本的参数改掉
13.8结构体案例
13.8.1结构体案例1※
#include<iostream>
using namespace std;
#include<string>
#include<ctime>
//学生结构体定义
struct StudentArray {
//成员列表
string name;
int score;
};
//老师结构体定义
struct TeacherArray {
string name;//老师姓名
struct StudentArray stuarray[5];//嵌套学生结构体,学生信息
};
//定义赋值老师和学生的值
void allocateSpsce(TeacherArray tarray[],int len) {
string nameSeed = "ABCDE";
//给老师赋值
for (int i = 0; i < len; i++) {
tarray[i].name = "Teacher_";//TeacherArray tarray[i]. name = "Teacher_"这样会报错,数组赋值的时候直接数组名.属性即可 不需要加数据类型
tarray[i].name += nameSeed[i];
//给学生赋值
for (int j = 0; j < 5; j++) {
int random = rand() % 61 + 40;//40-100
tarray[i].stuarray[j].name = "Student_";
tarray[i].stuarray[j].name += nameSeed[j];
tarray[i].stuarray[j].score = random;
}
}
}
void Printfio(TeacherArray tarray[],int len) {
for (int i = 0; i < len; i++) {
cout << "老师姓名: " << tarray[i].name << endl;
for (int j = 0; j < 5; j++) {
cout << " 学生姓名:" << tarray[i].stuarray[j].name << " 分数:" << tarray[i].stuarray[j].score << endl;
}
}
}
int main() {
//随机种子
srand((unsigned int)time(NULL));
//结构体嵌套结构体
//创建教师结构体
TeacherArray tarray[3];
int len = sizeof(tarray) / sizeof(tarray[0]);
allocateSpsce(tarray, len);
Printfio(tarray,len);
system("pause");
return 0;
}
运行结果:
attention:
- 整体框架:1.有两个结构体定义,其中一个嵌套另一个,2.然后创建两个结构体变量,被嵌套的结构体变量在另一个结构体中创建的,另一个是在main函数中创建,3.之后对其赋值,创建赋值函数,传递数组指针,传入数组名即地址,属性赋值时,直接数组名[i].属性
- 结构体嵌套结构体,两个结构体都要定义,定义结构体时,struct必须要有,在结构体里创建别的结构体,结构体创建的时候struct可以省略
- 创建结构体数组,数据类型 数组名[x];结构体里创建 结构体数组,其中x为有几个这样的结构体
- 随机数int random = rand() % 60表示值在0-59,不过这是伪随机数
- 主函数加上时间戳srand((unsigned int)time(NULL));就可以产生随机数了,记得头文件加#include < ctime >
- 字符串也可以下标引用它的第几个字符
13.8.2结构体案例2
#include<iostream>
using namespace std;
#include<string>
#include<ctime>
//英雄结构体定义
struct HeroArray {
//成员列表
string name;//成员姓名
int age;//年龄
string sex;//性别
};
//定义升序排序函数
//冒泡排序,外层循环管总体交换次数,内层循环管每一次/行交换次数
//外层循环循环次数为元素个数-1
//内层循环次数为元素个数-外层循环次数-1
void bubbleSort(HeroArray heros[], int len) {
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - i - 1; j++) {
if (heros[j].age > heros[j + 1].age) {//比较前后相邻两个年龄大小
HeroArray temp = heros[j];//创建同数据类型变量完成两个结构体数组变量元素的互换
heros[j] = heros[j + 1];
heros[j + 1] = temp;
}
}
}
}
//定义打印函数
void Printfio(HeroArray heros[], int len) {
for (int i = 0; i < len; i++) {
cout << "英雄名:" << heros[i].name << " 年龄" << heros[i].age << " 性别:" << heros[i].sex << endl;
}
}
int main() {
//创建一个结构体数组
HeroArray heros[5] = {
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",20,"男"},
{"赵云",21,"男"},
{"貂蝉",19,"女"},
};
//定义长度
int len = sizeof(heros) / sizeof(heros[0]);
bubbleSort(heros, len);//调用函数
Printfio(heros, len);
system("pause");
return 0;
}
运行结果:
第六篇笔记到此结束,C++基础学习会持续更新在C++学习笔记合集中,当作学习笔记复习,如果能帮助其他小伙伴就更好了。
笔记是看黑马程序C++时做的记录,笔记中如果有错误和改进的地方,欢迎大家评论交流,up up up!!!
学习原视频来自:黑马程序员C++从0到1