NOI C++ 课程体系 / 语法入门 / 第6讲
CSP-J 入门级 · 语法入门 · 结构体与联合体专题

C++ 结构体与联合体 完全指南

让程序学会"打包"不同类型的数据 —— 结构体定义与操作、结构体数组、联合体 union 逐一讲透,自定义类型一次看明白。

6 大教学模块 2 大自定义类型 3 个精讲案例 5 大易错点 1 张速查表 15 道分层练习
本讲 · 第 20/56 讲结构体与联合体
模块 01

情景导航

先用"整理书包"的故事建立直觉,理解为什么需要结构体,掌握结构体的定义与基本操作。

故事故事引入 —— 小强的"整理书包"烦恼

小强是一名初中生,每天要记录自己各科的成绩。他一开始是这样记的:

C++小强的做法
// 语文、数学、英语、物理、化学 五科成绩
string name = "小强";
int chinese = 92;
int math = 98;
int english = 85;
int physics = 90;
int chemistry = 88;
// 隔壁班的小明也要记录自己的成绩...
string name2 = "小明";
int chinese2 = 88;
int math2 = 95;
int english2 = 92;
int physics2 = 87;
int chemistry2 = 91;

小强抱怨道:"每多一个同学,就要多写 5 行代码!如果全班 50 个人,那不得写 250 行?这也太麻烦了!"

老师笑着说:"你想想,一个人有名字、年龄、成绩……这些东西虽然种类不同,但它们都属于同一个人。为什么不给'一个人'定制一个大箱子,把名字、年龄、成绩全都装进去呢?"

"不同类型的数据,可以装进同一个自定义的大箱子里 —— 这个大箱子就叫'结构体'!"

类比生活类比 —— 不同种类的箱子

把基本类型和结构体用身边的场景对一对号,自定义类型的概念一下子就清晰了:

文具盒

只放笔和橡皮

各占各的位置,互不干扰

= 基本类型(int / char)
书包

课本、文具、水杯

不同东西放在不同格子,但都属于书包

= 结构体(多种类型打包)
成绩单

姓名、各科成绩

组合成一条完整记录

= 结构体变量
全班成绩单

50 条学生记录

整齐排列,统一管理

= 结构体数组
定义什么是结构体

到目前为止我们使用的都是 C++ 内置的基本数据类型:int 存整数、float 存小数、char 存字符、string 存字符串。它们各有用处,但有一个共同的限制——每个变量只能存一种类型的数据。

可现实中,很多事物是由多种不同类型的数据组成的。比如一个学生有名字(string)、年龄(int)、成绩(float)…… 如果要把这些信息打包在一起管理,基本类型就力不从心了。

于是 C++ 提供了 结构体(struct),它允许我们自定义一种新的数据类型,把多种不同类型的数据组合在一起,作为一个整体来使用。

类型能存什么例子
int只能存整数int age = 16;
string只能存文本string name = "张三";
struct Student同时存名字+年龄+成绩Student s = {"张三", 16, 95.5};
结构体口诀 结构体,自定义,不同类型打包住。
先定义类型再变量,成员访问用点号。
数组一开五十人,整齐管理不混乱。

口诀里藏着本课的全部主角:struct 关键字、自定义类型、成员访问(. 点号)、结构体数组。接下来我们就把它们一个一个请出来,看清各自的"内部构造"和"使用方式"。

模块 02

知识探究

深入理解结构体的定义方法、成员操作、初始化方式,结构体数组与联合体的使用。

语法结构体定义语法

定义结构体的基本格式如下:

struct Student {
  string name;
  int age;
  int score;
};
关键字 struct 结构体类型名(首字母大写) 数据类型 成员变量名

定义结构体时牢记五个要点:

要点说明
关键字 struct告诉编译器这是一个结构体定义,不能省略
类型名自定义名称,建议首字母大写,如 Student、Date
花括号花括号内是"成员列表",每个成员占一行,格式为"类型 名;"
分号花括号后面的分号 不能省略,否则编译报错
成员类型可不同每个成员可以是任意类型:int、float、string、甚至其他结构体
操作结构体的三种操作方式

定义好结构体类型后,可以创建结构体变量并进行操作:

1整体操作 —— 直接赋值/交换

结构体变量可以像普通变量一样整体赋值或交换:

C++结构体整体操作
struct Student {
    string name;
    int age;
    int score;
};
Student a = {"张三", 16, 95};
Student b = a;          // 整体赋值:b 和 a 完全一样
swap(a, b);             // 整体交换:a 和 b 互换
2成员操作 —— 用点号访问

访问结构体中某个成员的格式为:结构体变量名.成员名

C++成员访问
Student zhangsan;
cin >> zhangsan.name;    // 输入名字
zhangsan.age = 16;       // 设置年龄
zhangsan.score = 95;     // 设置成绩
cout << zhangsan.name << " " << zhangsan.score << endl;
3初始化 —— 定义时直接赋值

定义结构体变量时可以像数组一样初始化:

C++结构体初始化
Student lisi = {"李四", 15, 88};
Student wangwu{"王五", 17, 92};  // C++11 花括号初始化
方法两种定义方式对比

结构体可以在定义类型的同时定义变量,也可以先定义类型再定义变量:

方法一:先定义类型,再定义变量
C++分步定义
struct Student {
    string name;
    int age;
    int score;
};
Student zhangsan;     // 定义变量
Student a[100];      // 定义数组
方法二:定义类型的同时定义变量
C++一步到位
struct Student {
    string name;
    int age;
    int score;
} zhangsan, a[100];

建议:方法一更清晰,推荐在大多数情况下使用。方法二适合简单的小程序。

数组结构体数组

结构体数组就是把多个同类型结构体变量组织在一起,就像用多个格子存放多条学生记录:

C++结构体数组
struct Student {
    string name;
    int age;
    int score;
};
Student classA[50];  // 50个学生的数组

int main() {
    for (int i = 0; i < 50; i++) {
        cin >> classA[i].name >> classA[i].age >> classA[i].score;
    }
    return 0;
}

解读:classA[i].name 表示第 i 个学生的名字。数组下标和点号可以连用,非常方便。

拓展联合体(union)

联合体(union)和结构体长得非常像,但有一个关键区别:联合体的所有成员共享同一块内存。也就是说,同一时刻联合体只能存一个成员的值,修改任何一个成员都会影响其他成员。

union Data {
  int i;
  float f;
  char c;
};
关键字 union 联合体类型名 成员变量(共享内存)

联合体的大小等于最大成员的大小。例如上面的 Data,int 占 4 字节,float 占 4 字节,char 占 1 字节,所以 Data 的大小是 4 字节。

C++联合体示例
union Data {
    int i;
    float f;
};
Data d;
d.i = 12345;      // 存整数
cout << d.i << endl;  // 输出 12345
d.f = 3.14;       // 存浮点数(i 的值被覆盖)
cout << d.f << endl;  // 输出 3.14
cout << d.i << endl;  // 输出乱码(i 已被覆盖)
对比结构体 vs 联合体
对比项结构体(struct)联合体(union)
内存分配每个成员各有独立内存所有成员共享同一块内存
同时存多个值可以同时存只能同时存一个
大小所有成员大小之和最大成员的大小
使用场景记录学生、日期等复合信息节省内存,变量可能取多种类型
案例案例1:成绩统计

定义一个学生结构体,输入 3 个学生的信息,输出成绩最高的学生:

C++成绩统计
#include <iostream>
#include <string>
using namespace std;
struct Student {
    string name;
    int score;
};
int main() {
    Student s[3];
    for (int i = 0; i < 3; i++) {
        cin >> s[i].name >> s[i].score;
    }
    int maxIdx = 0;
    for (int i = 1; i < 3; i++) {
        if (s[i].score > s[maxIdx].score) {
            maxIdx = i;
        }
    }
    cout << s[maxIdx].name << " " << s[maxIdx].score << endl;
    return 0;
}
运行结果
输入:张三 92 李四 88 王五 95
输出:王五 95
案例案例2:结构体数组排序

按成绩从高到低排序输出所有学生:

C++结构体排序
#include <iostream>
#include <string>
using namespace std;
struct Student {
    string name;
    int score;
};
int main() {
    Student s[3];
    for (int i = 0; i < 3; i++) {
        cin >> s[i].name >> s[i].score;
    }
    for (int i = 0; i < 2; i++) {
        for (int j = i + 1; j < 3; j++) {
            if (s[j].score > s[i].score) {
                swap(s[i], s[j]);  // 整体交换
            }
        }
    }
    for (int i = 0; i < 3; i++) {
        cout << s[i].name << " " << s[i].score << endl;
    }
    return 0;
}
运行结果
输入:张三 92 李四 88 王五 95
输出:王五 95
张三 92
李四 88
案例案例3:联合体共享内存

