循环边界总出错?8.6章习题复盘与边界思维训练
1. 为什么循环边界是编程新手的“第一道鬼门关”1.1 从一道习题看循环边界的杀伤力编程基础课学到循环这一章大部分人都会经历一个相同的困惑期语法看懂了例子也能跟着敲出来但一到自己独立写习题程序要么少跑一次要么多跑一次要么干脆死循环。这不是你笨而是循环边界本身就是编程里最容易出错的地方之一连工作多年的老手在写二分查找时都可能栽在边界条件上。我当年带过几个刚入门的朋友他们做8.6章习题时最常卡住的就三类题累加求和、图形打印、以及带条件的循环控制。这三类题表面上看是不同题型实际上考的是同一个核心能力——你能不能准确判断循环该从哪里开始、到哪里结束、每次变化多少。把这三个问题想清楚了循环题基本就稳了。这一章习题的价值不在于题目本身有多难而在于它逼着你把“边界”这件事想明白。想明白之后后面学数组、学递归、学算法都会轻松很多。因为数组越界、递归终止条件这些坑本质上和循环边界是同一类问题。1.2 循环三要素初值、条件、步长任何循环都可以拆成三个要素我习惯叫它们“循环三要素”初值循环变量从哪个数开始条件满足什么条件时继续循环步长每次循环变量怎么变化这三者共同决定了循环体执行的次数。很多新手写循环时只关注循环体里干什么却忽略了这三个要素的配合结果就是“逻辑看着对结果就是不对”。举个最典型的例子求1到100的和。有人写成total 0 i 1 while i 100: total i i 1 print(total)这段代码的结果是4950而不是5050因为条件写成了i 100漏掉了100。正确的应该是i 100。就这么一个符号的差别结果差了100。这就是边界的威力。我个人的经验是写循环之前先在纸上或者注释里把三要素写清楚尤其是“循环结束时循环变量应该等于多少”这个问题想清楚了再动手能省掉大量调试时间。1.3 边界错误为什么这么难自查边界错误难查是因为它往往不会报错。程序能跑结果也“看起来差不多”只是差了一点点。这种错误比语法错误更可怕因为语法错误编译器会直接告诉你而边界错误需要你自己发现。我见过一个朋友写打印九九乘法表的程序打印出来是8行而不是9行他盯着代码看了半小时没看出来问题最后发现是外层循环写成了for i in range(1, 9)而Python的range是左闭右开的range(1, 9)只到8。这个坑几乎每个Python初学者都会踩一次。所以复盘这一章习题时重点不是把答案抄一遍而是要把每道题的边界条件单独拎出来分析搞清楚为什么是这个边界换成别的边界会怎样。这种“边界敏感度”一旦建立起来受益终身。2. 累加累乘类习题的边界处理与常见陷阱2.1 求和题的三种写法与边界对比求和是循环习题里最基础的一类但基础不代表简单。以“求1到n的和”为例至少有三种常见写法每种写法的边界处理都不一样。第一种是while循环def sum_while(n): total 0 i 1 while i n: total i i 1 return total第二种是for循环配rangedef sum_for(n): total 0 for i in range(1, n 1): total i return total第三种是直接用数学公式def sum_formula(n): return n * (n 1) // 2这三种写法里前两种的边界最容易出错。while版本的关键是i n这个条件如果写成i n就漏了n。for版本的关键是range(1, n 1)如果写成range(1, n)同样漏了n。而公式法没有循环也就没有边界问题但需要你记得公式。提示初学阶段建议先用循环写理解过程之后再了解公式法。不要一上来就用公式那样练不到边界思维。2.2 累乘题的溢出与初值陷阱累乘和累加结构相似但有两个额外的坑。第一个是初值累加的初值是0累乘的初值必须是1。如果累乘也写total 0那不管循环多少次结果都是0因为0乘任何数都是0。这个错误新手犯得特别多而且因为程序不报错很难发现。第二个坑是溢出。在C、Java这类语言里阶乘增长极快算到13的阶乘就可能超出int范围算到21的阶乘会超出long范围。Python虽然自动处理大整数不会溢出但如果你在学C或Java做累乘题时一定要考虑数据类型的范围。我建议做累乘题时养成一个习惯先估算结果的最大值再决定用什么数据类型。比如算20的阶乘结果约2.4×10^18刚好在64位整数范围内但21的阶乘就超了。这种估算能力在实际开发中很重要。2.3 带条件的累加筛选逻辑与边界叠加稍微进阶一点的题目是“求1到100之间所有偶数的和”或者“求1到100之间能被3整除的数的和”。这类题在累加的基础上加了一个筛选条件边界问题会叠加。以“求1到100之间所有偶数的和”为例有两种写法。第一种是遍历所有数用if筛选total 0 for i in range(1, 101): if i % 2 0: total i第二种是直接遍历偶数total 0 for i in range(2, 101, 2): total i第一种写法的边界是range(1, 101)第二种是range(2, 101, 2)。第二种写法效率更高但边界更容易错。range(2, 101, 2)的最后一个数是100因为101是开区间取不到而步长2保证了所有数都是偶数。如果写成range(2, 100, 2)最后一个数就是98漏了100。我个人的偏好是筛选条件简单时用第一种写法可读性好不容易错筛选条件复杂或者性能要求高时用第二种。但不管用哪种写完都要手动验证一下首尾两个数是否被正确包含。3. 图形打印类习题嵌套循环的边界配合3.1 直角三角形打印的行列关系图形打印是循环习题里最能锻炼边界思维的一类。以打印一个n行的直角三角形为例第1行1个星号第2行2个星号以此类推。这道题需要嵌套循环外层控制行数内层控制每行的星号数。n 5 for i in range(1, n 1): for j in range(1, i 1): print(*, end) print()这里的关键是内层循环的边界range(1, i 1)它依赖于外层变量i。i等于1时内层跑1次i等于5时内层跑5次。如果内层写成range(1, i)那第i行就只有i-1个星号整个图形就变形了。这类题的核心思路是找到每一行的数量与行号之间的函数关系。直角三角形的关系是“第i行有i个”所以内层边界是i。把这个关系想清楚代码自然就出来了。3.2 等腰三角形的空格与星号双重边界等腰三角形比直角三角形难一个档次因为它每行既有空格又有星号而且两者的数量都随行号变化。以n5为例第1行4个空格1个星号第2行3个空格3个星号第3行2个空格5个星号。规律是第i行的空格数是n - i星号数是2 * i - 1。代码n 5 for i in range(1, n 1): for j in range(n - i): print( , end) for k in range(2 * i - 1): print(*, end) print()这道题的边界有三个地方要注意外层range(1, n 1)保证n行空格循环range(n - i)i1时有n-1个空格星号循环range(2 * i - 1)i1时有1个星号。三个边界任何一个错了图形都会歪。我当年做这道题时空格数算错了好几次后来发现是因为我习惯性地把空格循环写成range(n - i 1)多了一个空格。这种错误只能通过实际打印出来看效果才能发现所以做图形题一定要运行看结果不能光靠脑补。3.3 打印图形时的换行与格式细节图形打印还有一个容易被忽略的细节换行。内层循环负责打印一行内的字符外层循环每结束一轮要换行。如果换行位置放错所有字符会挤在一行。在Python里print()默认换行print(x, end)不换行。所以内层循环用end外层循环末尾单独调用print()换行。这个模式要记牢。另外有些题目要求打印的图形有特定格式比如数字金字塔、菱形等。这些题目的思路是一样的先找每行的空格数和字符数与行号的函数关系再用嵌套循环实现。难点不在代码而在找规律。我建议做这类题时先在纸上画出n5的情况标出每行的空格数和字符数规律一目了然。4. 循环控制语句的边界break与continue的正确用法4.1 break的终止时机与常见误用break用于提前终止循环但它的终止时机很容易搞错。看这道题在1到100中找第一个能被7整除的数。for i in range(1, 101): if i % 7 0: print(i) break结果是7正确。但如果把break写在if外面for i in range(1, 101): if i % 7 0: print(i) break那结果还是7但原因是循环第一次就break了只检查了i1。这种错误很隐蔽因为结果“碰巧”对了但逻辑完全错了。如果题目改成“找第一个能被13整除的数”第二种写法就会输出1明显错误。break的位置必须紧跟在找到目标之后不能放在循环体的其他位置。我个人的习惯是写完带break的循环后一定用一个“找不到”的案例测试一下看看循环是否能正常跑完。4.2 continue跳过与边界更新的坑continue用于跳过本次循环剩余部分直接进入下一次。它最常见的坑是如果循环变量的更新写在continue之后那更新语句会被跳过导致死循环。i 0 while i 10: if i % 2 0: continue print(i) i 1这段代码会死循环因为i0时满足偶数条件continue跳过了i 1i永远是0。正确的写法是把i 1放在continue之前或者改用for循环。注意用while配continue时一定要确保循环变量的更新在continue之前执行否则必死循环。这是新手最容易踩的坑之一。4.3 循环嵌套中break只跳一层的陷阱在嵌套循环里break只能跳出它所在的那一层不能一次跳出所有层。这是很多人不知道的细节。for i in range(3): for j in range(3): if j 1: break print(i, j)这段代码里break只跳出内层循环外层循环继续。输出是(0,0) (1,0) (2,0)。如果你想一次跳出两层需要用一个标志变量或者函数返回。found False for i in range(3): for j in range(3): if j 1: found True break if found: break这种写法虽然啰嗦但逻辑清晰。在Python里也可以用for...else结构但那个语法比较绕新手容易搞混我一般建议用标志变量。5. 经典习题复盘从错误中提炼边界思维5.1 素数判断循环上界的数学依据素数判断是循环习题里的经典题。判断n是否为素数需要检查2到n-1之间有没有能整除n的数。但更高效的做法是只检查到√n。import math def is_prime(n): if n 2: return False for i in range(2, int(math.sqrt(n)) 1): if n % i 0: return False return True这里的边界int(math.sqrt(n)) 1是关键。为什么要加1因为range是左闭右开如果不加1当n是完全平方数时平方根那个因子会被漏掉。比如n9math.sqrt(9)是3.0int之后是3range(2, 3)只检查2漏了3结果会把9误判为素数。为什么只需要检查到√n因为如果n有一个大于√n的因子那必然有一个小于√n的对应因子。比如n100因子对是(2,50)(4,25)(5,20)(10,10)所有大于10的因子都对应一个小于10的因子。所以检查到√n就够了。这道题把边界和数学原理结合得很好是训练边界思维的好素材。5.2 水仙花数位数提取与循环范围水仙花数是指一个三位数其各位数字的立方和等于它本身。比如153 1³ 5³ 3³。这道题的循环范围是100到999边界很明确。for num in range(100, 1000): a num // 100 b (num // 10) % 10 c num % 10 if a**3 b**3 c**3 num: print(num)这道题的坑在于位数提取。num // 100取百位(num // 10) % 10取十位num % 10取个位。这三个公式要记牢后面做类似题目会反复用到。循环范围range(100, 1000)的边界是100到999因为水仙花数定义就是三位数。如果写成range(100, 999)就漏了999虽然999不是水仙花数但边界写错说明思维不严谨。5.3 斐波那契数列循环与递推的边界衔接斐波那契数列是1, 1, 2, 3, 5, 8...从第三项开始每项等于前两项之和。用循环实现时边界处理有讲究。def fib(n): if n 0: return 0 if n 1 or n 2: return 1 a, b 1, 1 for i in range(3, n 1): a, b b, a b return b这里的边界有两处前两项单独处理循环从3开始到n。为什么从3开始因为第1、2项已知从第3项才开始递推。循环条件range(3, n 1)保证第n项被算出来。这道题的难点在于理解“循环变量i代表的是第几项”。i3时算第3项in时算第n项。如果写成range(3, n)那第n项就算不出来。这种“循环变量与业务含义对应”的思维是边界思维的高级形态。6. 循环边界自查清单与调试技巧6.1 写完循环必做的三个检查根据我多年的经验写完任何循环后做这三个检查能发现90%的边界错误首项检查循环第一次执行时循环变量是多少这个值符合预期吗末项检查循环最后一次执行时循环变量是多少有没有漏掉或多算零次检查如果循环条件一开始就不满足循环体不执行这个结果合理吗以for i in range(1, n 1)为例首项是1末项是n如果n0则一次都不执行。这三个检查做完边界基本就稳了。我个人的习惯是写完循环后在代码旁边用注释标出首项和末项的值比如# i: 1 - n。这样一眼就能看出边界对不对比在脑子里想要可靠得多。6.2 用打印语句追踪循环变量调试循环最有效的方法是在循环体里打印循环变量的值。虽然简单但极其管用。for i in range(1, 6): print(fi {i}) # 循环体逻辑运行后看输出的i值序列是不是1,2,3,4,5。如果是1,2,3,4那就是边界少了如果是1,2,3,4,5,6那就是多了。这种方法比盯着代码看快得多。对于嵌套循环可以在内层循环打印(i, j)的组合看看所有组合是否都符合预期。图形打印题尤其适合这种方法把每行的空格数和星号数打印出来和纸上画的对比问题一目了然。6.3 常见边界错误速查表错误现象常见原因排查方法结果少一个条件用了而非或range右边界少1检查末项是否被包含结果多一个条件用了而非或range右边界多1检查首项是否从0开始死循环while条件永远为真或continue跳过了变量更新打印循环变量看是否变化累乘结果为0初值写成了0而非1检查累乘变量初值嵌套循环只跳一层break只能跳出当前层用标志变量或函数返回图形错位空格数或字符数的边界算错打印每行的空格数和字符数这张表是我自己踩坑总结出来的基本上循环题的错误都能对上号。做习题时如果卡住了先对照这张表排查比盲目改代码效率高得多。7. 从习题到实战边界思维的迁移价值7.1 数组越界与循环边界的同源性学完循环再学数组你会发现数组越界和循环边界是同一类问题。数组下标从0开始长度是n的数组有效下标是0到n-1。遍历数组时循环条件应该是i n而不是i n否则就会越界。arr [1, 2, 3, 4, 5] n len(arr) for i in range(n): # 正确0到4 print(arr[i]) for i in range(n 1): # 错误0到5arr[5]越界 print(arr[i])这个坑和循环边界是同一个思维模式搞清楚有效范围的首尾。循环题练好了数组题自然就不会错。反过来如果循环边界总是搞不清数组越界会一直困扰你。7.2 二分查找边界思维的终极考验二分查找是边界思维的最高考验因为它的边界条件极其微妙。写错一个符号结果就可能完全错误而且不一定报错。def binary_search(arr, target): left, right 0, len(arr) - 1 while left right: mid (left right) // 2 if arr[mid] target: return mid elif arr[mid] target: left mid 1 else: right mid - 1 return -1这段代码里有四个边界right初值是len(arr) - 1循环条件是left right更新时left mid 1和right mid - 1。任何一个写错都会导致错误。比如循环条件写成left right当数组只有一个元素时就会漏查。我当年学二分查找时反复写错了五六次才彻底搞明白。后来发现只要把“搜索区间”这个概念想清楚——是左闭右闭还是左闭右开——边界就自然确定了。这个思维方式正是从循环习题里练出来的。7.3 把边界检查变成肌肉记忆边界思维的最高境界是变成肌肉记忆写循环时不用刻意想手自然就写对了。这需要大量的练习和复盘。我的建议是每做完一道循环题都问自己三个问题这道题的边界是什么为什么是这个边界换成别的边界会怎样把这三个问题回答清楚比做十道题都管用。另外养成“先写边界再写循环体”的习惯。先把for i in range(?, ?)或者while ?的框架搭好确认边界无误再往里填逻辑。这样能把边界问题和逻辑问题分开处理降低出错概率。循环边界这件事说难不难说简单也不简单。它不需要高深的数学但需要严谨的思维和大量的练习。8.6章这些习题表面上是练循环语法实际上是在训练一种“精确控制”的思维方式。这种思维方式一旦建立后面学什么都会事半功倍。我自己带新人的经验是循环边界过关的人后面学算法、学数据结构都会顺很多循环边界总是含糊的人后面会一直卡在各种越界和死循环上。所以这一章值得多花时间把每道题的边界都抠清楚。

