CCF GESP 考级专项讲义:结构体、高级排序与文件操作
一、 结构体(struct)的定义与使用
在实际编程中,一个人的信息往往包含多种数据类型(年龄是整数、性别是布尔值、姓名是字符数组、体重是浮点数)。单纯用一维数组无法满足需求,此时必须使用结构体。
1. 结构体的定义
struct people {
int age; // 年龄
bool sex; // 性别(1代表男,0代表女)
char name[100]; // 姓名
double weight; // 体重
};
- 关键字:
struct - 结构体变量声明:代码中定义了全局数组
people t[10];,代表最多可以存 10 个people对象。
二、 结合一维数组的输入输出与格式化函数
我们可以将结构体与一维数组结合,通过循环实现多组数据的批量读入与输出。
1. 使用 cin 读入多个数据
利用 for 循环和 cin,可以依次给数组中的每个结构体成员赋值:
for(int i = 0; i < 5; i++) {
cin >> t[i].age >> t[i].sex >> t[i].name >> t[i].weight;
}
2. 编写独立的 print 函数输出信息(应用 const 引用)
为了让代码结构更清晰,我们可以把打印单个结构体信息的逻辑封装成一个函数。
三、 补充知识:函数参数的传递方式(重点:const 引用)
在处理结构体(struct)、类或大体积数据时,盲目使用“值传递”会复制整个结构体,造成内存和时间的浪费。
1. 引用传递(&)与常量引用(const)
- 引用传递:在参数类型后加
&(如people &p),函数内部操作的是实参本身,不发生数据复制。 const修饰符:加上const后(如const people &p),既享受了引用的高效(不复制),又保证了数据绝对安全(函数内无法修改p的成员)。
在 print 函数和 sort 的 cmp 函数中,我们强烈推荐使用 const 引用:
// 打印函数:使用常量引用,高效且安全
void print(const people &p) {
cout << "==========个人信息=========" << endl;
cout << "年龄:" << p.age << endl;
cout << "性别:" << (p.sex == 1 ? "男" : "女") << endl;
cout << "姓名:" << p.name << endl;
cout << "体重:" << p.weight << endl;
}
四、 sort 排序与自定义 cmp 函数(多关键字排序)
当我们需要对结构体数组进行排序时,必须通过自定义比较函数(cmp)来告诉 sort 排序规则。
多关键字排序(优先级排序)
在考试中经常遇到“先按条件A排序,如果条件A相同,再按条件B排序”的题型。 例如:要求先按年龄从大到小排序;如果年龄相同,则按体重从大到小排序。
// cmp 比较函数也必须使用 const 引用,保证效率和安全性
bool cmp1(const people &a, const people &b) {
if(a.age != b.age) {
return a.age > b.age; // 第一关键字:年龄不同,按年龄降序
}
return a.weight > b.weight; // 第二关键字:年龄相同,按体重降序
}
- 调用方式:
sort(t, t + 5, cmp1);
五、 freopen 文件重定向
在 GESP 考试中,有时需要从文件中读取数据,并输出到文件中。
* 语法:freopen("文件名", "模式", 标准流);
* 模式:"r" 代表读(Read),"w" 代表写(Write)。
* 代码应用:
cpp
// 将标准输出重定向到 "个人信息.txt" 文件中
freopen("个人信息.txt", "w", stdout);
六、 完整综合代码总览
#include <bits/stdc++.h>
using namespace std;
struct people {
int age;
bool sex;
char name[100];
double weight;
} t[10];
// 使用 const 引用传递参数
void print(const people &p) {
cout << "==========个人信息=========" << endl;
cout << "年龄:" << p.age << endl;
cout << "性别:" << (p.sex == 1 ? "男" : "女") << endl;
cout << "姓名:" << p.name << endl;
cout << "体重:" << p.weight << endl;
}
// 多关键字排序:年龄降序,年龄相同时体重降序
bool cmp1(const people &a, const people &b) {
if(a.age != b.age) {
return a.age > b.age;
}
return a.weight > b.weight;
}
int main() {
freopen("个人信息.txt", "w", stdout);
for(int i = 0; i < 5; i++) {
cin >> t[i].age >> t[i].sex >> t[i].name >> t[i].weight;
}
sort(t, t + 5, cmp1);
for(int i = 0; i < 5; i++) {
print(t[i]);
}
return 0;
}
七、 课后巩固练习题
一、 选择题
1. 关于 C++ 中结构体(struct),以下说法错误的是?
A. 结构体可以包含不同类型的数据成员(如 int, double, char 等)。
B. 结构体数组的一维数组下标也是从 0 开始的。
C. 结构体变量不能作为数组的元素。
D. 可以通过 . 运算符访问结构体变量中的成员。
2. 在编写 sort 函数的自定义比较函数 cmp 时,参数通常采用 const 结构体类型 &a, const 结构体类型 &b 的形式,这样做的好处不包括?
A. 避免了结构体复制带来的内存和时间开销,提高程序运行效率。
B. 防止在比较函数内部不小心修改了原结构体的数据,保证安全性。
C. 可以让 sort 函数自动支持降序排序,不需要写具体的比较逻辑。
D. 语法规范,符合大对象传递的最佳实践。
3. 关于代码 freopen("output.txt", "w", stdout); 的作用,下列说法正确的是?
A. 从 output.txt 文件中读取输入数据。
B. 将标准输出(如 cout 的内容)重定向写入到 output.txt 文件中。
C. 关闭文件输出流。
D. 清空屏幕上的所有显示内容。
二、 代码阅读题
阅读以下代码片段,并回答问题:
#include <iostream>
#include <algorithm>
using namespace std;
struct Student {
int id;
int score;
};
bool cmp(const Student &a, const Student &b) {
if (a.score != b.score) {
return a.score > b.score; // 成绩从高到低
}
return a.id < b.id; // 学号从低到高
}
int main() {
Student s[3] = {{101, 85}, {102, 90}, {103, 85}};
sort(s, s + 3, cmp);
cout << s[0].id << " " << s[1].id << " " << s[2].id << endl;
return 0;
}
问题:
1. 请问程序运行后,终端或输出文件中打印的结果是什么?
2. 在 cmp 函数中,如果将 return a.score > b.score; 改为 return a.score < b.score;,第一名(即排序后的第一个元素 s[0])会是谁(写出其学号)?
参考答案与解析
一、 选择题答案
- C
- 解析:结构体完全可以作为数组的元素(例如本文中的
people t[10];),因此选项 C 说法错误。 - C
- 解析:
const引用和降序逻辑无关,降序需要我们在函数内部明确写出>. 选项 C 错误。 - B
- 解析:参数
"w"代表 Write(写),stdout代表标准输出。因此是将cout写入文件。
二、 代码阅读题答案
- 输出结果:
102 101 103 - 解析:
- 初始数据:
{101, 85},{102, 90},{103, 85}。 - 按
cmp规则:先按分数从高到低排序。分数最高的是102(90分),排在第一位。 101和103的分数相同(都是85分),触发第二关键字:学号从低到高排序。因此101排在103前面。- 排序后的顺序为:
102->101->103。输出对应的id即为102 101 103。
- 初始数据:
- 学号:
101(或103中的一个,具体看谁分低) - 解析:如果改成
a.score < b.score,则变成成绩从低到高排序。分数最低的是 85 分的101和103。由于学号从小到大排,所以排在最前面 (s[0]) 的学号是101。
—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com