联合体所有成员共享同一块内存,写入一个成员后读取另一个成员会得到"解释不同"的结果:

C++联合体内存共享
#include <iostream>
using namespace std;
union Data {
    int i;
    char c;
};
int main() {
    Data d;
    d.i = 65;        // 写入整数 65
    cout << d.i << endl;   // 输出:65
    cout << d.c << endl;   // 输出:A(65 的 ASCII 码)
    return 0;
}
运行结果
65
A

解读:d.i = 65 把整数 65 写入共享内存,d.c 读取同一块内存时把它当作 char,而 ASCII 码 65 对应字符 'A'。这就是联合体共享内存的特性。

模块 03

实践应用

通过 3 道综合题巩固结构体和联合体的使用,每道题含完整代码和详细解析。

题目题目1:成绩最高学生

定义学生结构体(含姓名、学号、成绩),输入 n 个学生的信息,输出成绩最高的学生信息。

提示:用结构体数组存储所有学生,遍历找最大值。
查看参考代码
C++参考代码
#include <iostream>
#include <string>
using namespace std;
struct Student {
    string name;
    string id;
    int score;
};
int main() {
    int n; cin >> n;
    Student s[105];
    for (int i = 0; i < n; i++) {
        cin >> s[i].name >> s[i].id >> s[i].score;
    }
    int best = 0;
    for (int i = 1; i < n; i++) {
        if (s[i].score > s[best].score) best = i;
    }
    cout << s[best].name << " " << s[best].id << " " << s[best].score << endl;
    return 0;
}
题目题目2:日期比较

定义日期结构体(年、月、日),输入两个日期,判断哪个更早。

提示:先比年,年相同再比月,月相同再比日。
查看参考代码
C++参考代码
#include <iostream>
using namespace std;
struct Date {
    int year, month, day;
};
int main() {
    Date d1, d2;
    cin >> d1.year >> d1.month >> d1.day;
    cin >> d2.year >> d2.month >> d2.day;
    if (d1.year < d2.year) cout << "d1 更早";
    else if (d1.year > d2.year) cout << "d2 更早";
    else if (d1.month < d2.month) cout << "d1 更早";
    else if (d1.month > d2.month) cout << "d2 更早";
    else if (d1.day < d2.day) cout << "d1 更早";
    else if (d1.day > d2.day) cout << "d2 更早";
    else cout << "两个日期相同";
    cout << endl;
    return 0;
}
题目题目3:联合体输出分析

分析以下代码的输出结果,并解释原因:

C++联合体分析
#include <iostream>
using namespace std;
union Test {
    int a;
    char b;
};
int main() {
    Test t;
    t.a = 256;
    cout << t.b << endl;
    return 0;
}
查看解析

输出:输出一个不可打印的字符(具体值取决于系统)。

解析:int 占 4 字节,char 占 1 字节,联合体大小由 int 决定。t.a = 256 写入 4 字节,t.b 只读取最低 1 字节。256 的二进制是 00000001 00000000,最低字节是 0,所以 t.b 的值为 0(空字符,不可打印)。

模块 04

总结提升

回顾本课核心要点,并通过拓展案例加深理解。

总结核心要点速查表
知识点关键内容
结构体定义struct 类型名 { 成员列表; }; 注意末尾分号不能省
成员访问变量名.成员名,如 s.name
整体操作结构体变量可以整体赋值、交换(swap)
初始化Student s = {"张三", 16, 95};
结构体数组Student s[50]; 用 s[i].name 访问第 i 个元素
联合体 union所有成员共享内存,大小=最大成员大小
拓展拓展案例:简易学生管理系统

综合运用结构体数组、排序、查找等知识,实现一个简易的学生管理系统:

C++学生管理系统
#include <iostream>
#include <string>
using namespace std;
struct Student {
    string name;
    int score;
};
int main() {
    Student cls[5] = {
        {"张三", 92}, {"李四", 88},
        {"王五", 95}, {"赵六", 76},
        {"孙七", 85}
    };
    int n = 5;
    // 按成绩降序排序
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            if (cls[j].score > cls[i].score) swap(cls[i], cls[j]);
        }
    }
    // 输出排名
    for (int i = 0; i < n; i++) {
        cout << i + 1 << ". " << cls[i].name << " " << cls[i].score << endl;
    }
    return 0;
}
运行结果
1. 王五 95
2. 张三 92
3. 李四 88
4. 孙七 85
5. 赵六 76