相关新闻

多Agent编排平台实战:从任务调度到可观测性设计

多Agent编排平台实战:从任务调度到可观测性设计

从事AI应用落地这么久,我一直觉得最难的其实不是单个模型的能力,而是怎么把一堆各司其职的智能体(Agent)编排好,让它们在一套统一调度体系里不打架、不掉链子、还能稳定输出结果。这次我要分享的就是我实际搭建的一套智…

2026/10/9 6:27:21 阅读更多 →
Python面向对象实战:命令行通讯录类设计与JSON持久化实现

Python面向对象实战:命令行通讯录类设计与JSON持久化实现

做了这么多年 Python 教学相关的项目,我始终觉得"面向对象"是很多初学者跨不过去的一道坎。语法都认识,class、self、方法都能默写,但一到写实际项目就懵了,不知道类到底该长什么样、方法该放哪个类里。所以我一直主张用…

2026/10/9 6:27:21 阅读更多 →
uv:用Rust重写的极速Python包管理器,Windows安装与高频用法详解

uv:用Rust重写的极速Python包管理器,Windows安装与高频用法详解

你是不是也被 Python 的包管理折腾过?pip install慢、虚拟环境建了又建、Python 版本切换全靠手动改环境变量。这几年冒出来的uv,一句“用 Rust 写的极速 Python 包管理器”就让很多人开始关注。这周我在 Windows 上完整走了一遍安装和基础使用流程&…

