news 2025/12/30 2:01:30

C++ 条件判断与循环全解:从入门到避坑指南(附 OJ 实战)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ 条件判断与循环全解:从入门到避坑指南(附 OJ 实战)

在 C++ 编程学习中,条件判断与循环是构建程序逻辑的核心基础,也是算法竞赛入门的必备技能。本文基于系统的知识点梳理和 41 道 OJ 编程题实战经验,从语法细节、常见陷阱到优化技巧,全面解析 if-else、switch、while、for、do-while 等核心语法,帮助初学者快速掌握编程逻辑设计,稳步迈向算法竞赛进阶之路。

面向大一/大二初学者,带你稳扎稳打掌握if与循环的正确打开方式!

目录

一、条件判断:让程序学会 "做选择"

1.1 if-else 语句:灵活应对多场景判断

基本语法:

1.1.1 单分支 if

1.1.2 else 与嵌套 if:非此即彼的逻辑判断,例如判断成年与否:

1.1.3 多分支嵌套 if-else:处理多重条件场景,例如判断数的正负:

1.1.4 悬空 else(Dangling else)——高频陷阱!

1.2 switch 语句:高效处理多选项分支

1.2.1 语法结构:

1.2.2 穿透效应(Fall-through):漏写 break 的灾难!

1.2.3 多 case 共享逻辑

1.3 关系与逻辑运算符:构建复杂条件

关系运算符:

逻辑操作符:构建复杂条件

浮点数比较:

条件操作符(三目运算符):简洁的 if-else

二、循环结构:让程序学会 "重复做"

2.1 while 循环:先判断后执行

2.2 for 循环:结构清晰的循环王者

2.3 do-while 循环:先执行后判断

2.4 break 与 continue:循环流程控制

三、循环嵌套:解决复杂逻辑问题

3.1 经典案例:打印乘法口诀表

3.2 实战拓展:水仙花数、质数筛选

四、常见陷阱与优化技巧

五. 总结:避坑清单 + 进阶建议

📌 初学者必记避坑点:

🔜 下一步怎么学?

思考题:


一、条件判断:让程序学会 "做选择"

条件判断是程序根据不同场景执行不同逻辑的基础,核心包含 if-else 系列和 switch 语句,配合关系运算符与逻辑运算符,可实现复杂条件决策。

1.1 if-else 语句:灵活应对多场景判断

if-else 语句是最常用的条件判断结构,支持单分支、双分支和多分支嵌套,满足从简单到复杂的判断需求。

基本语法:

if (表达式) 语句;
1.1.1 单分支 if
  • 当表达式结果非 0(真)时执行语句,0(假)时跳过。例如判断一个数是否为奇数:

#include <iostream> using namespace std; int main() { int n = 0; cin >> n; if (n % 2 == 1) cout << n << "是奇数" << endl; return 0; }

关键点

  • 表达式结果为非 0(真)就执行语句,0(假)则跳过。
  • ifelse不能加分号
  • 如果要控制多条语句,必须加{}

💡初学易错:很多人写if (x = 5)以为是比较,其实是赋值!永远记住:比较用==,赋值用=

1.1.2 else 与嵌套 if:非此即彼的逻辑判断,例如判断成年与否:
if (age >= 18) { cout << "成年" << endl; cout << "可以谈恋爱了" << endl; } else { cout << "未成年" << endl; cout << "不能早恋" << endl; }
1.1.3多分支嵌套 if-else:处理多重条件场景,例如判断数的正负:
#include <iostream> using namespace std; int main() { int n = 0; cin >> n; if (n > 0) cout << "positive" << endl; else if (n < 0) cout << "negative" << endl; else cout << "zero" << endl; return 0; }

1.1.4 悬空 else(Dangling else)——高频陷阱!

if (a == 1) if (b == 2) cout << "hehe"; else cout << "haha"; // 这个 else 实际匹配的是内层 if!

问题:当a != 1时,整个内层 if(含 else)都不执行,不会输出 "haha"

解决方法加花括号明确作用域