思考与启发

结构体是 C++ 中面向对象编程的基石。类(class)本质上就是结构体的增强版——多了成员函数和访问控制。掌握了结构体,你就为后续学习类打下了坚实的基础。

联合体虽然使用场景较少,但在底层编程(如嵌入式、网络协议解析)中非常有用,因为它允许你对同一块内存进行不同的"解读"。

模块 05

学习检测

检测本课核心知识点,避免常见陷阱。

检测5大易错点
易错 01

忘记分号

错误写法
struct Student {
    string name;
    int age;
}  // 缺少分号!
正确写法
struct Student {
    string name;
    int age;
};  // 分号不能省
易错 02

混淆类型和变量

错误写法
struct Student {
    string name;
};
Student.name = "张三";  // 错!Student 是类型
正确写法
Student s;
s.name = "张三";  // 先定义变量,再访问成员
易错 03

成员访问符号用错

错误写法
Student s;
s:name = "张三";  // 错!不能用冒号
正确写法
Student s;
s.name = "张三";  // 用点号 .
易错 04

联合体混用

错误写法
union Data { int i; float f; };
Data d;
d.i = 42;
cout << d.f << endl;  // 错!写入 int 读 float 结果未定义
正确写法
union Data { int i; float f; };
Data d;
d.i = 42;
cout << d.i << endl;  // 写入什么就读什么
易错 05

数组越界

错误写法
Student s[3];
for (int i = 0; i <= 3; i++) {  // <= 导致越界
    cin >> s[i].name;
}
正确写法
Student s[3];
for (int i = 0; i < 3; i++) {  // < 3
    cin >> s[i].name;
}
速查结构体与联合体速查表
操作语法
定义结构体struct 名 { 成员; };
定义变量Student s;
访问成员s.name
整体赋值s1 = s2;
整体交换swap(s1, s2);
初始化Student s = {"张三", 16, 95};
定义数组Student s[50];
数组成员访问s[i].name
定义联合体union 名 { 成员; };
联合体访问d.i 或 d.f(只能读当前写入的类型)

知识点笔记

结构体是什么

自定义数据类型,把多种不同类型的数据打包成一个整体

成员访问

用点号 . 访问:变量名.成员名

结构体数组

多个同类型结构体变量:Student s[50]; 访问 s[i].name

联合体

所有成员共享内存,大小=最大成员大小,写入和读取要用同一种类型

定义注意

结构体/联合体定义末尾的分号不能省,否则编译报错

整体操作

结构体变量支持整体赋值和交换(swap),联合体同样支持整体赋值

练习作业

巩固练习

通过分层练习巩固本课知识,A 基础、B 提高、C 挑战,循序渐进。

总结总结练习(3题)
基础编程题

题目 1:定义日期结构体,输入年月日,输出这是该年的第几天。

提示:用数组存每月天数,注意闰年判断。
查看参考代码
C++参考代码
#include <iostream>
using namespace std;
struct Date { int y, m, d; };
int main() {
    Date dt; cin >> dt.y >> dt.m >> dt.d;
    int days[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    if ((dt.y % 4 == 0 && dt.y % 100 != 0) || dt.y % 400 == 0)
        days[2] = 29;
    int total = 0;
    for (int i = 1; i < dt.m; i++) total += days[i];
    total += dt.d - 1;
    cout << total << endl;
    return 0;
}
基础编程题

题目 2:定义学生结构体,输入 5 个学生的成绩,计算平均分并输出。

查看参考代码
C++参考代码
#include <iostream>
using namespace std;
struct Student { string name; int score; };
int main() {
    Student s[5]; double sum = 0;
    for (int i = 0; i < 5; i++) {
        cin >> s[i].name >> s[i].score;
        sum += s[i].score;
    }
    cout << sum / 5 << endl;
    return 0;
}
基础编程题

题目 3:定义矩形结构体(长、宽),输入两个矩形,判断哪个面积更大。

查看参考代码
C++参考代码
#include <iostream>
using namespace std;
struct Rect { int w, h; int area() { return w * h; } };
int main() {
    Rect r1, r2;
    cin >> r1.w >> r1.h >> r2.w >> r2.h;
    if (r1.area() > r2.area()) cout << "r1 更大";
    else if (r1.area() < r2.area()) cout << "r2 更大";
    else cout << "一样大";
    cout << endl;
    return 0;
}
A组A 组·基础(4题)
基础填空

1. 定义结构体时,末尾的______不能省略。

答案

答案:分号(;)

考点:结构体定义语法——struct 定义末尾必须有一个分号。

易错:漏了分号,编译器会把下一行代码接进定义里,报出很难看懂的错误。

基础选择

2. 以下哪个是访问结构体成员的正确方式?A) s:name B) s.name C) s-name D) s->name

答案

答案:B

考点:结构体成员访问——结构体变量用点号 s.name,结构体指针才用箭头 s->name。

易错:看到“访问成员”就选箭头 D——箭头只适用于指针,对变量 s 应该用点号。

基础编程

3. 定义一个 Person 结构体,包含 name(string) 和 age(int) 两个成员,定义变量并初始化。

参考代码
C++参考代码
struct Person { string name; int age; };
Person p = {"张三", 25};

思路:定义 struct Person { string name; int age; };,用 Person p = {"张三", 25}; 按成员声明顺序初始化。

易错:初始化列表的顺序要和成员声明顺序一致,写反了两个值就互换了。

基础判断

4. 结构体变量可以整体赋值,联合体变量也可以整体赋值。(对/错)

答案
C++完整参考代码
#include <iostream>
#include <string>
using namespace std;

struct Student {
    string name;              // 成员可以是任意类型
    int score;
};                            // ← 这个分号不能省略,否则编译报错

int main() {
    Student s = {"小明", 95}; // 用花括号一次性初始化
    cout << s.name << " " << s.score << endl;
    return 0;
}

// 运行结果:小明 95

答案:分号(;)。

思路:struct 名字 { 成员列表 }; 整体是一条完整的语句,末尾必须用分号收尾,编译器才知道成员列表到哪儿结束了。

考点:结构体定义的完整语法:struct 关键字 + 类型名 + 花括号成员列表 + 分号,四部分一个都不能少。

易错:漏掉花括号后面的分号时,编译器报错的位置往往在下一行(比如说某个类型名找不到),很容易看错地方。写结构体时先补分号,再写 main。

B组B 组·提高(4题)
提高编程

1. 定义学生结构体(姓名、成绩),输入 10 个学生,找出成绩最高和最低的学生并输出。

参考代码
C++参考代码
struct Student { string name; int score; };
int main() {
    Student s[10];
    for (int i = 0; i < 10; i++) cin >> s[i].name >> s[i].score;
    int mx = 0, mn = 0;
    for (int i = 1; i < 10; i++) {
        if (s[i].score > s[mx].score) mx = i;
        if (s[i].score < s[mn].score) mn = i;
    }
    cout << "最高:" << s[mx].name << " " << s[mx].score << endl;
    cout << "最低:" << s[mn].name << " " << s[mn].score << endl;
    return 0;
}

思路:用结构体数组存 10 个学生,遍历时记录最高分、最低分的下标,最后输出对应学生。

易错:mx、mn 忘了初始化为 0,或比较时只换下标忘了同步更新。

提高编程

2. 定义日期结构体,输入一个日期,输出它是星期几(已知 2000年1月1日是星期六)。

参考代码
C++参考代码
struct Date { int y, m, d; };
int main() {
    Date dt; cin >> dt.y >> dt.m >> dt.d;
    int days[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    if ((dt.y % 4 == 0 && dt.y % 100 != 0) || dt.y % 400 == 0) days[2] = 29;
    int total = 0;
    for (int y = 2000; y < dt.y; y++) {
        total += ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) ? 366 : 365;
    }
    for (int i = 1; i < dt.m; i++) total += days[i];
    total += dt.d - 1;
    string w[] = {"六","日","一","二","三","四","五"};
    cout << w[total % 7] << endl;
    return 0;
}

思路:累加从 2000-1-1 到目标日期经过的总天数(注意闰年 2 月 29 天),对 7 取模映射到星期(2000-1-1 是星期六)。

易错:忘了闰年判断或取模后与“星期六”的基准对应错位,结果整体差几天。

提高分析

3. 分析以下联合体代码的输出:

C++联合体分析
union U { int a; char b; };
U u; u.a = 0;
cout << (int)u.b << endl;
答案

答案:输出 0。u.a = 0 写入 4 字节全 0,u.b 读取最低字节也是 0。

