C++ Primer 第五章:语句详解与实战练习
Cpp-Primer C++ Primer 5 answers 项目地址: https://gitcode.com/gh_mirrors/cp/Cpp-Primer
前言
本文基于C++ Primer第五章内容,深入讲解C++中各种语句的使用方法、常见错误及最佳实践。作为C++基础语法的重要组成部分,掌握语句的正确使用对编写健壮、高效的代码至关重要。
空语句与块语句
空语句(Null Statement)
空语句是最简单的语句形式,仅由一个分号组成:
; // 空语句
使用场景:
- 作为占位符,当语法要求必须有语句但逻辑上不需要任何操作时
- 循环体中不需要执行任何操作的情况
示例:
// 读取输入直到遇到特定值或文件结束
while (cin >> s && s != sought)
; // 使用空语句作为循环体
块语句(Block)
块语句是由花括号包围的语句序列:
{
statement1;
statement2;
// ...
}
关键特性:
- 可以包含零个或多个语句
- 形成独立的作用域
- 常用于需要执行多个语句但语法只允许单个语句的场合
示例:
while (val <= 10) {
sum += val; // 多个语句需要放在块中
++val;
}
逗号运算符与代码可读性
逗号运算符允许在单个表达式位置写多个表达式,按顺序求值并返回最后一个表达式的值。
示例:
while (val <= 10)
sum += val, ++val; // 使用逗号运算符合并两个表达式
可读性分析: 虽然逗号运算符可以减少代码行数,但会降低可读性。建议在简单逻辑中使用,复杂逻辑还是应该使用块语句。
条件语句常见错误
if语句常见问题
- 遗漏分号:
if (ival1 != ival2) ival1 = ival2 // 错误:缺少分号
- 作用域不明确:
if (ival < minval)
minval = ival;
occurs = 1; // 不在if作用域内
- 变量作用域问题:
if (int ival = get_value()) // ival只在if作用域内有效
cout << "ival = " << ival << endl;
if (!ival) // 错误:ival已不可见
cout << "ival = 0\n";
- 误用赋值运算符:
if (ival = 0) // 应该是ival == 0
ival = get_value();
switch语句陷阱
- 忘记break导致case穿透:
switch (ch) {
case 'a': aCnt++; // 没有break会继续执行下一个case
case 'e': eCnt++; // 无论ch是否为'e'都会执行
default: iouCnt++;
}
- 变量初始化问题:
switch (index) {
case 1:
int ix = get_value(); // 初始化可能被跳过
ivec[ix] = index;
break;
default:
ix = ivec.size()-1; // ix可能未初始化
ivec[ix] = index;
}
- case标签语法错误:
switch (digit) {
case 1, 3, 5, 7, 9: // 错误:应该用多个case标签
oddcnt++;
break;
}
- 非常量case标签:
unsigned ival=512; // 必须为常量表达式
switch(swt) {
case ival: // 错误:case标签必须是常量
bufsize = ival * sizeof(int);
break;
}
循环语句最佳实践
while vs for循环选择
while循环适用场景:
- 不确定循环次数的情况
- 基于条件的循环(如读取输入直到特定条件)
for循环适用场景:
- 已知循环次数或范围
- 需要局部循环变量的情况
示例比较:
// while风格
int i;
while (cin >> i) {
// 处理i
}
// 等效for循环
for (int i; cin >> i;) {
// 处理i
}
专家建议: 优先使用for循环,因为:
- 循环变量作用域限于循环内,减少命名冲突
- 初始化、条件和迭代操作集中在一处,更易维护
- 代码更紧凑
do-while循环注意事项
do-while循环保证循环体至少执行一次,但要注意:
- 条件中使用的变量必须在外部声明
- 不要将变量声明放在do块内而在while条件中使用
错误示例:
do {
int ival = get_response(); // 错误:ival在while条件中不可见
} while (ival);
跳转语句与异常处理
goto语句替代方案
goto语句容易导致代码结构混乱,应尽量避免。通常可以用循环结构替代:
goto版本:
begin:
int sz = get_size();
if (sz <= 0) goto begin;
改进为for循环:
for (int sz = get_size(); sz <= 0; sz = get_size())
; // 空循环体
异常处理基础
基本try-catch结构:
try {
// 可能抛出异常的代码
if (denominator == 0)
throw runtime_error("Division by zero");
result = numerator / denominator;
} catch (runtime_error err) {
// 处理异常
cout << err.what() << endl;
}
实战练习解析
重复单词统计
统计输入中连续重复次数最多的单词及其重复次数:
解决方案要点:
- 使用两个string变量分别保存当前单词和前一个单词
- 维护当前重复计数和最大重复计数
- 遇到新单词时重置当前计数
- 每次重复时更新最大计数
除法异常处理
安全除法程序需要考虑除零异常:
关键实现:
try {
if (b == 0) throw runtime_error("Divide by zero");
cout << a / b << endl;
} catch (runtime_error e) {
cout << e.what() << endl;
}
总结
本章深入讲解了C++中各种语句的使用方法和最佳实践,重点包括:
- 空语句和块语句的正确使用场景
- 条件语句(if/switch)的常见陷阱和解决方案
- 循环语句(while/for/do-while)的选择标准和优化建议
- 跳转语句的替代方案和异常处理基础
通过理解这些概念并避免常见错误,可以编写出更健壮、更易维护的C++代码。建议读者结合实际练习巩固这些知识点,为后续更复杂的C++学习打下坚实基础。
Cpp-Primer C++ Primer 5 answers 项目地址: https://gitcode.com/gh_mirrors/cp/Cpp-Primer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考