if (a == 1) { if (b == 2) cout << "hehe"; } else { cout << "haha"; // 现在 else 明确属于外层 if }

🙋心得:别依赖缩进!花括号{}是逻辑清晰的第一道防线。

1.2 switch 语句:高效处理多选项分支

switch 语句适用于判断条件为离散整型值的场景,结构清晰,可读性优于多层 else-if。

1.2.1 语法结构

switch 后表达式必须为整型,case 后需跟整型常量,default 处理默认情况:

switch (表达式) { // 表达式必须是整型! case 常量1: 语句; break; case 常量2: 语句; break; default: 语句; break; }

例如:判断星期几

#include <iostream> using namespace std; int main() { int day = 0; cin >> day; switch (day) { case 1: cout << "Monday" << endl; break; case 2: cout << "Tuesday" << endl; break; case 3: cout << "Wednesday" << endl; break; case 4: cout << "Thursday" << endl; break; case 5: cout << "Friday" << endl; break; case 6: cout << "Saturday" << endl; break; case 7: cout << "Sunday" << endl; break; default: cout << "input error!" << endl; break; } return 0; }

1.2.2 穿透效应(Fall-through):漏写 break 的灾难!

switch (n % 3) { case 0: cout << "余0"; case 1: cout << "余1"; // 如果 n%3==0,会连续执行这里! case 2: cout << "余2"; }

解决:每个case结尾加break

1.2.3 多 case 共享逻辑

switch (day) { case 1: case 2: case 3: case 4: case 5: cout << "Workday"; break; case 6: case 7: cout << "Weekend"; break; default: cout << "input error!"; }

建议default放最后,处理非法输入。

核心技巧回顾

  1. 每个 case 后需加break,否则会触发 "穿透效应",执行后续 case 代码;
  2. case 与 default 无固定顺序,但建议将 default 放在最后;
  3. 多 case 共享逻辑时,可省略中间 break

1.3 关系与逻辑运算符:构建复杂条件

关系运算符

共 6 种(>、<、>=、<=、==、!=),返回值为 0(假)或 1(真)

⚠️千万别连写比较
错误:i < j < k→ 实际执行(i < j) < k,结果是0 或 1k比较
正确:i < j && j < k

逻辑操作符:构建复杂条件

  • !:取反(!flag表示“如果 flag 为假”)
  • &&:逻辑与(短路求值:左为假,右不执行)
  • ||:逻辑或(短路求值:左为真,右不执行)

💡短路求值妙用:避免除零、越界等错误
例:if (ptr != nullptr && ptr->value > 0)—— 安全!

浮点数比较

因精度问题,切勿直接用==比较浮点数,需通过判断差值是否小于允许误差(如 1e-9):

#include <iostream> #include <cmath> using namespace std; int main() { double a = 0.1, b = 0.2, c = 0.3; if (fabs((a + b) - c) < 1e-9) cout << "a + b 约等于 c" << endl; else cout << "a + b 不等于 c" << endl; return 0; }

条件操作符(三目运算符):简洁的 if-else

语法:条件 ? 表达式1 : 表达式2

int a; cin >> a; int b = (a > 5) ? 3 : -3; cout << b << endl;

适用场景:简单赋值、输出选择。不推荐嵌套使用,可读性差!

📌注意数据类型:如题目范围大,用long long避免溢出!

二、循环结构:让程序学会 "重复做"

循环结构用于重复执行一段代码,C++ 提供while、for、do-while三种循环,适用于不同场景,配合 break 和 continue 可灵活控制循环流程。

2.1 while 循环:先判断后执行

while 循环是最基础的循环结构,先判断表达式真假,真则执行循环体,适用于循环次数不确定的场景。

while ( 表达式 循环条件) { 语句1; 语句2; ... }

语法与实践:打印 1~10 的值:

#include <iostream> using namespace std; int main() { int i = 1; while (i <= 10) { cout << i << " "; i++; // 循环变量调整,避免死循环 } return 0; }
  • 典型应用:反向输出数字每一位、计算数位之和、角谷猜想等,核心思路是通过循环逐步处理数据。

2.2 for 循环:结构清晰的循环王者

for 循环将初始化、判断、调整三部分集中书写,可读性和维护性最优,是最常用的循环结构。

for(表达式1; 表达式2; 表达式3) { 语句1; 语句2; ... }

执行流程:

  • 语法结构for(表达式1; 表达式2; 表达式3),其中表达式 1 初始化循环变量,表达式 2 判断循环条件,表达式 3 调整循环变量。
  • 实践优化:计算 1~100 之间 3 的倍数之和,直接生成目标数避免多余判断:
#include <iostream> using namespace std; int main() { int sum = 0; for (int i = 3; i <= 100; i += 3) sum += i; cout << sum << endl; return 0; }

变量作用域

  • for (int i=...i只在循环内有效
  • int i; for (i=...:循环后仍可用i

注意事项:循环变量的作用域可通过声明位置控制(for 内声明仅在循环内有效),需根据数据范围选择合适类型(如大数值用 long long 避免溢出)。

2.3 do-while 循环:先执行后判断

do-while 循环先执行一次循环体,再判断表达式真假,适用于循环体必须至少执行一次的场景。

  • 实践案例:统计正整数的位数(即使输入为 0 也需统计为 1 位):
#include <iostream> using namespace std; int main() { int n = 0, cnt = 0; cin >> n; do { n /= 10; cnt++; } while (n); cout << cnt << endl; return 0; }

执行流程:

在 do while 循环中先执⾏图上的“语句”,执⾏完语句,在去执⾏“判断表达式”,判断表达式的 结果是!=0,则继续循环,执⾏循环语句;判断表达式的结果==0,则循环结束。所以在 do while 语句中循环体是⾄少执⾏⼀次的,这是 do while 循环⽐较特殊的地⽅。

实践案例:统计正整数的位数(即使输入为 0 也需统计为 1 位):

#include <iostream> using namespace std; int main() { int n = 0, cnt = 0; cin >> n; do { n /= 10; cnt++; } while (n); cout << cnt << endl; return 0; }

2.4 break 与 continue:循环流程控制

  • break:立即终止当前循环,跳出循环体执行后续代码,例如找到质因数后终止循环;
  • continue:跳过本次循环后续代码,直接进入下一次循环判断,注意在 while 循环中需确保循环变量调整在 continue 之前,避免死循环。

while 中慎用 continue
i++continue后,会导致死循环!

#include<iostream> using namespace std; int main() { // 错误示范(死循环!) int i = 1; while (i <= 10) { if (i == 6) { // 跳过 i++,i 永远=6 cout << i; continue; } i++; } return 0; }

for 循环更安全continue后会执行i++

三、循环嵌套:解决复杂逻辑问题

循环嵌套是指在一个循环内部包含另一个循环,常用于处理多维数据或复杂图案生成,核心是明确外层循环与内层循环的职责分工。

3.1 经典案例:打印乘法口诀表

外层循环控制行数(1~9),内层循环控制每行的列数(1~ 当前行数),通过嵌套实现逐行逐列打印:

#include <cstdio> int main() { for (int i = 1; i <= 9; i++) { for (int j = 1; j <= i; j++) printf("%d*%d=%2d ", j, i, i*j); // %2d保证对齐 printf("\n"); } return 0; }

3.2 实战拓展:水仙花数、质数筛选

  • 水仙花数:三位数中各位数字立方和等于自身的数,通过外层循环遍历 100~999,内层循环拆分各位数字:

#include <iostream> #include <cmath> using namespace std; int main() { for (int i = 100; i <= 999; i++) { int tmp = i, ret = 0; while (tmp) { ret += pow(tmp % 10, 3); tmp /= 10; } if (ret == i) cout << i << endl; } return 0; }
  • 第 n 小的质数:通过外层循环遍历自然数,内层循环判断是否为质数,优化点:判断质数时只需遍历到根号 n,减少循环次数:
#include <iostream> #include <cmath> using namespace std; int main() { int n, cnt = 0, i = 2; cin >> n; while (1) { int flag = 1; for (int j = 2; j <= sqrt(i); j++) { if (i % j == 0) { flag = 0; break; } } if (flag) cnt++; if (cnt == n) { cout << i << endl; break; } i++; } return 0; }

四、常见陷阱与优化技巧

  1. 数据类型选择:根据题目数据范围选择合适类型,如超过 int 范围(-2^31~2^31-1)需用 long long,浮点数用 double 避免精度丢失;
  2. 循环效率优化:减少循环内部的重复计算(如预处理常量、提前终止循环),质数判断、因子分解等场景可利用数学性质缩小遍历范围;
  3. 语法细节避坑
    • 避免 if/else 后多语句漏写{}
    • switch 语句勿忘 break,防止穿透效应;
    • 逻辑运算符短路求值可用于简化代码(如a != 0 && b / a > 5避免除零错误);
  4. 代码可读性:合理使用缩进和{},复杂条件可拆分为多个变量,嵌套循环控制层数(避免超过 3 层)。

五. 总结:避坑清单 + 进阶建议

📌 初学者必记避坑点:

  1. if (x = 5)是赋值,不是比较!
  2. 浮点数比较必须用fabs(a - b) < eps
  3. switch每个case后记得加break
  4. else总是匹配最近的if(悬空 else)
  5. whilecontinue可能导致死循环

🔜 下一步怎么学?

  • 刷题平台:在 洛谷 或 牛客 搜索“循环”、“判断”标签,从 P1000 系列开始练手。
  • 扩展阅读:尝试用vector+ 循环解决“输入 n 个数求最大值”问题。

思考题:

  1. 为什么for (int i = 0; i < n; i++)while更适合遍历数组?
  2. 如何用do-while实现一个“输入密码,错误则重试”的程序?

原创不易,如果你觉得这篇博客帮你避开了几个坑,欢迎点赞、收藏、转发!
有任何疑问,评论区见 👇

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/28 8:32:26

iOS自动化测试终极指南:基于idb工具的完整实践教程

iOS自动化测试终极指南&#xff1a;基于idb工具的完整实践教程 【免费下载链接】idb idb is a flexible command line interface for automating iOS simulators and devices 项目地址: https://gitcode.com/gh_mirrors/idb/idb 在当今移动应用开发领域&#xff0c;iOS自…

作者头像 李华
网站建设 2025/12/28 8:32:14

在Windows上轻松运行Linux图形应用的完整解决方案

在Windows上轻松运行Linux图形应用的完整解决方案 【免费下载链接】GWSL-Source The actual code for GWSL. And some prebuilt releases. 项目地址: https://gitcode.com/gh_mirrors/gw/GWSL-Source 你是否曾经希望在Windows系统中运行Linux图形应用&#xff0c;但又不…

作者头像 李华
网站建设 2025/12/29 17:14:14

西门子S7系列MMC存储卡系统恢复解决方案

西门子S7系列MMC存储卡系统恢复解决方案 【免费下载链接】西门子S7_MMC存储卡镜像软件官方最新版 西门子S7_MMC存储卡镜像软件官方最新版 项目地址: https://gitcode.com/open-source-toolkit/d3eab 软件概述与核心价值 本资源包提供了西门子S7系列PLC专用的MMC存储卡官…

作者头像 李华
网站建设 2025/12/28 8:29:43

Windows 7 SP2更新包:为经典系统注入现代生命力

Windows 7 SP2更新包&#xff1a;为经典系统注入现代生命力 【免费下载链接】win7-sp2 UNOFFICIAL Windows 7 Service Pack 2, to improve basic Windows 7 usability on modern systems and fully update Windows 7. 项目地址: https://gitcode.com/gh_mirrors/wi/win7-sp2 …

作者头像 李华
网站建设 2025/12/28 8:28:56

Volumio 2高保真音乐播放器:重塑家庭音乐体验的终极方案

Volumio 2高保真音乐播放器&#xff1a;重塑家庭音乐体验的终极方案 【免费下载链接】Volumio2 Volumio 2 - Audiophile Music Player 项目地址: https://gitcode.com/gh_mirrors/vo/Volumio2 Volumio 2作为一款开源高保真音乐播放器&#xff0c;专为追求极致音质的用户…

作者头像 李华
网站建设 2025/12/29 10:05:55

Boop:让任天堂Switch和3DS文件传输变得简单有趣

Boop&#xff1a;让任天堂Switch和3DS文件传输变得简单有趣 【免费下载链接】Boop GUI for network install for switch and 3ds 项目地址: https://gitcode.com/gh_mirrors/boo/Boop 想要在Switch和3DS之间轻松传输游戏文件吗&#xff1f;Boop就是你的理想选择&#xf…

作者头像 李华