思路:联合体所有成员共享同一段内存,u.a = 0 把 4 个字节全写成 0,读 b 自然也是 0。

易错:按结构体的思路以为 a、b 互相独立,算出别的值。

提高编程

4. 定义员工结构体(工号、姓名、部门、工资),输入 5 个员工,按工资降序排序并输出。

参考代码
C++参考代码
struct Emp { int id; string name, dept; double salary; };
int main() {
    Emp e[5];
    for (int i = 0; i < 5; i++) cin >> e[i].id >> e[i].name >> e[i].dept >> e[i].salary;
    for (int i = 0; i < 4; i++)
        for (int j = i+1; j < 5; j++)
            if (e[j].salary > e[i].salary) swap(e[i], e[j]);
    for (int i = 0; i < 5; i++)
        cout << e[i].name << " " << e[i].salary << endl;
    return 0;
}

思路:结构体数组按 salary 比较做排序,注意要交换整个结构体。

易错:排序时只交换了工资没交换其他成员,工号、姓名和工资对不上号。

C组C 组·挑战(4题)
挑战编程

1. 定义图书结构体(书名、作者、ISBN、价格),实现按书名排序和按价格查找功能。

参考代码
C++参考代码
struct Book { string title, author, isbn; double price; };
int main() {
    Book books[3] = {
        {"C++ Primer", "Lippman", "978-0", 89.9},
        {"Python 编程", "Zelle", "978-1", 69.9},
        {"算法导论", "Cormen", "978-2", 129.9}
    };
    for (int i = 0; i < 2; i++)
        for (int j = i+1; j < 3; j++)
            if (books[j].title < books[i].title) swap(books[i], books[j]);
    double target; cin >> target;
    bool found = false;
    for (int i = 0; i < 3; i++)
        if (books[i].price == target) {
            cout << books[i].title << " " << books[i].author << endl;
            found = true;
        }
    if (!found) cout << "未找到" << endl;
    return 0;
}

思路:string 直接用 < 比较书名即可排序,查找就遍历数组逐个比对。

易错:对 string 用 strcmp 编译不过(那是 C 字符串函数);排序时忘了整体交换结构体。

挑战编程

2. 定义复数结构体(实部、虚部),实现复数加法和乘法。

参考代码
C++参考代码
struct Complex { double r, i; };
Complex add(Complex a, Complex b) {
    return {a.r + b.r, a.i + b.i};
}
Complex mul(Complex a, Complex b) {
    return {a.r*b.r - a.i*b.i, a.r*b.i + a.i*b.r};
}
int main() {
    Complex c1 = {1, 2}, c2 = {3, 4};
    Complex s = add(c1, c2);
    cout << s.r << " + " << s.i << "i" << endl;
    return 0;
}

思路:复数乘法按 (a+bi)(c+di) = (ac−bd) + (ad+bc)i 实现,函数返回 Complex 结构体。

易错:虚部公式误写成 ad − bc,和实部的 ac − bd 混淆了。

挑战分析

3. 联合体大小是多少?分析以下代码:

C++联合体大小
union U { char a; int b; double c; };
cout << sizeof(U) << endl;
答案

答案:输出 8(double 的大小)。联合体大小等于最大成员的大小,double 占 8 字节,是最大的。

思路:联合体大小等于最大成员的大小,double 占 8 字节,所以 sizeof 是 8。

易错:以为联合体大小是所有成员之和,算成十几字节。

挑战编程

4. 定义班级结构体(班级名、学生数组),实现添加学生、删除学生、按成绩排名功能。

参考代码
C++参考代码
struct Student { string name; int score; };
struct Class {
    string name;
    Student students[100];
    int count;
    void add(Student s) { students[count++] = s; }
    void sort() {
        for (int i = 0; i < count-1; i++)
            for (int j = i+1; j < count; j++)
                if (students[j].score > students[i].score)
                    swap(students[i], students[j]);
    }
};
int main() {
    Class c; c.name = "一班"; c.count = 0;
    c.add({"张三", 92}); c.add({"李四", 88});
    c.sort();
    for (int i = 0; i < c.count; i++)
        cout << c.students[i].name << " " << c.students[i].score << endl;
    return 0;
}

思路:班级结构体里嵌学生数组和计数 count,添加时 students[count++] = s,排名按成绩比较交换。

易错:添加学生后忘了 count++,下一个学生把上一个覆盖掉。