持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
前言
接着上次讲的结构体内容,下篇主要讲解结构体指针、结构体中const的使用,结构体和函数组合(做函数参数)、以及案例来巩固知识。
一、结构体指针
1、创建结构体
示例:
struct student
{
string name;//姓名
int age;//年龄
int score;//分数
};
2、使用指针赋值
示例://1、创建学生结构体变量
student s = { "韩信",18,99 };
//2、通过指针指向结构体变量
student* p = &s;
这里有两点需要注意:1、指针变量前面的struct省略了 2、引用学生结构体属性的时候不是用” .“而是用” ->“有时候编译器不提醒,家人们要注意。
二、结构体中const的使用
1、const 关键字的作用
-
可以定义const常量,具有不可变性。
例如:const int Max=100; Max++会产生错误; -
便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患。
例如: void fun(const int i) { .........} 编译器就会知道i是一个常量,不允许修改; -
可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改。 同宏定义一样,可以做到不变则已,一变都变!
如 1 中,如果想修改Max的内容,只需要它修改成:const int Max=what you want;即可! -
可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。 还是上面的例子,如果在函数体内修改了i,编译器就会报错,也叫只读性;
例如: void f(const int i) { i=10;//error! }
-
可以节省空间,避免不必要的内存分配。和#dedine M 8 类似,我们可以直接写成 const int M =8;而且 #define 在内存中有多份拷贝, const 定义常量仅有一份拷贝,无疑可以提高运行效率。
2、具体使用
struct student
{
string name;
int age;
int score;
};
void printStudent(const student *s) {
//s->age = 150; 加入const后程序会报错,此时函数只能读取而不能修改,防止出现误操作
cout << "姓名:" << s->name << " 年龄:" << s->age << endl;
}
int main()
{
student s1 = { "张三",18,88 };
printStudent(&s1);
}
这里简单的定义了学生结构体和打印信息 printfStudent(const student *s) 方法,主函数传入结构体变量的地址,对应形参的结构体指针类型,如果修改name 属性,编译器会告诉你错误::“表达式必须是可修改的左值”,意思我们无法修改s1的所有属性,只能读取,从而防止出现误操作。
三、结构体做函数参数
1、说明
顾名思义,我们需要创建结构体变量,然后将结构体变量传入函数里面,我准备了值传递和地址传递两种,顺便比较二者的区别,代码如下:
struct student
{
string name;
int age, score;
};
void printStudent1(student s) {
s.name = "李白";
cout<< "printfStudent1中 姓名:" << s.name << "年龄:" << s.age
<< "分数:" << s.score << endl;
}
void printStudent2(student* p)
{
p->name = "韩信"; p->age = 38;
cout << "printfStudent2中 姓名:" << p->name << "年龄:" << p->age
<< "分数:" << p->score<< endl;
}
int main()
{
student s = { "张三",21,99 };
cout << "在main函数中打印学生信息:" << "姓名:" << s.name
<< "年龄:" << s.age << "分数:" << s.score << endl;
printStudent1(s);//pS1为值传递,不改变实参的值
cout << "值传递后姓名为:" << s.name << endl;
printStudent2(&s);
cout << "地址传递后姓名:" << s.name << endl;//pS2为地址传递,改变实参的值
}
这里创建结构体变量的时候就给s 赋值,经过printfStudent1()方法后姓名仍然不变,想必大家看过我上次的文章“详解函数的三种传参方式”后,可以很好理解其中的原因。经过printfStudent2()方法后姓名就会改变,因为传参传的是地址,不会像值传递那样拷贝副本。
2、输出结果
四、结构体案例
最后来个小案例巩固技能:按年龄大小输出一个人物数组的所有信息,提示:冒泡排序加结构体即可。代码如下:
#include<iostream>
using namespace std;
#define N 5
struct DInfo
{
string Name;
string Sex="男";
float Age;
DInfo(string name = "0", float age = 0)
{
Name = name; Age = age;
}
};
DInfo D[N] = {DInfo("张飞",20.8),DInfo("赵云",22.3),DInfo("韩信",20.1)
,DInfo("树叶",23),DInfo("耀杨",20.0) };
void StructArray(DInfo *D, int len)
{
for (int i = 0; i < N - 1; i++)
for (int j = 0; j < N - i - 1; j++)
{
if (D[j].Age > D[j + 1].Age)
{
DInfo temp;
temp = D[j + 1]; D[j + 1] = D[j]; D[j] = temp;
}
}
}
int main()
{
int len = sizeof(D) / sizeof(D[0]);
StructArray(D, len);
cout << "按年龄从小到大输出所有成员信息:\n";
for (int i = 0; i < N; i++) {
cout << "姓名\t" << D[i].Name << "\t性别\t"
<< D[i].Sex << " 年龄\t" << D[i].Age << endl;
}
system("pause");
}
总结
到这里结构体相关知识就暂时告一段落了,但是我们的脚步永远都不会停下,后面我会更Visual Stdio 的函数分文件编写和用结构体实现一个通讯录管理系统,我们不见不散