ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

for、while、do while循环流程图怎么画:执行顺序、判断框与避坑

for、while、do while循环流程图怎么画:执行顺序、判断框与避坑 给 for、while、do while 画流程图是很多人学编程初期绕不过去的一道坎。我见过代码敲得挺熟练的人一让他把循环的执行过程画成框图立马就卡住画出来的图要么判断框放错位置要么循环的箭头回错了地方。说到底卡住的不是画框这个动作而是脑子里没把“程序先走哪一步、再走哪一步、什么时候回头”这件事彻底想清楚。流程图恰恰是把执行顺序强制可视化的工具而循环又是所有程序结构里执行顺序最容易绕晕的一种所以这三种循环的流程图值得单独拿出来认真捋一遍。这篇内容我打算把 for、while、do while 的流程图从头画到尾讲清楚每一根线为什么这么连、判断框为什么放在那个位置再配上学分累加、Shell 遍历、菜单重试这类能直接抄的案例。不管你是在校学生做算法作业还是刚转行写脚本需要理清逻辑或者带新人时想找一份讲得透的参考资料看完应该都能自己动手画出规范、不出错的循环流程图。1. 三种循环差了十万八千里为什么一定要用流程图捋清楚很多人觉得循环流程图画起来都差不多不就是个菱形判断框加个矩形的循环体嘛。真上手就会发现for 和 while 的图长得像do while 的图恰恰是反过来的判断框要放到循环体后面去。这个差别不是排版习惯而是执行顺序本身的差别画错了图别人照着图读代码就会得到完全错误的结论。所以先把三者的执行模型讲透再谈怎么画顺序不能颠倒。1.1 先判断还是先执行这是三者的分水岭从执行模型上看for 和 while 属于前测循环也就是每轮循环开始前先检查条件条件成立才进入循环体不成立就直接跳过循环体有可能一次都不执行。do while 属于后测循环先把循环体执行一遍执行完了再去检查条件因此无论条件真假循环体至少会跑一次。这三者的差别用一句话概括前两个是“看情况要不要做”最后一个是“先做了再说做完再看要不要继续”。这个差别反映到流程图上就是判断框的位置。前测循环里菱形判断框画在最前面循环体的矩形在它下面返回的箭头从循环体尾部回到判断框上方。后测循环里矩形循环体在最前面菱形判断框在它下面返回的箭头从判断框的“真”分支绕回到循环体上方。如果你画的 do while 图把判断框放到了循环体前面那这张图描述的就变成 while 了图与代码对不上复盘逻辑时就会踩坑。举一个能立刻感受到差别的例子。假设要写一段“不断读取用户输入直到输入为 0 就停止”的逻辑用 while 写条件判断在读取之前如果第一次读到的就是结束标志循环体一次都不执行用 do while 写条件判断在读取之后无论输入什么至少会读一次。这两种写法的流程图几乎一模一样唯独判断框和输入框的先后顺序不同。真实项目里因为搞混这一点导致“明明该跳过的分支却执行了一次”的 bug 非常常见很多时候就是当初画图时没把执行顺序理清。1.2 流程图的框和线先把约定说清楚在动手画之前把几种基本符号的约定统一一下这样无论你用哪款工具画别人都能读懂。行业里通用的符号其实就那么几种椭圆或圆角矩形表示开始和结束矩形表示处理步骤赋值、计算、自增等菱形表示判断分支平行四边形表示输入输出读数据、打印结果箭头表示流向小圆圈表示连接点用于跨页或避免线条交叉。循环流程图里最常出错的是判断框的两个出口。菱形通常有“是”和“否”两个分支习惯上把“是”画在下方或左侧“否”画在右侧或直接指向结束。对于循环来说“是”分支一般接循环体“否”分支接循环后面的语句。还有一种常见画法是在菱形旁边直接标“真/假”或者“成立/不成立”这都行关键是全图统一不要前面用“是/否”后面突然改成“true/false”。再强调一个容易被忽略的细节循环的返回箭头必须回到判断框的入口而不是回到循环体本身。很多新手把返回箭头直接从循环体尾部指回循环体开头这样画出来的图会让人误以为条件不参与后续判断等于默认了死循环。正确的连法是箭头回到判断框上方重新进行一次条件检查这才符合前测循环“每轮都重新判断”的本质。do while 同理返回箭头要从判断结果回指到循环体的入口。线连对了图的语义才立得住。2. for 循环的流程图画法三段式结构的标准画法for 是三种循环里结构最规整的一个初始化、条件判断、变量递增被压缩写在了一行里看起来紧凑但画流程图的时候必须把它拆成三个独立的步骤否则图会失去细节。拆开之后你会发现for 本质上是“初始化 while 结构 递增”的组合只是写法上被合并了。2.1 for 的三段式与执行轨迹拆解以for (int i 0; i n; i)为例它的执行顺序是先执行一次i 0然后判断i n成立则执行循环体循环体结束后执行i再回到判断如此往复。注意初始化只执行一次递增每次循环体结束后都执行判断每轮都执行。画图时要严格按照这个顺序把“初始化”框放在判断框之前把“i”框放在循环体之后、返回箭头之前。[开始] | v [i 0 初始化] -- 只执行一次 | v i n ? -- 每轮都判断 / \ 是 否 | | v v [循环体] [结束] | v [i 递增] | -------- 回到判断框这张图里有两个关键点值得单独说。第一“初始化”框只有一条进线一条出线没有回头箭头指向它因为它只跑一次。第二“i”框在循环体之后返回箭头从“i”指向判断框而不是从循环体直接返回。如果把递增忘在循环体里图就会变成死循环的结构。我见过不少人画 for 流程图时把i直接写进循环体的矩形里虽然运行结果一样但从流程图规范角度看递增是 for 语法自带的控制部分最好单独画一个框逻辑更清晰。2.2 for 循环流程图实操案例先看一个最基础的累加案例把 1 到 100 的和算出来int sum 0; for (int i 1; i 100; i) { sum sum i; } printf(%d, sum);对应的流程图步骤是这样的开始之后先初始化sum 0再初始化i 1然后判断i 100成立就执行sum sum i和i再返回判断不成立则输出 sum 并结束。这里有两个初始化框注意 sum 的初始化只执行一次要画在 i 初始化之前或同级位置不能放进循环体里否则每轮都清零结果永远是 100。再看数组遍历的例子这是实际开发里 for 用得最多的场景int arr[5] {3, 7, 1, 9, 4}; int max arr[0]; for (int i 1; i 5; i) { if (arr[i] max) { max arr[i]; } }它的流程图里菱形判断框会出现两个外层是循环条件i 5内层是arr[i] max。画的时候要注意判断框的嵌套层次内层判断的“是”分支接max arr[i]“否”分支直接汇合到i之前。这种带分支的循环流程图很容易画乱我的经验是先把外层的循环骨架画好保证返回箭头闭合再往循环体内部填充判断分支层次就不会乱。嵌套 for 的流程图稍微复杂一点但拆开看就是两个独立的三段式套在一起。关键规则是内层循环完整跑完一轮外层才递增一次。画图时把内层的“初始化—判断—循环体—递增—返回”整个作为外层循环体的一部分外层的递增框放在内层循环结束之后。只要记住“内层整体是外层循环体里的一块”嵌套结构就不会画错。注意for 循环流程图里“初始化”和“递增”是最容易被漏掉的两个框。漏掉初始化图变成没有起点的循环漏掉递增图变成死循环。画完记得回头数一遍三段是不是都在。3. while 循环的流程图条件当家的前测循环while 的结构比 for 简单语义上就是“条件成立就一直做”。它和 for 的区别在于while 的初始化和变量更新要自己写在循环体内外语法本身不帮你管理所以流程图里这两部分的位置完全取决于代码怎么写的。这也是为什么用 while 写循环时更容易出现忘记更新变量导致死循环的问题。3.1 while 的执行特点与死循环是怎么来的while 的执行顺序是先判断条件成立就执行循环体执行完回到条件处重新判断不成立就跳出。流程图的结构是一个菱形判断框加一个矩形循环体返回箭头从循环体尾部回到判断框。[开始] | v 条件成立? -- 每轮都判断 / \ 是 否 | | v v [循环体] [结束] | -------- 回到判断框死循环在流程图上表现得很直观只要循环体内部的步骤永远不改变判断条件里涉及的那个变量判断结果就会一直为“真”返回箭头就会无限循环下去。比如下面这段代码int i 0; while (i 10) { printf(%d\n, i); // 忘记写 i }流程图里判断框是i 10循环体是打印但循环体里没有任何框改变 i 的值判断永远成立返回箭头就会一直转。排查死循环的时候我的习惯是直接看流程图找到判断框里的变量再看循环体里有没有框去修改它如果没有那基本就是死循环了。这个方法比盯着代码看快得多尤其是逻辑复杂的时候。3.2 while 流程图案例Shell 脚本与用户输入校验Shell 里 while 用得非常多最常见的是逐行读取文件while read -r line; do echo $line done data.txt这里条件部分其实是read命令本身读到内容返回成功读不到就失败退出。画流程图时判断框可以写成“read 成功读取一行?”成立则执行 echo然后返回判断不成立则结束。这类“隐式条件”在 Shell 里很常见画图时要把它显式表达出来不能因为代码里没写while [ ... ]就觉得没有判断框。另一个典型场景是输入校验要求用户输入一个 1 到 10 之间的数字输错了就重新输int n; scanf(%d, n); while (n 1 || n 10) { printf(请重新输入: ); scanf(%d, n); }这段的流程图里第一次 scanf 在循环外判断失败后又进循环体重新 scanf。注意这里有个细节循环外的第一次输入和循环体内的输入是两个不同的框虽然代码长得一样但在执行顺序上一个是进入判断前的准备一个是循环内的重复动作。画图时分开画逻辑才准确。这也是很多人在画输入校验流程图时会合并简化、结果导致读图的人误以为输入框在循环里的原因。心得用 while 画流程图时先在心里问自己三个问题——条件是什么变量控制的这个变量在哪里被初始化在循环体里哪里被更新把这三处的方框都画出来图就八九不离十了。这三个问题对应的正是前测循环最容易出错的位置。4. do while 循环的流程图先执行后判断的“至少跑一次”do while 是三者里最特别的一个判断框的位置和前面两个完全相反。它解决的是一类很实际的问题有些操作天然需要先做一次再看要不要继续。菜单系统、密码重试、用户交互循环几乎都是 do while 的主场。理解它的最好办法就是把它的流程图和 while 的摆在一起对比。4.1 do while 与 while 的本质区别从语法上看do while 是这样写的do { // 循环体 } while (条件);注意 while 后面那个分号这是 C 系语言里唯一一个循环语句末尾要加分号的结构忘掉分号编译器会报错这个坑新手几乎都踩过。执行顺序上先无条件执行一次循环体然后判断条件成立则回到循环体开头不成立则往下走。[开始] | v [循环体] -------- | | v | 条件成立? | / \ | 是 否 | | | | ---------- | | v [结束]对比一下就能看出while 图的返回箭头是从循环体回判断do while 图的返回箭头是从判断结果回循环体。两个图的“循环回流”方向在视觉上是相反的这正是前测和后测的本质差别。判断框的位置一前一后决定了循环体是否可能一次都不执行。4.2 do while 流程图案例菜单系统与密码重试菜单系统是 do while 最经典的应用场景因为菜单至少要显示一次int choice; do { printf(1. 查询 2. 修改 3. 退出\n); scanf(%d, choice); switch (choice) { case 1: query(); break; case 2: modify(); break; case 3: printf(再见\n); break; default: printf(无效选项\n); } } while (choice ! 3);画这张图时循环体里包含“显示菜单”“读取选择”“根据选择执行分支”三个部分其中 switch 那一段可以画成一个大的处理框也可以展开成多个判断菱形。我的建议是如果只是为了表达循环结构switch 用一个处理框概括即可如果要表达完整业务逻辑再展开成分支。图不是越细越好关键看你想让读者关注什么层次。密码重试是另一个典型场景要求最多输入三次int tries 0; int ok 0; do { char *pwd get_input(); if (check(pwd)) { ok 1; } else { tries; } } while (!ok tries 3);这张图里判断条件是两个条件的组合!ok tries 3画判断框时可以写成一个菱形也可以在旁边加括号注明两个条件都要满足。带逻辑组合的条件在实际项目里很常见画图时最好把“与/或”关系标出来避免读图的人理解偏差。这里循环体至少执行一次的意义在于即使输入的密码一次就对也要先把输入框和校验框走一遍这正是 do while 相比 while 的优势所在。注意do while 的“至少执行一次”是它的特点也是它的风险。如果业务逻辑本身允许“一次都不做”那用 do while 就是错的比如批量处理一个可能为空的列表用 do while 就会对空列表也执行一次容易出问题。画图前先确认业务是否真的需要“先做一次”。5. 三种循环流程图放在一起对比选型不再靠猜把三种循环的图和特点摆在一起选型就变得很直接。很多人写代码时纠结用哪个其实只要回答一个问题这段逻辑有没有可能一次都不执行有可能的话用前测循环必须先做一次的话用后测循环。下面用表格把差异列清楚。5.1 结构、执行次数与适用场景横向对比对比项forwhiledo while循环类型前测循环前测循环后测循环判断框位置初始化之后循环体之前循环体之后最少执行次数0 次0 次1 次初始化与递增语法自带需自己写需自己写典型场景已知次数、遍历条件未知、读文件菜单、重试、交互死循环易发点递增写错忘记更新变量条件写错导致不再判断流程图特征初始化判断体递增判断体体判断这张表里最需要记住的是“最少执行次数”这一行。它直接决定了选型遍历数组、计数循环通常用 for因为次数已知读取直到满足条件、条件本身在变化用 while而像交互菜单这种“先显示再判断”的场景就只能用 do while。选型清楚了流程图的方向也就定了前测还是后测一眼分得出来。5.2 嵌套循环与 break/continue 在流程图里怎么画实际项目里的循环很少是单层的嵌套循环的流程图要特别注意层次。嵌套规则是内层循环整体作为外层循环体的一部分内层的返回箭头只在内层自己的判断框和循环体之间连接不能跨层连线。跨层连线是新手最容易犯的错误一旦连错读图的人就无法判断哪条线属于哪一层。[开始] | v [i 0] | v i 3 ? -------否------ [结束] | 是 | v [j 0] | v j 3 ? -------否------ | | 是 | | | v | [打印 i,j] | | | v | [j] ------- 回到 j 判断 | | v [i] ------- 回到 i 判断 -- 这里的连线要回到外层判断break 和 continue 在流程图里的画法也有讲究。break 是直接跳出整个循环箭头要指向循环出口之后的“结束”或下一段逻辑continue 是跳过本轮剩余部分箭头直接回到判断框而不是回到循环体开头。很多人把 continue 画成回到循环体开头这样会让人误以为它要重新执行循环体前面的语句实际上它跳过的是循环体内剩余的语句直接进入下一轮判断。这个区别在排查逻辑时很关键尤其是在循环体里有多个后续操作的场景下画错 continue 的方向会得出完全错误的执行预期。提示画多层循环时可以用不同颜色的线区分层级或者用连接点小圆圈断开长线减少交叉。但颜色和标记只是辅助真正让图清晰的是每一层的返回箭头都回到各自的判断框这条做到位图就不会乱。6. 画流程图的工具选择与实战避坑清单工具的选择其实没那么玄乎能画出规范符号、连线方便、导出清晰就行。不同场景各有所长我把常用的几类按适用性排一下再说说画循环图时反复踩过的坑。6.1 工具怎么挑在线、离线、代码生成各有取舍在线工具如 ProcessOn、draw.io 这类优点是打开浏览器就能用模板多、符号全导出 PNG 和 SVG 都方便适合写文档、做毕设时快速出图。缺点是网络不好的时候会卡复杂大图偶尔会有保存延迟。离线工具如 Visio、本地版的思维导图软件稳定性好、适合画大型复杂图但要装软件协作分享不如在线方便。还有一类是代码生成式比如用 Mermaid 语法写文本再渲染成图适合放在 Markdown 文档里跟代码一起维护改起来只要改一行文本缺点是样式调整不如拖拽工具灵活。具体怎么选看你的使用场景。如果只是给博客挂一张示意图用在线工具拖拽最快如果是毕业设计里要反复修改的技术文档用代码生成式能省不少改图的力气如果是团队协作有统一样式要求的选支持模板和协作的在线工具。对于循环流程图这种结构固定的图我个人更推荐在线拖拽工具因为判断框、返回箭头的调整是高频操作拖拽比改文本直观得多。画图时建议养成几个习惯统一使用一套符号不要一会儿用椭圆一会儿用矩形表示开始主流程线尽量走直线减少不必要的拐弯判断框的“是/否”标注写在线的旁边不要写进菱形里图太大时用连接点分段别硬拉长线。这些习惯不影响正确性但直接影响别人能不能一眼看懂。6.2 实操避坑清单与常见问题速查表画循环流程图踩过的坑我整理成一张表基本覆盖了绝大多数出错场景。常见问题原因正确做法do while 画成了 while判断框被放到循环体前面判断框必须放在循环体之后循环体永远不执行前测循环错误地先画了循环体前测循环判断框在前图变成死循环循环体里没画修改变量的框补上递增/更新框返回箭头连错箭头回到循环体而非判断框前测回判断后测回循环体嵌套层次混乱内外层线条交叉跨层内层返回只连内层判断continue 方向错画成回到循环体开头应直接回到判断框break 位置错画成跳出本轮应指向循环之后的出口判断条件不完整组合条件只画了一个标出与/或关系除了表格里的这些还有几个经验性的提醒。第一画图之前先把代码逻辑用自然语言复述一遍比如“先初始化再判断成立就执行执行完递增再回来判断”边念边画顺序基本不会错。第二画完做一次“走查”用一组具体的数字代入比如循环变量取 0、1、2跟着箭头走一遍看看是不是符合预期这比反复盯着图看有效得多。第三图别画太大一个流程图里塞五六个嵌套判断神仙也看不懂该拆就拆成子流程图用连接点或子流程框引用。最后分享一个我自己的习惯把三种循环的流程图当成模板存下来遇到新逻辑时先套模板再改细节比每次从零画快得多。循环再怎么变骨架就那么几种前测的是“判断在前”后测的是“判断在后”嵌套的是“分层连线”把这三点记牢画出来的图基本不会出结构性的错。剩下的就交给工具去美化排版了。
返回列表