简介C语言循环练习题共23题是一份面向初学者的编程练习资料包内容覆盖最大数查找、素数判断、数列求和、水仙花数、数位之和、最大公约数、斐波那契数列判断等经典场景重点训练for、while循环结构及循环嵌套、条件判断与算术运算的综合应用。资料以单个docx文档整理压缩包约3.85MB题目描述清晰每题均包含输入格式、输出格式、样例输入输出及测试用例便于自学与教师布置作业。已有4248人学习浏览。适合刚学完循环章节、希望巩固语法与逻辑思维的高校学生和编程爱好者通过完成这23道题能系统掌握循环控制流程学会处理批量数据统计、迭代计算、数字拆分等常见编程任务同时积累调试与边界条件处理经验。1. 语法背完了怎么一写 C 语言循环题还是翻车C 语言循环练习题共 23 题这类清单看起来是整本教材里最不起眼的基础训练for 三行、while 一个条件语法十分钟背完。但真到期末机试或面试手写白板翻车最多的恰恰是循环。循环边界多一个等号统计结果差一位scanf 读完数字后回车没清掉下一次循环直接跳过嵌套循环里一个 break 下去外层还在不知情地继续跑。这批题表面在练语法实际在练你对循环变量、边界值和退出条件这些“易碎点”的敏感度。适合三类人期末机试前想快速查漏补缺的新手、从脚本语言转回 C 想重新捡起底层控制流的人、工作后想用一组小题目检验基础牢不牢的应用开发者。下面按我实际带人做题的顺序把这 23 题拆成三阶段讲清楚再把工具链、调试方法和高频翻车点一并写透。2. 把 23 题拆成三阶段单层、双层到底在练什么23 道题不能一口气从头写到尾。把它们按难度和练习点拆开练起来才有节奏。我习惯分三个阶段第一阶段是单层 for 与累加器解决“循环怎么走得动”的问题第二阶段是 while 与 do-while 的边界控制解决“循环什么时候停”的问题第三阶段是嵌套循环与算法雏形解决“两层循环怎么配合”的问题。先看整体分布。阶段大致题号核心训练点最常翻车的位置一约 1~9 题单层 for、累加器、计数累加器没初始化、类型溢出二约 10~17 题while、do-while、输入终止scanf 返回值、EOF、死循环三约 18~23 题嵌套循环、素数、排序内外层变量混用、break 范围三个阶段是递进关系先保证循环能按预期多走几个来回再保证它该停的时候停得干净最后才谈两层循环之间的配合。很多人直接跳到第三阶段打印菱形写不出来又回来看 for 语法效率很低。先把每个阶段的典型题做扎实比追求数量更重要。2.1 第一阶段约 1~9 题单层 for 与累加器这一阶段的题目形态很集中求某个区间的累加和、求阶乘、统计能被某个数整除的个数、把一串数倒序输出。共同点是只有一个循环循环体里只做一件事累加或计数。真正拉开差距的不是循环本身而是累加器的初始化和循环变量的类型选择。第一个典型题是“求 1 到 n 的累加和”代码如下。#include stdio.h int main(void) { int n; long long sum 0; // 累加器必须初始化否则结果是随机值 scanf(%d, n); for (int i 1; i n; i) { sum i; // 每一轮把当前的 i 加进 sum } printf(%lld\n, sum); return 0; }for 循环的执行顺序要刻进直觉初始化只走一次每次进入循环体之前判断i n每轮循环体执行完再执行i。很多人把注意力放在sum i上却忽略了i是循环能停下来的关键。如果步进表达式被改成i 2循环次数就会变化边界值也会跟着变这时候再谈“循环的规律”才有意义。这里有一个必须提前解释的参数选择累加和为什么用 long longint 的取值范围大概在正负 21 亿之间n 等于 65535 时累加和就已经逼近 int 上限n 再大一点就会溢出成负数。练习题通常不会给超大 n但把 sum 声明成 long long 是专业习惯避免为一道题反复改类型。i 本身用 int 足够它的任务只是走到 n不会比 n 更大。这一阶段还经常出现“统计因子个数”这类题本质是把累加换成计数。写法上要注意循环体里加一个 if满足条件时count而不是sum i。很多新手把计数值也加到 sum 里输出结果就成了求和而不是计数。先想清楚“这一轮我要改变哪个变量”再写循环体。2.2 第二阶段约 10~17 题while 与 do-while 的边界控制第二阶段开始出现“读到输入 0 为止”“至少执行一次”等带终止条件的题目。这类题用 for 也能写但 while 和 do-while 更贴近语义。这一阶段真正的门槛是 scanf 的行为它到底读走了什么、留下了什么。典型的题目形态是“从输入读一串整数读到 0 结束输出个数和平均值”代码可以这样写。#include stdio.h int main(void) { int x; int cnt 0; double sum 0.0; while (scanf(%d, x) 1 x ! 0) { sum x; cnt; } if (cnt 0) { printf(count%d, avg%.2f\n, cnt, sum / cnt); } return 0; }这段代码把两个最容易犯的错一起避开了。第一个错是“先读一次再在循环里读第二次”导致第一个数被漏掉第二个错是写成while (x ! 0)但 x 在第一次判断时还没有被赋值属于未初始化变量。scanf(%d, x) 1的意思是“成功读到一个整数”它读不到数字时返回 0 或 EOF循环自然退出不会死循环。while 的循环条件要按“安全退出优先”来设计。一个常见做法是条件里先写 scanf 的返回值再写业务条件顺序不能反。因为x ! 0必须在 x 有值之后判断才成立。平均值的分母 cnt 可能为 0所以输出前必须加if (cnt 0)保护这也是这道题最容易忽略的隐藏细节。do-while 在这一批题里通常出现在菜单场景比如“打印菜单、读选项、根据选项执行、直到选择退出”。这类题天生适合 do-while因为菜单至少要显示一次用户才有东西可选。写成 while 就得在循环前先手动执行一次菜单函数代码冗余且容易漏。do-while 的坑在写条件时容易按 while 的习惯去套结果条件里的变量第一次还未被读到。记住do-while 的循环条件在循环体执行完才判断所以“退出条件”要在变量有值之后再写。2.3 第三阶段约 18~23 题嵌套循环与算法雏形最后几题进入嵌套循环打印三角形、九九乘法表、打印菱形、素数判断、冒泡排序。这些题单层循环做不了核心是搞清楚哪个循环管行、哪个循环管列。以九九乘法表为例先把行和列的职责分清楚。#include stdio.h int main(void) { for (int i 1; i 9; i) { // 外层 i 管行 for (int j 1; j i; j) { // 内层 j 管列ji 形成三角 printf(%d*%d%2d , j, i, i * j); } printf(\n); // 每行结束换行 } return 0; }外层变量是行号内层变量是列号j i让列数跟随行数增长所以输出是左下三角。如果把内层条件改成j 9就会变成完整方阵。打印图形类题目里内层条件的写法是边界检查的第一落点三角形是j i倒三角是j n - i 1菱形则需要把行列关系换算成两条不等式。先确定行号 i 的物理意义再写出本行列的取值范围最后才写打印语句顺序不要倒过来。素数判断是嵌套循环里最值得精读的题。外层循环遍历待判断的数内层循环从 2 试除到平方根一旦发现能整除就说明不是素数。这里的break只跳出内层循环外层还要继续处理下一个数所以不能靠 break 一个语句搞定整个流程。常见做法是设一个标志位内层发现非素数时把标志位置位再决定外层是否提前结束。嵌套循环还有一个很重要的自查点循环体里是否修改了控制变量。比如在 for 的循环体里给 i 重新赋值就会让步进表达式变得不可预测这是很多“循环次数不对”问题的根源。下面这张参数自查表是我让学习者做题前先过一遍的清单23 题里每一题都能用上。自查项检查内容出错信号变量类型累加、计数用 int 还是 long long输出变负数或结果跳变边界表达式还是从 0 还是 1 开始输出多一行或少一行步进位置i是否每次循环体后都执行死循环或循环次数不对循环体修改是否改写了 i、n 等控制变量结果与手推不一致3. 用最小环境跑通 23 题编译命令、输入模板与测试记录工具链先配好再谈刷题效率。我的建议是最小方案一个能写 C 的编辑器加一个终端就够不需要重型 IDE。23 个题目本身就是最好的测试环境编译和运行越直接调试时的反馈回路就越短。下面从编译命令、总控模板、测试文件三块讲。3.1 最小命令用 gcc 编译并打开全部警告gcc -Wall -Wextra -stdc11 test01.c -o test01 ./test01-Wall和-Wextra打开大多数常见警告比如未初始化变量、比较时类型不匹配。-stdc11确保 for 内部声明变量、long long 这些 C11 特性能够正常使用。如果你在某个 IDE 里点按钮运行这条命令可以跳过但我建议至少在终端成功跑一次。终端会原样显示警告和报错信息IDE 的控制台面板经常把关键行折叠掉。第一次编译时看到 warning 不代表程序不能跑但它是在提醒你“这里有隐患”。比如 scanf 的返回值没使用时警告会提示“忽略返回值”。把警告当作免费评审比输出结果正确更重要。刷 23 题期间我会要求每次编译都确保警告数为 0再开始跑测试数据。3.2 通用输入模板为什么用 do-while 做总控刷题时如果每题都从#include stdio.h开始写前三行代码会消耗掉不少耐心。我习惯用一个最小代码模板把总控逻辑固定下来每道题只替换中间的部分。模板如下。#include stdio.h int main(void) { int choice; do { printf(1. run case\n); printf(2. quit\n); printf(choice: ); scanf(%d, choice); if (choice 1) { // 把当前练习的题目逻辑放到这里 // 例如调用 print_triangle(n) } } while (choice ! 0); return 0; }用 do-while 而不是 while 的原因前面提过菜单至少要显示一次循环体先执行再判断退出正好匹配“显示菜单、读选择、再判断”的过程。这里的 choice 用 int如果改成 char 并且用%c接收就要额外处理上一次输入残留的换行符平白增加一个陷阱。模板里的 scanf 返回值最好也检查一下输入非数字时按scanf(%d, choice) 1来判断能避免输入字母后死循环。这个模板的真正价值是让 23 道题共用一套运行框架。做题时只关心被注释位置的那一段逻辑其他代码不用重复写。等全部题做完再把每一题从 main 里拆成独立函数模板就会变成非常顺手的测试工具。3.3 文件组织与测试记录把“看答案”变成“查结果”刷 23 题不建议把所有代码塞在一个文件里我推荐的划分方式是按阶段建文件每个题目独立一个 .c 文件文件名能看出题号。阶段文件范围练习重点建议用时入门test01.c ~ test09.c单层 for 与累加器每题 20~40 分钟进阶test10.c ~ test17.cwhile 与输入终止每题 40~60 分钟综合test18.c ~ test23.c嵌套循环与算法每题 60 分钟以上每个文件只放当前题目的实现编译时单独编译。这样哪个文件报错一目了然不会出现“改了一个文件另一个也挂掉”的情况。测试数据单独存成文本文件用重定向喂给程序免去每次手动敲输入。./test01 case1.txt ./test01 case1.txt out1.txt第一条命令把 case1.txt 里的内容当作键盘输入。第二条命令把程序输出存到 out1.txt方便和期望输出做对比。反复跑测试时这个习惯能节省大量时间改一次代码敲一次重定向命令就够了不用重新输一遍数据。4. 循环题总是差一点调试思路与边界排查23 道题里排错占用的时间几乎和写代码一样多。差别在于会调试的人盯着输出想原因不会调试的人反复改代码碰运气。循环题的输出维度通常很少无非是数字、行、列只要按步骤排查基本都能在十分钟内定位。这一章讲我常用的四步排查法。4.1 先列边界表再敲代码拿到一道循环题不要立刻写代码。先在草稿纸上列一组边界值最小值、中间值、最大值、特殊情况。以“求 1 到 n 的累加和”为例边界表长这样。输入 n期望输出1123361055四组数据写完后拿这组数当测试用例去验证代码。大多数循环题的错误集中在 1 和 0 的边界上n1 时循环能不能进入、n0 时会不会输出错误结果。先手推出期望值再让程序输出来比对就能把“那个数不对”变成“n3 时第 2 行多了一个字符”定位范围急剧缩小。4.2 printf 插桩循环题排错第一利器如果输出与期望不一致我一般不会立刻开断点调试而是先插入 printf 观察循环变量的变化轨迹。拿累加和举例插桩长这样。#include stdio.h int main(void) { int n; long long sum 0; scanf(%d, n); for (int i 1; i n; i) { printf(debug: i%d, sum%lld\n, i, sum); // 临时插桩排完删除 sum i; } printf(result%lld\n, sum); return 0; }插桩位置决定你能看到什么。放在 sum 累加之前能看到“进入每一轮时 sum 是多少”放在之后能看到“这一轮的影响是什么”。如果 i 的打印序列是 1、2、3、5、6中间缺了 4说明循环条件或步进有问题。调试完必须把插桩行删掉否则输出混进 debug 字符和期望文件对比时全是噪音。若你用的是支持断点的 IDEfor 首行打断点、单步执行、每步看变量面板效果比 printf 更直观。但纯输入输出型题里断点要反复按 F10 才能看完一轮循环效率不比 printf 高。两者结合是常见做法先用断点判断循环走没走再用 printf 看具体值。4.3 从现象反推多一行、少一行、错一位分别看哪里输出和期望不一致时现象本身就能指出检查方向。以下是我在带人过程中总结的对应关系。现象优先检查输出多一行边界是否多用了一次内层 j 的初值是否从 0 开始输出少一行边界是否误写为最后一次迭代是否被跳过字符错位循环变量从 0 还是 1 开始printf 是否用了 i 而不是 j程序卡住步进是否被 continue 跳过循环体是否忘了读新输入多一行和少一行大多数时候是与的问题。以打印 n 行三角为例外层写成i n会多打一行写成i n会少最后一行。字符错位多半是数组下标从 0 开始而循环变量从 1 开始或者在打印语句里把行变量当成列变量输出。这类错误肉眼仔细看一遍代码也能发现但先看现象能少走弯路。死循环是最容易让人崩溃的。排查顺序先看步进表达式是否在循环体的每个分支都被执行再看 while 条件里是否读取了新的输入最后看循环体里有没有赋值语句修改了循环变量。三个位置都正常死循环基本不会发生。4.4 编译能过、输出不对的“玄学”时刻有一种情况会被新手当成玄学代码能编译手边推演也对但结果就是不对。最常见的原因有两个。第一个是 for 后的分号for (i 0; i n; i);会在循环结束才执行后面的代码块导致循环体整体只执行一次。第二个是写成把比较写成了赋值循环条件变成常量真值循环次数全乱。这两种错误肉眼检查时要特别留意代码最后的分号和判断条件。另一个容易忽略的点是条件表达式的写法。if (i n)和if (n i)对编译器没有区别但对检查的人有区别。把常量写在左边是不少老程序员防止误写成赋值的小习惯一旦写成n i编译器会直接报错。遇到“道理都对但结果不对”时先检查这两个位置通常能省下大把时间。5. 循环练习避坑五个高频翻车点与解决方案23 道题里最值得记录的翻车点往往集中在输入输出和循环退出这两个环节。把下面五条避坑记录背下来再去做题会少走很多弯路。每一条都按“现象、原因、解决”的顺序整理可以当成排错手册来翻。5.1 scanf 后的换行符第二次输入直接跳过现象菜单循环里第一次选择后程序立刻执行了下一次逻辑第二次输入还没敲就跳过了。原因上一次输入数字后按下的回车键残留在输入缓冲区被下一次scanf(%c, ch)或getchar()直接读走。解决输入字符前先用while (getchar() ! \n);清掉缓冲区或者把格式串改成 %c前面的空格会让 scanf 跳过所有空白符。数字输入不受影响但菜单题经常混合%d和%c这个坑就特别容易出现。5.2 循环结束后用 i 当结果值总比预期大 1现象循环结束后打印 i发现它是 n1不是最后一次循环体内的值。原因for 的步进表达式i在每轮循环体执行完之后运行跳出循环时 i 已经被多走了一步。解决要在循环结束后保留“最后一次满足条件”的值单独声明变量保存不要直接拿循环变量当结果。比如判断某数是否为素数时用int is_prime 1;作为标志位而不是循环结束后看 i 等不等于 n。5.3 大数累加与阶乘溢出结果突然变成负数现象n20 的阶乘输出是负数n 再大一点输出变成 0。原因int 上限约 21 亿20 的阶乘约 2.43 亿亿早就溢出。溢出后相当于截断操作出现负数或 0 都是正常现象。解决累加和用 long long阶乘用unsigned long long或直接改 double。练习题本身不要求超高精度但考察点就是你有没有选对类型。做题时在注释里标一下 n 的安全范围比如“int 累加安全到 n65535”比临时查表快得多。5.4 嵌套循环里的 break只跳出内层现象双重循环中内层满足条件 break 后外层还在继续跑浪费大量时间甚至输出多余结果。原因C 语言的 break 只终止离它最近的一层循环。解决用一个标志位控制外层例如int found 0;内层找到时置为 1外层每轮开头判断if (found) break;。更直接的做法是使用 goto 跳到循环结束位置在跳出深层循环的场景里goto 是合法且清晰的工具不必避讳。5.5 读到 EOF 时死循环现象题目要求“读到文件结尾结束”写成while (scanf(%d, x) ! EOF)后输入一个字母程序就卡住不动。原因scanf 遇到非数字字符时返回 0并且不消费那个字符条件一直为真循环退不出去。解决把条件统一写成while (scanf(%d, x) 1)。它在读到 EOF 时返回 EOF读到字母时返回 0两种情况都能安全退出只有成功读到数字才进入循环。多组数据题优先用这个写法能省掉一半的排错时间。这五条基本覆盖了循环练习里 80% 的错误来源。做题时如果输出不对先对照清单过一遍再考虑更复杂的逻辑问题。修改边界条件后一定把之前跑过的测试数据重新跑一遍哪怕只改了一个字符也得重跑这是刷题最重要的习惯之一。6. 把23题变成自己的代码库验证习惯与函数化改造跑通 23 题只是第一步。这批题真正的价值是帮你形成一套可以迁移到任何 C 项目里的验证习惯。我建议练完后回头做一次整理每题保留一个 .c 文件、一组测试输入、一份期望输出三者放在同一目录。这样以后任何一次修改都能快速回归测试而不只是“当时能跑就行”。函数化改造是把题目变成代码库的关键一步。以打印三角形为例把整个逻辑抽成函数后主程序只需调用并传参。void print_left_triangle(int n) { for (int i 1; i n; i) { for (int j 1; j i; j) { printf(*); } printf(\n); } }抽函数的意义不只是减少重复代码而是让“规律”变成“参数”。同一个函数传入 3 和 5 就能打印不同尺寸的三角形编译器会帮你检查参数类型以后想改打印字符也只需要改一处。到这一步做题的思维就从“写一次性的代码”升级成“写可复用的工具”。还有一个更进一步的练法把打印图形类题目合并成一个函数增加方向参数。左边三角、右边三角、倒三角全部由同一个函数加一个参数控制23 题里相近的题目会迅速收敛成少数几个模式。注释里标一下每题的复杂度比如O(n^2)也为后面学算法打基础。这套练习给我最深的教训是改完边界条件不重跑全量测试。当年做打印三角形题把j i改成j n以为只是宽度变化结果形状彻底错位自己没发现直到交作业前一晚整体对了一遍输出才救回来。现在我习惯把每个用例的期望输出存成文件任何修改后统一对比这个习惯比刷完 23 题本身更值钱。希望帮到你。本文还有配套的精品资源点击获取