ARTICLE DETAIL

资讯详情

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

三种循环流程图怎么画:for、while、do while 语义与回流线

三种循环流程图怎么画:for、while、do while 语义与回流线 1. 三种循环画在同一张纸上差异一眼就看出来了刚开始学编程那会儿我最烦的就是画流程图。代码写三行跑通了老师非要我画一张图说是“把逻辑理顺”。直到后来帮别人排查一个死循环问题——代码看半天没毛病把图一画出来发现判断框的回流线指错了地方指到了初始化框上面那个变量永远被重置循环永远出不来——我才明白流程图这东西的价值不在于交作业而在于它能把你脑子里的模糊逻辑逼成一个看得见的形状。for、while、do while 这三种循环是 C 语言、Java、Python、JavaScript 乃至 shell 脚本里最基础的三种循环结构也是各类考试、答辩、软著文档、毕业设计里出现频率最高的流程图元素。标题里说的“流程图画法”本质上不是美术问题而是语义问题你得先搞清楚这三种循环各自在什么时刻做判断、什么时候执行循环体、变量在哪里被更新然后才能决定箭头往哪儿画、菱形框放在什么位置。这篇内容我打算按“先看懂框 → 再拆解语义 → 再逐个给案例 → 最后讲踩过的坑”这个顺序来写。无论你是刚接触循环的新手还是被毕业设计流程图卡住的同学或者是需要给团队画清楚业务循环的开发者都能直接从里面挑能用的部分抄走。我会把每个案例的节点、连线、判断条件都写清楚画图之前先把逻辑推一遍图自然就出来了。1.1 循环流程图真正要解决的是什么问题很多人以为画循环流程图就是“把代码翻译成图形”其实不完全对。流程图要表达的是控制流的走向而循环的核心控制流只有一句话从哪进来、判断什么、什么时候退出去、退出去之后去哪儿。把这四件事拆开看循环图就只有三个必备要素。第一是入口也就是循环变量的初始化放在哪里第二是判断节点它是菱形框负责决定“继续循环”还是“跳出循环”第三是回流线也就是循环体执行完之后箭头往哪根线回去。这三种循环的差别换句话说只体现在这三个要素的排列顺序上。一旦你这么理解画图就不再是靠记忆去背模板而是靠推理。你只要问自己三个问题这个循环的判断是在循环体之前还是之后变量更新写在循环体里面还是单独拉出来一个框回流线的终点是判断框还是循环体入口三个问题答完图就定型了而且不会画错。1.2 三种循环的本质差异先判断还是先执行这是所有教材都会讲、但很多同学记不牢的一点。while 和 for 属于先判断后执行条件不成立时循环体一次都不跑do while 属于先执行后判断循环体至少跑一次。这个差别在流程图上的表现非常直接while 和 for 的菱形判断框在循环体的上方do while 的菱形判断框在循环体的下方。我用一个实际场景来说明这个差别为什么重要。比如做一个“输入密码最多重试三次”的功能用 while 写的时候先判断剩余次数是否大于 0成立才允许输入用 do while 写的时候先弹框让用户输入一次然后再判断是否还有次数。看起来结果差不多但如果初始条件本来就不满足——比如次数上限被配置成了 0——while 版本一次都不会执行do while 版本会强行执行一次。这就是“流程图能提前暴露 bug”的典型场景。对比项forwhiledo while判断时机循环体之前循环体之前循环体之后循环体最少执行次数0 次0 次1 次判断框在图上位置循环体上方循环体上方循环体下方初始化框明确独立通常紧贴判断框上方通常在循环外可能离得较远通常在循环外变量更新位置独立更新框回流到判断框写在循环体内部写在循环体内部回流线终点判断框判断框循环体入口注意判断“判断框在上还是在下”这个特征时不要看代码里while关键字写在第几行而要看执行时序。有人把 do while 的图照抄成 while 的样子只把文字换掉这种图一眼就能被看出来是错的。2. 画循环图之前先把流程图的符号规范立起来画图这事儿最怕的不是逻辑错而是符号乱。同一个矩形框你用来表示“处理”别人以为你在表示“模块”审图的人直接懵掉。国家有流程图图形符号的通用规范虽然平时自己画着玩不用那么严格但只要涉及答辩、评审、交付文档符号统一就是底线。我见过最离谱的一张毕业设计流程图判断框画成圆角矩形输入框画成正方形起止框画成菱形整张图看上去像是把符号打乱重排了一遍。逻辑其实没错但评审老师第一句话就是“你这个符号用错了”后面讲什么都不好使了。所以这一章我先把符号讲清楚再讲连线最后讲工具怎么选。2.1 六种核心图形记住它们各自代表什么动作流程图符号看起来多实际常用的就六种循环图里基本只会用到前五种。起止框圆角矩形或椭圆形表示流程的开始和结束。一张图里通常只有一个“开始”和一个“结束”但如果有多个出口也可以有多个结束框。处理框矩形表示一个具体动作比如赋值、计算、调用函数。sum sum i就画处理框。判断框菱形表示条件判断一定要有明确的“是/否”两个出口不能只有一个出口悬空。这是循环图里最关键的框画错了整张图就没意义了。输入输出框平行四边形表示数据的输入或输出。scanf、printf、读取文件、打印结果都用它。预处理框或初始化框六边形有些规范里用来表示循环变量的初始化或者准备动作比如i 1、sum 0。如果嫌符号太多用矩形代替也不会被挑错但要在一张图里保持一致。连接点小圆圈用于跨页或者断线连接。图特别大的时候用能让画面干净不少尤其是嵌套循环那种线特别多的图。提示判断框里的条件文字尽量写成完整的表达式比如i 100而不是只写“循环结束了吗”。审图的人需要看到边界值边界值恰恰是循环最容易出错的地方。2.2 回流线是循环图的灵魂画错一根线全盘皆错流程图的连线是箭头方向代表执行顺序。从上往下画直线从右往左或从下往上画回流线这是一般的视觉习惯。循环图里最重要的就是那根回流线——从循环体执行完的位置向上回到判断框的那根箭头。回流线的终点必须精确。for 和 while 回流到判断框的上方入口也就是重新去判断条件do while 回流到循环体入口也就是重新执行一遍循环体再去判断。这两者画反了流程图表达的逻辑就完全反了。还有一个小细节回流线尽量不要穿过其他框也不要和别的线重叠。如果画到一半发现线缠在一起了说明你的图布局有问题通常的解决办法是把循环体纵向拉长让回流线走图的右侧或者左侧的空白通道形成一条干净的回路。嵌套循环更要留出通道内层的回流线走内圈外层的走外圈不要共用一条。2.3 手绘还是用软件几种常见工具的取舍手绘的好处是快思路还没定型的时候在纸上涂两笔比开软件快得多。但手绘的图没法直接放进文档所以最终还是要落到工具上。工具类型代表方式适合场景需要注意的点在线图形工具ProcessOn、draw.io答辩文档、团队协作、需要精细排版自动布局和手动拖拽要配合先定结构再调位置文本驱动绘图mermaid 语法渲染技术文档、代码仓库内的图手动拖动改过的位置不会保存重新渲染就复原只适合结构图思维导图工具XMind 等梳理层级、拆解知识点它的主职是导图画流程图要靠自由主题加联系线回流线表达起来别扭办公软件Word、PPT 的形状工具临时插图、简单流程对齐和对位很费时间稍微复杂的循环图不要用它硬画专业建模工具各类 UML/BPMN 工具系统级设计、流程建模符号体系不同BPMN 里的网关表达分支合流不擅长表达“回到上一步”我个人的习惯是逻辑还没定型的时候用文本驱动的画法快速出结构确认逻辑没问题之后再用拖拽式工具做最后的精修排版。这样做的好处是逻辑迭代成本极低改一行文字图就更新了不用反复挪框。3. for 循环的流程图画法把三个表达式拆成三个框for 循环是三种循环里结构最规整的因为它的三个组成部分——初始化、条件、更新——都写在同一个括号里一目了然。但也正因为它们挤在一行很多人画图的时候反而不知道该拆成几个框。我的做法是把它们彻底拆开初始化一个框条件一个菱形更新一个框循环体一个框四者串起来。3.1 for 循环的执行时序拆解以for (i 1; i 100; i) { sum sum i; }为例它的执行顺序是固定的执行初始化i 1这一步只执行一次画在判断框上方。进入判断框检查i 100是否成立。成立则执行循环体sum sum i不成立则直接跳到结束框。循环体执行完执行更新i。更新完回到判断框重新判断。这里最容易画错的地方是第 4 步和第 5 步的连线。更新框的出口必须连回判断框而不是连回循环体。如果连回循环体逻辑就变成了“更新一次然后无限循环体”条件永远不会重新检查那就是死循环。另一点是初始化只在最上面执行一次绝对不能出现在回流路径上。节点顺序理清之后参数也好算了。这个循环的判断条件i 100初始值 1每次加 1一共要判断 101 次最后一次判断不成立循环体执行 100 次。把这个次数写在图旁边的注释里是审图人特别喜欢的细节说明你真的推过边界。3.2 案例1 到 100 累加的完整流程图描述直接给节点表你照着摆框就行。序号节点内容图形出线方向1开始起止框向下2sum 0i 1处理框初始化向下3i 100判断框是向下否向右下到结束4sum sum i处理框循环体向下5i i 1处理框更新向上回流到节点 36输出 sum输入输出框向下7结束起止框无判断框的“否”分支走出去之后是先输出 sum 再结束这个顺序不能颠倒。有人把输出框画在判断框的“是”分支上那逻辑就变成每累加一次就打印一次完全变味了。3.3 嵌套 for九九乘法表的图怎么画才不打架嵌套循环的流程图是重灾区主要问题就是线缠在一起。拿九九乘法表来说外层i从 1 到 9内层j从 1 到i循环体输出j × i 结果。它有两个判断框、两个更新框、一条内回流线、一条外回流线。画法上有个诀窍把内层循环整体当成外层循环体里的一个大处理块来看待。具体操作是先把外层结构画出来——外层初始化、外层判断、外层更新、外回流中间空出一大块当作“外层循环体”。然后在这个空白区域里再画完整的内层循环小结构包括内层初始化、内层判断、内层循环体、内层更新、内回流。这样两层结构在视觉上是套娃关系不会交叉。具体到九九乘法表内层初始化j 1必须写在外层循环体内部也就是说外层每转一圈内层变量都要重新初始化一次。这是嵌套循环最经典的坑如果j 1画在了外层循环的外面那内层从第二圈开始就永远不会执行因为j早就超过i了判断直接为否。图上一眼就能看出这个错误——初始化框的位置跑到了外层判断框的上方。4. while 循环的流程图画法判断框永远在循环体上面while 循环和 for 的图形结构几乎一样判断框也在上面区别在于它没有独立的初始化和更新框这两件事一个放在循环前一个写在循环体里。正是因为“更新”被藏进了循环体while 循环在图上反而更容易暴露强迫症级别的问题。4.1 更新语句藏在循环体里的后果写 for 的时候更新是括号里的一部分你不会忘写 while 的时候更新要自己写进大括号里一不留神就漏了。而流程图对这件事的呈现方式极其残酷如果循环体里没有更新框那从循环体出来的回流线会直接回到判断框而循环变量从头到尾没变过判断结果永远相同——图上就是一条纯粹的闭环没有任何能改变判断结果的动作。所以画 while 循环图的时候我强制自己遵守一条规则循环体的最后一个框必须是能让判断条件发生变化的框。这不一定是i也可能是读入新数据、修改标志位、或者推进指针。如果找不出这样的框那这个循环要么写错了要么它本来就是个故意的死循环比如服务主循环后者必须在图上用注释明确写清楚。4.2 案例密码最多重试三次的 while 版本需求是允许用户最多输入三次密码输对就进系统三次都错就锁定。用 while 写逻辑是“只要还有次数并且还没输对就继续输入”。序号节点内容图形出线方向1开始起止框向下2count 0处理框向下3输入 password输入输出框向下4count 3 且 password 不正确判断框是向下否向右5提示密码错误count count 1处理框向下回流到节点 46password 正确判断框是向下提示成功否向下提示锁定7输出结果输入输出框向下8结束起止框无这张图值得说的是判断条件的写法。如果把“输入密码”放在判断框下面就变成了先判断次数再输入那么用户第一次进入时 count 是 0判断成立然后才输入——逻辑也通但判断框里必须写“count 3”输入动作在循环体里。两种写法都对区别在于输入动作发生在判断前还是判断后画图时选一种并保持一致。4.3 案例统计一个整数的位数再给一个纯数值的案例帮助理解“更新动作”在图上长什么样。需求是输入一个正整数输出它是几位数。思路是不断除以 10每除一次计数加一直到数变成 0。初始化n 输入值count 0判断n 0是否成立循环体n n / 10整数除法count count 1回流回到判断框结束输出 count这里的更新动作是n n / 10它就是那个让判断条件最终变成“否”的关键框。如果这个框漏了n永远大于 0图上的闭环就是一个死循环。顺带算一下输入 12345除 5 次变成 0输出 5边界值 0 输入时 count 为 0输出 0这也是为什么用 while 而不是 do while——0 应该输出“0 位”还是“1 位”取决于业务定义用 while 至少不会强行执行一次。5. do while 的流程图画法判断框挪到最下面do while 的图和 while 只差一个位置但语义差别是本质的。它的菱形框画在循环体下方从循环体出来先判断判断为“是”就回流到循环体入口判断为“否”才走到结束。5.1 回流线的终点是循环体入口不是判断框这是 do while 图最容易画错的一点我再强调一次。while 的回流线终点是判断框因为要先判断do while 的回流线终点是循环体入口因为它的语义是“再执行一遍循环体”。判断框的两个出口也容易标反。菱形里的条件是“是否继续循环”那么“是”应该连回流线回到循环体“否”才向下走结束。有些同学习惯了 while 的标法把“否”当成跳出结果 in do while 里标成“否”回流、“是”结束整个逻辑就反了——变成条件成立时退出不成立时循环跟代码完全对不上。5.2 案例菜单程序必须至少显示一次do while 最典型的应用场景就是菜单。用户打开程序菜单必须显示出来然后用户选择操作选完再问要不要继续。不可能出现“先判断要不要显示菜单结果一次都没显示”的情况。节点顺序是这样的开始 → 显示菜单 → 读取用户选择 → 执行对应功能 → 判断“是否继续” → 是则回流到显示菜单否则向下到结束。这里“显示菜单”既是循环体的第一步也是回流线的终点。画的时候把回流线从判断框拉回到“显示菜单”框的上方入口走图左侧的空白通道会很干净。5.3 案例单片机广告灯左右移控制的循环结构在嵌入式场景里比如用单片机做广告灯的左移右移控制循环结构用得很频繁。常见的做法是初始化端口和方向变量然后用循环控制移位的次数每次移位后加一段延时移完一轮再反向。这里的循环画成流程图时循环体里通常包含三个动作输出当前灯状态、延时、更新移位变量。判断框放在循环体下方判断“是否已移完 8 位”。如果用 for 写判断框就在上面两者表达的执行次数一样但 do while 的版本保证了“至少先亮一次灯再谈判断”这在硬件场景里往往更符合直觉。注意嵌入式的循环图里延时框不能省。很多新手画的图只有“移位”没有“延时”审图的人一看就知道你根本没跑过硬件——没有延时灯的移动速度快到肉眼看不见效果就是全亮。6. 三种循环放在一起什么时候用哪个画图之前先选对循环类型比画得快更重要。选错了图要么别扭要么表达不了真实需求。我一般按下面的思路判断。6.1 三条互转规则第一如果循环次数提前就能确定比如“累加 1 到 100”“遍历数组的 10 个元素”选 for判断条件里天然带着计数器。第二如果循环次数不确定取决于运行时的数据比如“读到文件结尾为止”“用户输入 0 就停”选 while初始化拿出来更新写进循环体。第三如果至少要做一次比如菜单、先执行再确认的交互选 do while。这三种结构在逻辑上是可以互相转换的这是画图和读图时的重要基本功。for 可以拆成一个初始化框加一个 whilewhile 可以包装成一个 do while 外加一次前置判断do while 也可以在前面补一次相同的操作转成 while只是代码会重复。能在图上把这种转换画出来说明你对循环的理解已经到位了。判断依据推荐结构图上特征次数已知、有明确计数器for判断框上方有初始化框旁边有更新框次数未知、依赖运行时数据while初始化离得较远更新在循环体内至少执行一次do while判断框在循环体下方回流线指向循环体入口遍历集合元素for 或增强 for判断条件写成“还有下一个元素吗”需要先做再加条件do while循环体在判断之前6.2 集合遍历类循环的图画法很多语言里有增强 for 或者 for-each 结构用来遍历集合、数组、字典。这类循环在流程图上和普通 for 有区别它的判断条件不是数值比较而是“是否还有下一个元素”它的更新动作不是自增而是“取下一个元素”。所以画这类图的时候我会把判断框写成“还有未处理的元素”把更新框写成“取出下一个元素”。循环体里则直接用“当前元素”做操作。这样画的好处是图跟语言的语法细节解耦了不管你是写 Python 的 for 语句、shell 的 for 遍历列表、还是 JavaScript 的数组遍历图都是同一张思路完全一致。7. 画循环图时最容易踩的坑以及怎么排查前面讲的都是怎么画对这一章讲画错了怎么找出来。循环图的错误有一个特点逻辑错了但图形上看起来可能完全正常。一根线画歪一点整个循环的含义就变了而肉眼很难第一时间发现。7.1 死循环在图上长什么样死循环在流程图上有三种典型形态。第一种回流线上没有任何能改变判断条件的框判断框的输入和输出形成了纯闭环第二种判断条件写成了恒真表达式比如1 1或者条件里用了赋值符号第三种更新框的方向写错了比如自增写成了自减导致离目标值越来越远。排查方法很简单我习惯用“追踪法”拿一支笔从判断框出发沿着“是”分支走一圈看回到判断框时判断条件里涉及的变量值有没有发生变化。如果一圈走完变量值一模一样那就是死循环图上一定有问题。7.2 边界值自查清单循环出错的另一大类是边界也就是俗称的差一错误。画完图之后我建议强制自己做一遍边界测试把结果写在图的旁边或注释里。初始值是否满足判断条件不满足的话循环体执行几次最后一次成立时循环变量的值是多少更新之后是否刚好让条件为假循环体内部有没有用到数组下标最大下标和边界值是否对齐累加、累乘这类操作单位元是否初始化正确累加要设 0累乘要设 1。嵌套循环的内层变量是否每轮都重新初始化了这五条我基本上每次画循环图都会过一遍能挡掉九成以上的低级错误。7.3 工具相关的常见问题速查画图的工具问题也很消耗时间这里整理一张速查表。问题现象可能原因处理方式文本驱动画的图手动拖动位置后一刷新又乱了渲染是按文本结构重新计算的手改的位置不持久结构用文本画精修换拖拽式工具回流线和别的线重叠成一团布局没留通道循环体太扁纵向拉长循环体回流线走外侧通道导出后图里的字被裁掉画布尺寸不够或字体不兼容导出前留足边距尽量用通用字体思维导图工具画出的循环图很别扭导图工具擅长层级不擅长闭环导图只用来梳理结构流程图换专用工具系统级流程图里画了循环评审说不对建模规范里的分支合流符号不表达回到上一步循环用明确的回流线或循环标记表达别硬套网关符号8. 把循环嵌进系统级流程图里才是真正能交付的图单个循环的图练熟之后下一步就是把它放进真实的系统里。毕业设计、软著文档、需求说明书里的流程图很少只有孤零零一个循环通常是几十个框、好几条分支、多个循环嵌套在一起。这时候“循环画得对不对”已经退居其次“整张图读不读得懂”才是关键。8.1 用户管理模块里的循环节点拿用户管理模块举例登录部分用到的就是前面讲的密码重试循环用户列表展示部分用到的就是分页遍历循环——只要还有下一页就继续拉取数据。这两类循环在系统图里通常不需要展开画到最细可以把“密码校验重试”打包成一个处理框在旁边用一个小图或者注释说明它内部的循环结构。我的做法是分两级画主流程图只显示模块级的框和箭头“密码重试循环”画成一个矩形框然后单独出一张图把这块的内部循环展开标上前面讲的判断框和回流线。这样评审的时候主图清爽细节图也有两边都能交代清楚。图书馆管理系统的借阅、归还、超期提醒这些功能同样是这个套路循环逻辑单独成图。8.2 业务建模图里的分支和循环不是一回事有些同学把循环画到业务建模图里用网关符号去表达“回到上一步”结果评审说看不懂。这里要区分清楚分支类符号表达的是“条件不同走不同路径最后合并”它描述的是同时存在多条路径循环描述的是同一个动作重复执行。两者不是一回事。如果非要在业务建模图里表达循环正规做法是给活动节点加上循环标记或者单独画一张子图说明这个节点内部是个循环。硬用分支符号去绕图会变得又乱又难懂典型的费力不讨好。8.3 交付前把图过一遍的实操清单图纸交付前我一般会做几件事。先通读一遍从开始框出发手动走完每条路径尤其确认每个判断框的两个出口都有终点没有悬空的箭头。然后检查所有的循环是否都有退出路径没有的话是否有明确注释说明这是有意为之。接着看符号是否统一同一张图里不能一会儿用圆角矩形当处理框一会儿用矩形当起止框。最后检查文字判断框里的条件要具体到变量名和边界值处理框里的动作用动词开头输入输出框写清楚输入的是什么、输出的是什么。我在实际带新人时发现图上的问题往往和代码里的 bug 是同一批问题。能在一张图上把循环画清楚的人代码里也很少出现死循环和差一错误。这个习惯养成之后画图就不再是负担而是排查问题的手段——看着图想逻辑比盯着代码一行行猜快得多。这个套路后续还可以往两个方向扩展一个是把循环和递归放在一起对比着画看看同一个问题两种结构在图上差在哪另一个是把循环图直接对应成测试用例每一个边界值就是一条测试路径图上的路径走通了用例也就设计完了。
返回列表