2026/10/9 6:26:18 阅读更多 →

最新新闻

浏览器扩展端侧AI推理:WebGPU+ONNX Runtime实战架构

浏览器扩展端侧AI推理:WebGPU+ONNX Runtime实战架构

1. 这不是“把模型塞进浏览器”那么简单:端侧AI在扩展环境里的真实战场“现代浏览器扩展环境下的端侧 AI 推理系统架构与工程实现规范”——这个标题里没有一个词是虚的,每个字都踩在当下前端工程最硬的几块石头上。我从去年开始带团队落地三个真实商用级…

2026/10/9 7:00:47 阅读更多 →
MiMo-V2.6:面向自我改进的工业级强化学习架构

MiMo-V2.6:面向自我改进的工业级强化学习架构

1. 这不是一篇“读论文就完事”的笔记,而是一次对强化学习边界的实地勘探“MiMo-V2.6 - Scaling Reinforcement Learning Towards Self-Improvement”这个标题里藏着三个关键信号:MiMo(Multi-Model,多模型协同)、V2.6&…

2026/10/9 7:00:47 阅读更多 →
Vue过滤器指南:原理、使用场景及面试避坑

Vue过滤器指南:原理、使用场景及面试避坑

最近这道面试题出现的频率不低,尤其面试 Vue 相关岗位时,冷不丁就会被问到:“说说 Vue 过滤器是什么?有哪些使用场景?”很多人第一反应是“用过”,但真让展开讲讲,又容易和计算属性、方法混在一…

