Ch 9: 条件控制流
- 熟练使用 if/else 条件语句
- 掌握 switch 语句的用法
- 理解 C++20 的初始化语句语法
- 学会选择合适的条件结构
9.1 if/else 语句
Section titled “9.1 if/else 语句”Python 对比
Section titled “Python 对比”# Python - 用缩进表示块score = 85
if score >= 90: grade = "A" print("Excellent!")elif score >= 80: grade = "B" print("Good!")elif score >= 60: grade = "C" print("Passed")else: grade = "F" print("Failed")C++ if/else
Section titled “C++ if/else”// C++ - 用 {} 表示块int score = 85;std::string grade;
if (score >= 90) { grade = "A"; std::cout << "Excellent!" << std::endl;} else if (score >= 80) { grade = "B"; std::cout << "Good!" << std::endl;} else if (score >= 60) { grade = "C"; std::cout << "Passed" << std::endl;} else { grade = "F"; std::cout << "Failed" << std::endl;}单行 if(C++ 也支持)
Section titled “单行 if(C++ 也支持)”// 单行 if 可以省略 {}(不推荐)if (score >= 60) grade = "Pass";else grade = "Fail";
// Python 三元表达式// Python: result = "Pass" if score >= 60 else "Fail"
// C++ 三元运算符std::string result = (score >= 60) ? "Pass" : "Fail";三元运算符详解
Section titled “三元运算符详解”// 基本用法int a = 10, b = 20;int max = (a > b) ? a : b; // 20
// 嵌套(不推荐,难读)int grade = (score >= 90) ? 5 : (score >= 80) ? 4 : (score >= 70) ? 3 : (score >= 60) ? 2 : 1;
// 推荐:用 if-else 链代替嵌套三元9.2 C++20 初始化语句
Section titled “9.2 C++20 初始化语句”Python 的便利
Section titled “Python 的便利”# Python - 可以在 if 中直接赋值result = get_data()if result: process(result)C++20 初始化 if
Section titled “C++20 初始化 if”// C++20 - 初始化语句if (auto opt = find_item(); opt.has_value()) { // opt 在这个作用域内可用 process(opt.value());}
// 传统方式 - opt 在外层作用域auto opt = find_item();if (opt.has_value()) { process(opt.value());}初始化 if 的实际应用
Section titled “初始化 if 的实际应用”#include <unordered_map>#include <optional>
// 应用 1: map findstd::unordered_map<std::string, int> ages = {{"Alice", 30}};
if (auto it = ages.find("Alice"); it != ages.end()) { std::cout << "Found: " << it->second << std::endl;} else { // it 不在这个作用域 std::cout << "Not found" << std::endl;}
// 应用 2: optional 处理std::optional<int> find_score(const std::string& name) { if (name == "Alice") return 95; return std::nullopt;}
if (auto score = find_score("Alice"); score.has_value()) { std::cout << "Score: " << *score << std::endl;}
// 应用 3: 资源获取 + 检查if (auto file = open_file("data.txt"); file.is_open()) { process(file);} else { std::cerr << "Failed to open file" << std::endl;}9.3 switch 语句
Section titled “9.3 switch 语句”Python match (3.10+)
Section titled “Python match (3.10+)”# Python 3.10+command = "start"
match command: case "start": print("Starting...") case "stop": print("Stopping...") case _: print("Unknown command")C++ switch
Section titled “C++ switch”// C++ - switch 语句std::string command = "start";
switch (command) { case "start": // 编译错误!C++ 中 case 必须是整数常量! std::cout << "Starting..." << std::endl; break; case "stop": std::cout << "Stopping..." << std::endl; break; default: std::cout << "Unknown command" << std::endl; break;}重要: C++ switch 的 case 必须是整数常量表达式,不能是字符串!
整数 switch
Section titled “整数 switch”int day = 3;
switch (day) { case 1: std::cout << "Monday" << std::endl; break; case 2: std::cout << "Tuesday" << std::endl; break; case 3: std::cout << "Wednesday" << std::endl; break; case 4: std::cout << "Thursday" << std::endl; break; case 5: std::cout << "Friday" << std::endl; break; default: std::cout << "Weekend" << std::endl; break;}枚举类 switch(推荐)
Section titled “枚举类 switch(推荐)”// 使用枚举类使 switch 更清晰enum class State { IDLE, RUNNING, PAUSED, STOPPED };
State state = get_state();
switch (state) { case State::IDLE: std::cout << "Idle" << std::endl; break; case State::RUNNING: std::cout << "Running" << std::endl; break; case State::PAUSED: std::cout << "Paused" << std::endl; break; case State::STOPPED: std::cout << "Stopped" << std::endl; break;}switch 贯穿(fall-through)
Section titled “switch 贯穿(fall-through)”// C++ 允许 fall-through(有意为之时)switch (grade) { case 'A': case 'B': case 'C': std::cout << "Pass" << std::endl; // A/B/C 都执行这个 break; case 'D': case 'F': std::cout << "Fail" << std::endl; break;}C++17 [[fallthrough]] 属性
Section titled “C++17 [[fallthrough]] 属性”// 显式标注 fall-throughswitch (grade) { case 'A': std::cout << "Excellent" << std::endl; [[fallthrough]]; // 显式说明是故意的 case 'B': std::cout << "Good" << std::endl; break;}9.4 switch 初始化 (C++20)
Section titled “9.4 switch 初始化 (C++20)”// C++20 - switch 带初始化switch (int result = process(); result) { case 0: std::cout << "Success" << std::endl; break; case -1: std::cout << "Error: Not found" << std::endl; break; case -2: std::cout << "Error: Permission denied" << std::endl; break; default: std::cout << "Unknown error: " << result << std::endl; break;}9.5 条件表达式
Section titled “9.5 条件表达式”Python
Section titled “Python”# and/or 短路求值result = data and data.get("value") or "default"
# 链式比较if 60 <= score < 90: # Python 特有 print("Pass")// && 短路求值if (ptr != nullptr && ptr->value > 0) { // ptr != nullptr 为 false 时,不执行 ptr->value > 0}
// || 短路求值int* ptr = get_pointer();int value = (ptr != nullptr) ? *ptr : 0;
// 链式比较 - C++ 不支持!需要分开写int score = 75;if (score >= 60 && score < 90) { std::cout << "Pass" << std::endl;}9.6 完整示例
Section titled “9.6 完整示例”#include <iostream>#include <string>#include <optional>
// 模拟解析函数std::optional<int> parse_int(const std::string& s) { try { return std::stoi(s); } catch (...) { return std::nullopt; }}
// 判断分类enum class Category { SMALL, MEDIUM, LARGE, HUGE };
Category classify(int value) { if (value < 0) { throw std::invalid_argument("Negative not allowed"); } if (value < 10) return Category::SMALL; if (value < 100) return Category::MEDIUM; if (value < 1000) return Category::LARGE; return Category::HUGE;}
int main(int argc, char* argv[]) { // 检查参数 if (argc != 2) { std::cerr << "用法: " << argv[0] << " <数字>" << std::endl; return 1; }
// C++20 初始化 if if (auto opt = parse_int(argv[1]); opt.has_value()) { int num = *opt;
// if-else 链 if (num > 0) { std::cout << "正数" << std::endl; } else if (num < 0) { std::cout << "负数" << std::endl; } else { std::cout << "零" << std::endl; }
// switch 用枚举 switch (classify(num)) { case Category::SMALL: std::cout << "小数字" << std::endl; break; case Category::MEDIUM: std::cout << "中等数字" << std::endl; break; case Category::LARGE: std::cout << "大数字" << std::endl; break; case Category::HUGE: std::cout << "巨大数字" << std::endl; break; }
// 三元运算符 std::string parity = (num % 2 == 0) ? "偶数" : "奇数"; std::cout << parity << std::endl;
} else { std::cerr << "无效数字: " << argv[1] << std::endl; return 1; }
return 0;}9.7 最佳实践
Section titled “9.7 最佳实践”// ✅ 推荐:始终使用 {} 即使是单行if (ptr != nullptr) { process(ptr);}
// ✅ 推荐:使用枚举替代魔法数字enum class State { IDLE, RUNNING, PAUSED, STOPPED };State state = get_state();switch (state) { case State::IDLE: /* ... */ break; case State::RUNNING: /* ... */ break; case State::PAUSED: /* ... */ break; case State::STOPPED: /* ... */ break;}
// ✅ 推荐:switch 始终有 defaultswitch (type) { case TYPE_A: /* ... */ break; case TYPE_B: /* ... */ break; default: throw std::runtime_error("Unknown type");}
// ✅ 推荐:使用 std::optional 而非 sentinel 值std::optional<int> find(const std::vector<int>& v, int target) { for (auto x : v) { if (x == target) return x; } return std::nullopt;}
// ❌ 避免:隐式 fall-through(不用 [[fallthrough]])if/else用{}表示块,单行可省略但推荐用{}- C++20 支持
if (init; condition)初始化语法 switch的 case 必须是整数常量,不能是字符串- switch 要加
break,或用[[fallthrough]]显式标注 - 用枚举类
enum class替代魔法数字 - 条件表达式用
&&/||短路求值
下章预告:ch10 学习循环语句,包括传统 for、while 和 C++20 范围 for。