跳到主要内容C++ 结构体基础用法与排序实现 | 极客日志C++算法
C++ 结构体基础用法与排序实现
C++ 结构体是一种自定义数据类型,用于描述复杂对象。本文涵盖结构体的定义、成员访问(点号与箭头)、初始化方式及嵌套结构处理。重点讲解结构体的成员函数、构造函数与析构函数的自动调用机制,以及运算符重载以支持标准输出流。此外,介绍了利用 STL 中的 sort 函数对内置类型及自定义结构体数据进行排序的方法,包括比较函数与仿函数的使用。
清心1 浏览 1. 结构体类型
结构体是一个自定义的类型。使用自定义类型可以描述一些复杂对象,比如描述人、书。
创建结构体使用 struct 关键字。
struct Stu {
};
示例:
struct Stu {
string name;
int chinese;
int math;
int total;
};
2. 结构体的使用
结构体直接访问内部成员变量用点号 (.) 运算符。指针访问内部成员变量用箭头运算符 ->。
struct Student {
char* name;
int age;
};
要使用结构体类型数据,首先要将结构体数据实例化:
struct Student s1;
然后有一个结构体指针类型指向原来的 s1:
struct Student* PS1 = &s1;
最后,访问结构体成员变量:
PS1->name = "zhangsan";
PS1->age = 18;
3. 结构体的初始化
结构体的初始化和数组类似,使用 {},将初始化的内容按顺序放到 {} 里。
struct Stu {
string name;
int chinese;
int math;
int total;
};
struct Stu s2 = {"zhangsan", 100, 80, 180};
4. 结构体的嵌套
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
如果结构体中嵌套了其他结构体成员,这里初始化的时候,也可以在 {} 中嵌套 {},访问嵌套成员中的成员可以连续使用 . 操作符。例如:
struct Score {
int chinese;
int math;
int english;
};
struct Stu {
string name;
struct Score score;
int total;
int avg;
};
int main() {
struct Stu s = {"wangwu", {80, 90, 100}, 0, 0};
s.total = s.score.chinese + s.score.english + s.score.math;
s.avg = s.total / 3;
cout << s.total << endl;
return 0;
}
5. 结构体的成员函数
5.1 默认成员函数
C++ 的结构体会有一些默认的成员函数,比如构造函数、析构函数等,是编译器默认生成的。如果觉得不合适,可以自己显式地定义这些函数,这些函数都是自动被调用,不需要手动调用。
这些成员函数可以直接访问成员变量,调用也使用 . 操作符。
#include <iostream>
#include <string>
using namespace std;
struct Stu {
string name;
int chinese;
int math;
int total;
void init_stu() {
name = "小明";
chinese = 100;
math = 100;
total = chinese + math;
}
void print_stu() {
cout << "名字:" << name << endl;
cout << "语文:" << chinese << endl;
cout << "数学:" << math << endl;
cout << "总成绩:" << total;
}
};
int main() {
struct Stu s1;
s1.init_stu();
s1.print_stu();
return 0;
}
5.2 构造函数和析构函数
构造函数是结构中默认的成员函数之一,主要任务是初始化结构体变量。写了构造函数,就不需要再写其他成员函数来初始化 (类) 的成员,而且构造函数是在结构变量创建的时候,编译器自动被调用的。
- 函数名与结构体 (类) 名相同。
- 无返回值。
- 构造函数可以重载。
若未显式定义构造函数,系统会自动生成默认的构造函数。
#include <iostream>
#include <string>
using namespace std;
struct Stu {
string name;
int chinese;
int math;
int total;
Stu() {
name = "小明";
chinese = 100;
math = 100;
total = chinese + math;
}
void print_stu() {
cout << "名字:" << name << endl;
cout << "语文:" << chinese << endl;
cout << "数学:" << math << endl;
cout << "总成绩:" << total;
}
};
int main() {
struct Stu s1;
s1.print_stu();
return 0;
}
析构函数是用来完成结构体变量中资源的清理工作,也是结构体中默认的成员函数之一。析构函数在结构体变量销毁的时候,被自动调用的。
- 析构函数名是在结构体 (类) 名前加上字符 ~。
- 无参数无返回值类型。
- 一个类只能有一个析构函数。若未显式定义析构函数,系统会自动生成默认的析构函数。
- 注意:析构函数不能重载。
#include <iostream>
#include <string>
using namespace std;
struct Stu {
string name;
int chinese;
int math;
int total;
Stu() {
name = "小明";
chinese = 100;
math = 100;
total = chinese + math;
}
~Stu() {
}
void print_stu() {
cout << "名字:" << name << endl;
cout << "语文:" << chinese << endl;
cout << "数学:" << math << endl;
cout << "总成绩:" << total;
}
};
int main() {
struct Stu s1;
s1.print_stu();
return 0;
}
6. 运算符的重载
在上一个代码的例子中,针对 struct Stu 类型的变量不能用 cout 进行打印,那么需要对运算符进行重载。使用 operator 关键字。
返回值类型 operator 要重载的运算符 () {
}
#include <iostream>
#include <string>
using namespace std;
struct Stu {
string name;
int chinese;
int math;
int total;
};
ostream& operator<<(ostream& os, struct Stu& s) {
os << "名字" << s.name << endl;
os << "语文" << s.chinese << endl;
os << "数学" << s.math << endl;
os << "总成绩" << s.total << endl;
return os;
}
int main() {
struct Stu s = {"张三", 100, 100, 0};
cout << s << endl;
return 0;
}
ostream 是 C++ 标准库提供的一个「输出流类」。用时要引用「#include」
ostream& os,是告诉编译器「os 是一个 ostream 类对象的引用」(这个对象就是用来做输出的,比如 cout)。
7. 结构体排序--sort
C++ 的 STL 中的库函数 sort,可以直接用来排序数据,在算法竞赛和日常开发中使用非常频繁。只要涉及到数据的排序,又没有明确要求自己实现排序算法的时候,就可以直接使用 sort 函数。
7.1 sort 函数介绍
7.2 排序内置类型数据
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int arr[] = {4, 5, 6, 9, 7, 1, 2, 8, 5, 4, 2};
int size = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + size);
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
int main() {
string s = "gefexoabccba";
sort(s.begin(), s.end());
cout << s << endl;
return 0;
}
begin() 和 end() 是 C++ 字符串(std::string)的成员函数,它们的作用是提供字符串中字符的迭代器(可以理解为'指向字符的指针'),来确定 sort 函数的排序范围。
begin() 返回一个起始迭代器,指向字符串的第一个字符(也就是 s[0] 的位置)
end() 返回一个结束迭代器,指向字符串的最后一个字符的下一个位置(不是最后一个字符本身)。
7.3 自定义排序
sort 的第三个参数是一个可选的自定义比较函数(或函数对象),用于指定排序规则
这个比较函数,接受两个参数,并返回一个布尔值。如果第一个参数应该排在第二个参数之前,则返回 true;否则返回 false。
7.3.1 创建比较函数
#include <iostream>
#include <algorithm>
using namespace std;
bool compart(int x, int y) {
return x > y;
}
int main() {
int arr[] = {7, 5, 9, 6, 4, 8, 1, 3, 0, 2, 2};
int sz = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + sz, compart);
for (int i = 0; i < sz; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
7.3.2 结构体中重载 () 运算符--仿函数
#include <iostream>
#include <algorithm>
using namespace std;
struct Cmp {
bool operator()(int x, int y) {
return x > y;
}
} cmp;
int main() {
int arr[] = {7, 5, 9, 6, 4, 8, 1, 3, 0, 2, 2};
int sz = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + sz, cmp);
for (int i = 0; i < sz; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
本质是编译器把这个调用转换成了 cmp.operator()(参数 1, 参数 2),执行你在 operator() 里定义的逻辑
7.4 排序结构体数据
7.4.1 比较函数排序
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
struct S {
string name;
int age;
};
bool cmp(struct S s1, struct S s2) {
return s1.age > s2.age;
}
int main() {
struct S arr[] = {{"zhangsan", 18}, {"lisi", 20}, {"wangwu", 17}};
int sz = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + sz, cmp);
for (int i = 0; i < sz; i++) {
cout << arr[i].name << ":" << arr[i].age << endl;
}
return 0;
}
7.4.2 重载 () 运算符--仿函数排序
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
struct S {
string name;
int age;
};
struct Cmp {
bool operator()(struct S s1, struct S s2) {
return s1.name > s2.name;
}
} cmp;
int main() {
struct S arr[] = {{"zhangsan", 18}, {"lisi", 20}, {"wangwu", 17}};
int sz = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + sz, cmp);
for (int i = 0; i < sz; i++) {
cout << arr[i].name << ":" << arr[i].age << endl;
}
return 0;
}