C++ 结构体与枚举:零基础入门讲义
模块一:结构体(struct)—— 数据的“组合大礼包”
1. 为什么需要结构体?
在没有结构体之前,如果你想记录 3 个学生的信息(学号、姓名、成绩):
// 以前的做法:开 3 个互不相干的独立数组
int ids[3] = {1, 2, 3};
string names[3] = {"张三", "李四", "王五"};
double scores[3] = {95.5, 88.0, 92.5};
这样写不仅分散,而且如果要按成绩排序,你得同时手动交换这 3 个数组里的内容,极易漏改出错。
结构体的本质:把你认为属于同一个事物的多个不同属性,打包捆绑成一个全新的“自定义类型”。
2. 怎么定义与使用结构体?
语法规则
struct 结构体名字 {
数据类型 变量1;
数据类型 变量2;
// ...
}; // ⚠️ 结尾千万别漏掉分号 ';'
C++11 入门代码(定义与赋值)
#include <iostream>
#include <string>
// 1. 定义一个“学生”结构体类型(类似一个设计图纸)
struct Student {
int id; // 学号
std::string name; // 姓名
double score; // 成绩
};
int main() {
// 2. 实例化:用设计图纸制造具体的变量
// 方式 A:逐个成员用“点操作符(.)”赋值
Student s1;
s1.id = 101;
s1.name = "张三";
s1.score = 95.5;
// 方式 B(推荐,C++11 大括号直接初始化):按定义顺序填入
Student s2 = {102, "李四", 88.0};
// 3. 读取并打印(依然用点操作符 . )
std::cout << "学生1:" << s1.name << ",学号:" << s1.id << ",分数:" << s1.score << std::endl;
std::cout << "学生2:" << s2.name << ",学号:" << s2.id << ",分数:" << s2.score << std::endl;
return 0;
}
3. 结构体数组(最常用的高频操作)
你可以像使用普通 int 数组一样,定义结构体数组:
#include <iostream>
#include <string>
struct Student {
int id;
std::string name;
double score;
};
int main() {
// 定义一个能装 3 个学生的数组
Student list[3] = {
{101, "张三", 95.5},
{102, "李四", 88.0},
{103, "王五", 92.5}
};
// 遍历打印所有学生信息
for (int i = 0; i < 3; ++i) {
std::cout << "第 " << i + 1 << " 个学生:" << list[i].name
<< ",成绩:" << list[i].score << std::endl;
}
return 0;
}
模块二:枚举类型(enum)—— 给有限选项取个好听的名字
1. 为什么需要枚举?
假设你要写一个方向控制系统:
* 方案 1:用数字 0 代表上,1 代表下,2 代表左,3 代表右。
* 缺点:过两天你自己看代码,完全记不清 2 到底是左还是右(这叫“魔法数字 Magic Number”)。
* 方案 2:用枚举(enum)把它们变成有意义的单词。
2. 现代 C++11 的推荐写法:enum class(强类型枚举)
语法规则
enum class 枚举名 {
选项1,
选项2,
选项3
}; // ⚠️ 结尾必须有分号 ';'
C++11 入门代码
#include <iostream>
// 定义一个“方向”枚举类型
enum class Direction {
Up,
Down,
Left,
Right
};
int main() {
// 声明一个枚举变量,必须加上“Direction::”
Direction myDir = Direction::Left;
// 配合 switch 使用(极度清晰!)
switch (myDir) {
case Direction::Up:
std::cout << "向上移动\n";
break;
case Direction::Down:
std::cout << "向下移动\n";
break;
case Direction::Left:
std::cout << "向左移动\n";
break;
case Direction::Right:
std::cout << "向右移动\n";
break;
}
return 0;
}
小技巧:在底层,
Direction::Up其实默认就是整数0,Down是1,Left是2,Right是3。如果需要把它转回数字打印,可以写(int)myDir。
模块三:结构体与枚举结合实战小案例
把二者结合,模拟一个游戏角色:
#include <iostream>
#include <string>
// 1. 定义角色职业
enum class Role {
Warrior, // 战士
Mage, // 法师
Archer // 射手
};
// 2. 定义角色结构体
struct Hero {
std::string name;
int hp;
int attack;
Role role;
};
int main() {
Hero hero1 = {"亚瑟", 1000, 80, Role::Warrior};
std::cout << "角色名字: " << hero1.name << "\n";
std::cout << "生命值: " << hero1.hp << "\n";
// 根据职业打印不同的描述
if (hero1.role == Role::Warrior) {
std::cout << "职业类型: 近战肉盾战士\n";
}
return 0;
}
模块四:针对基础的 3 道小练习
你可以先自己尝试思考或在电脑上敲一敲,再看下方的参考代码。
练习 1:坐标点与曼哈顿距离
要求:
1. 定义一个二维坐标点结构体 Point,包含整型坐标 x 和 y。
2. 在 main 函数中创建两个点 $A(1, 2)$ 和 $B(4, 6)$。
3. 计算并输出两点之间的曼哈顿距离(公式:$|x_A - x_B| + |y_A - y_B|$)。
练习 2:查找最贵的图书
要求:
1. 定义一个 Book 结构体,包含 title(书名,string)和 price(价格,double)。
2. 创建一个大小为 3 的图书数组,存入 3 本书。
3. 循环遍历该数组,找到并打印价格最高的那本书的名字和价格。
练习 3:季节选择器
要求:
1. 定义一个 enum class Season { Spring, Summer, Autumn, Winter };。
2. 给定一个 Season 变量,使用 switch 语句根据不同季节输出对应的天气特征(如:春天温暖、夏天炎热等)。
练习题参考答案
练习 1 参考代码
#include <iostream>
#include <cmath> // 包含绝对值函数 std::abs
struct Point {
int x;
int y;
};
int main() {
Point A = {1, 2};
Point B = {4, 6};
int dist = std::abs(A.x - B.x) + std::abs(A.y - B.y);
std::cout << "两点间的曼哈顿距离为: " << dist << std::endl; // 输出 7
return 0;
}
练习 2 参考代码
#include <iostream>
#include <string>
struct Book {
std::string title;
double price;
};
int main() {
Book books[3] = {
{"C++ Primer", 99.0},
{"算法导论", 128.0},
{"数据结构", 45.5}
};
// 假设第 0 本书最贵
int maxIdx = 0;
for (int i = 1; i < 3; ++i) {
if (books[i].price > books[maxIdx].price) {
maxIdx = i; // 记录更贵的那本书的下标
}
}
std::cout << "最贵的书是: 《" << books[maxIdx].title
<< "》,价格: " << books[maxIdx].price << " 元\n";
return 0;
}
练习 3 参考代码
#include <iostream>
enum class Season {
Spring,
Summer,
Autumn,
Winter
};
int main() {
Season now = Season::Autumn;
switch (now) {
case Season::Spring:
std::cout << "春季:万物复苏,天气温暖\n";
break;
case Season::Summer:
std::cout << "夏季:烈日炎炎,天气炎热\n";
break;
case Season::Autumn:
std::cout << "秋季:秋高气爽,落叶纷飞\n";
break;
case Season::Winter:
std::cout << "冬季:银装素裹,天寒地冻\n";
break;
}
return 0;
}
—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com