2026/10/9 7:00:47 阅读更多 →
人工智能数学基础:梯度下降、优化器与正则化的核心原理与实战

人工智能数学基础:梯度下降、优化器与正则化的核心原理与实战

手头这本《人工智能数学基础》翻到第十八章的时候,我其实松了一口气——前面十几章的线性代数、微积分、概率论铺了那么多,总算开始收网了。这一章讲的内容,很多人可能会觉得“不就是优化算法和正则化嘛”,但真等到训练模型训练不…

2026/10/9 7:00:47 阅读更多 →
WorkBuddy实战:搭建Excel VBA模板母版-副本自动同步系统

WorkBuddy实战:搭建Excel VBA模板母版-副本自动同步系统

我把手头几张各写各的VBA模板文档,用WorkBuddy理成了母版-副本自动同步的总控台。前几周我一直在维护一套Excel进销存模板,里面有报价单、对账单、领料单,每张表里都塞了一段VBA逻辑,逻辑还互相抄。最崩溃的一次是改完报价单的客户…

2026/10/9 7:00:47 阅读更多 →
C语言数据类型与变量:内存机制、指针结构与实战避坑指南

C语言数据类型与变量:内存机制、指针结构与实战避坑指南

C语言的数据类型和变量,看上去是每本教材开篇就讲的基础,但我在实际带项目、看别人代码、甚至帮人排查问题的时候发现,很多人恰恰是栽在这些“基础”上。指针用得晕、结构体定义不明白、类型转换出bug、变量作用域一锅粥——这些问题十有八九…

2026/10/9 6:59:46 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →