OJ基础题3、5、6精讲:输入输出、排序与字符串处理的隐藏坑位

发布时间:2026/10/20 11:43:27

OJ基础题3、5、6精讲:输入输出、排序与字符串处理的隐藏坑位 1. 基础题3、5、6到底在考察什么先看清OJ的门道很多刚开始刷题的同学看到基础 3 5 6这种题号都会有点懵不知道它对应的是什么样的题目也不知道为什么这三道题会被放在一起。我最近把某高校在线评测平台下面简称OJ基础题库里的这三道题从头到尾重刷了一遍才发现这个编号顺序其实是有讲究的它们对应的正是OJ刷题最核心的三件事——输入输出格式处理、基础算法应用、边界情况排查。把这三道题吃透后面再碰更复杂的题起码不会因为低级问题卡到怀疑人生。1.1 三道题在能力阶梯上的位置先说第3题。它在题库里属于输入输出练习的范畴表面上看只是求和但真正让人犯错的点在于题目怎么描述输入数据。OJ和平时自己写程序最大的区别是你面对的不是一个交互式输入而是评测系统预先准备好的一批测试数据。程序要能从标准输入里读完所有数据处理完再按格式输出。很多第一次刷OJ的人会在这里翻车原因就是没有意识到多组数据意味着什么。第5题则是排序。它考察的不只是你会不会写排序算法更重要的是你能否在规定的时限内处理完题目给的数据量。排序是所有算法题的地基树状数组、线段树、二分查找这些高级主题底层全是排序和有序性的思维。这道题我选择了手写排序而不是直接调用库函数原因后面会详细说。第6题是字符串处理。字符串在OJ题里是出了名的看起来简单、做起来全是坑因为你要同时处理字符数组的读入、终止符、空白字符、ASCII边界等一系列问题。这道题我从零重构了读入逻辑才把评测状态从答案错误刷成通过。1.2 拿到题目第一件事别急着写代码我见过不少同学包括早期的我自己一看到题目描述末尾那句输出样例即可就开始噼里啪啦敲键盘。这是刷OJ的大忌。正确做法是先静下心分析三件事输入以什么形式结束EOF特定位数的n换行符、输出对换行和空格的要求是什么、数据范围是否大到需要改变算法策略。以这三道基础题为例它们的输入规模都不大暴力解法完全可行但输入格式的坑相当多。第3题要求你不断读入n如果n等于0就终止第5题第一行给整数个数m第二行给m个整数第6题输入一行字符串可能包含空格。这些细节如果在写代码前没有理清楚后面WA错误答案一次就要回去改半天代码。所以我把刷题的第一个步骤固定成了把题目描述复制到本地用黑色加粗标出输入格式和输出格式两段看完之后再动手。这个习惯看着不起眼但帮我避开了至少80%的格式类错误。2. 第3题多组输入下的求和问题第一步就卡住一半人第3题的原题描述大概是这样的输入包含多组测试数据每组数据第一个数为n表示本组有n个整数当n为0时结束每组输出所有整数的和。看起来是不是很简单但这道题提交一次的通过率并不高原因就出在最基础的读入方式上。2.1 题目形态与隐藏边界先说题目形态。n的取值题目里没有明说但从基础题库的难度来推断n大概率在100以内整数范围也在int可承受的范围内。这意味着不需要开long long也不需要优化算法纯属考察你能不能把多组数据正确地读完、正确地和累加完。隐藏边界有两处。第一处是n为0时结束——有些同学看到这一句会真的把0当作一组数据去处理于是程序卡死在读入循环里或者输出一个多余的0。第二处是每组数据的输出后面要不要空行。OJ评测是逐字符比对的多一个空格、少一个换行都会被标记为格式错误PE虽然比WA好一点但同样不能通过。2.2 错误示范与正确写法我最初提交的版本长这样看起来没毛病但就是WA#include stdio.h int main() { int n; while (scanf(%d, n) ! EOF) { if (n 0) break; int sum 0, x; for (int i 0; i n; i) { scanf(%d, x); sum x; } printf(%d\n, sum); } return 0; }这个代码的问题出在哪它在本地自己试的时候没有问题但OJ里有一个测试点是n为0的情况终止循环理论上也没问题。后来我排查了很久才发现问题藏在scanf的返回值上某些版本的OJ评测数据里会出现只有n后面没有数据的情况此时scanf(%d, n)返回的是0而不是EOF程序就直接进入死循环了。正确的写法应该对scanf的返回值做严格判断#include stdio.h int main() { int n; while (scanf(%d, n) 1) { if (n 0) break; int sum 0, x; for (int i 0; i n; i) { scanf(%d, x); sum x; } printf(%d\n, sum); } return 0; }这两种写法在日常本地运行中几乎看不出差别但在评测系统的边界数据下返回值的差异就是AC和WA的区别。这一点是第3题教给我最深刻的一课OJ的读入永远不要用想当然的方式。3. 第5题排序问题的真相是调库还是手写第5题是给出一组整数要求从小到大输出。题目描述非常短数据规模给的是m小于等于1000看起来很基础。但在刷这道题的时候我更关注的问题是手写排序还是调用库函数不同选择背后的代价完全不同。3.1 为什么排序题容易把人带偏资源少、时间紧的新手最容易走的一条弯路是一看到排序就想直接调用qsort或sort函数。这样做本身没有错在工程开发中我也会这么干但在OJ基础题里我强烈建议至少手写一次排序。原因有三点第一基础题的意义就是让你理解算法本身。冒泡、选择、插入这三种排序代码量都不长自己写一遍能直观感受到比较次数和交换次数这也是后面学习复杂排序算法的前提。第二OJ评测讲究稳定库函数的排序实现虽然强大但如果你不理解它的比较器怎么写反而容易在结构体排序上犯错比如把降序写成升序或者比较函数返回值不符合规则。第三手写排序还能让你养成手动模拟数据流的习惯这在排查WA时尤其重要。3.2 手写选择排序和调用qsort的取舍对m小于等于1000的数据量选择排序的O(m²)完全够用。我实践下来的代码是这样#include stdio.h int main() { int m; int arr[1005]; scanf(%d, m); for (int i 0; i m; i) { scanf(%d, arr[i]); } for (int i 0; i m - 1; i) { int minIdx i; for (int j i 1; j m; j) { if (arr[j] arr[minIdx]) { minIdx j; } } if (minIdx ! i) { int tmp arr[i]; arr[i] arr[minIdx]; arr[minIdx] tmp; } } for (int i 0; i m; i) { if (i 0) printf( ); printf(%d, arr[i]); } printf(\n); return 0; }这里有一个容易被忽略的输出要求两个数之间以空格分隔行尾不能有多余空格但整行末尾必须有换行。我见过很多人在输出时直接写printf(%d , arr[i]);最后一个数后面自然会多一个空格OJ就会判格式错误。如果你确实想用库函数也不是不行。C语言里用qsort注意比较函数要写成int cmp(const void *a, const void *b) { int ia *(int *)a; int ib *(int *)b; return ia - ib; }C里用sort更简单sort(arr, arr m);默认就是升序。但要记住手写排序不是笨它让你在数据范围变大的时候能自然想到归并排序、快速排序这些更优的方案。如果一上来就只会调库后面遇到需要自定义排序规则的题会比较痛苦。4. 第6题字符串处理的隐藏坑位从一次WA说起第6题看起来也不难输入一行字符统计其中数字字符的个数并输出。题干就一句话没有特殊说明。但正是这种没有特殊说明让很多人在同一处栽跟头这一行字符里到底有没有空格4.1 题目描述看似友好陷阱在字符类型判断如果这一行字符不包含空格那么用scanf(%s, str)读入就够了但OJ评测数据里往往混有空格字符串变成类似abc 123 def 456这种形式。scanf(%s)遇到空白字符就会停止读入后面的数字根本读不进来统计结果自然出错。当时我的思路是这样的先用char数组存字符串然后遍历每个字符判断ASCII值在0到9之间就计数。逻辑没错但我使用的读入函数错了。这就是典型的算法对了输入处理错了整个程序等于白写。4.2 排查链路从读入方式到ASCII边界我第一次提交的代码是#include stdio.h #include string.h int main() { char str[1005]; scanf(%s, str); int cnt 0; for (int i 0; i strlen(str); i) { if (str[i] 0 str[i] 9) { cnt; } } printf(%d\n, cnt); return 0; }本地测试abc123没问题但我拿包含空格的测试样例一跑发现输出完全不对。这就是WA的根源。排查过程其实不复杂我用一个最简单的调试方式把读入的字符串原样打印出来看看它到底收到了什么。打印结果发现我的程序只收到了abc后面的123根本没被读进数组。正确的做法是使用gets或者fgets来读取带空格的一整行#include stdio.h #include string.h int main() { char str[1005]; if (fgets(str, sizeof(str), stdin) ! NULL) { int cnt 0; for (int i 0; str[i] ! \0 str[i] ! \n; i) { if (str[i] 0 str[i] 9) { cnt; } } printf(%d\n, cnt); } return 0; }这里要特别留意fgets的两个特点第一它会保留末尾的换行符\n所以遍历时要做判断否则把换行符也算进去就会莫名少1个第二如果字符串长度超过数组容量它会把剩余字符留在输入缓冲区里所以数组尽量开大一点题目没有给范围时1000到2000都是安全的。从这次WA里我总结出一个排查链路先打印读入的内容确认输入处理没错再打印计数结果确认统计逻辑没错最后检查输出格式。把这个顺序固化下来字符串类题目的错误率会直线下降。5. 基础题刷完之后我踩过的坑和真正有用的经验三道题刷完我的评价是它们不难但非常值得做。因为它们展开了一个完整的OJ刷题视角——既有输入输出细节又有算法手写训练还有字符串处理技巧。更关键的是它们让我踩了一串真实的坑这些坑比多刷十道套模板的题还有价值。5.1 新手最容易反复WA的五个细节我把自己在刷题过程中踩过的坑整理了一张表非常有代表性细节错误表现正确做法scanf返回值死循环或漏读数据判断 1而不是! EOF输出行尾空格格式错误PE用辅助变量控制首尾空格字符串含空格只读到空格前内容用fgets/gets读整行换行符残留字符串多出\n遍历时过滤\n数组越界结果错误或崩溃数组开大至少100到200这些细节在教程里很难被当作重点讲但在评测系统里每一个都会让你的提交状态从AC变成WA或PE。5.2 关于OJ刷题节奏的个人建议最后分享一点个人体会。不要因为这是基础题就直接跳过也不要一个晚上把三道题全部硬啃下来。我一个晚上只刷两道刷完先不看别人的题解自己复现一遍再隔两天重新提交一次看自己是否还记得写法的核心逻辑。这种方法比一次刷十道题有效得多。因为OJ刷题的本质不是我做过这道题而是我彻底理解了它背后的模式。基础3、5、6这三道题让我牢牢记住了读入必须严格校验输出格式必须精确到结尾无空格这两个原则。在后面的进阶题目里这两条原则又帮我挡住了一大批低级错误。如果你也正卡在OJ基础阶段建议你可以找找类似的题号认真把输入输出这块地基打牢。刷题这条路没有捷径但它有一个很友好的规律前期踩过的每一个坑都会在后面的题里以另一种形式回报给你。
延伸阅读

更多相关文章

2026/10/20 11:43:26

从零手写Linux字符设备驱动:核心原理与实战解析

"想写个Linux驱动,但打开文档一大堆结构体,完全不知道从哪下手”——这是我被问过最多的一句话。字符设备驱动是几乎所有Linux驱动开发者的第一站,它最简单,却又覆盖了驱动开发最核心的骨架:模块加载、设备号、fi…

2026/10/20 11:38:25

生信论文级R分析流水线:从count矩阵到期刊合规图

简介:本资源是一套面向生物信息学初学者与科研人员的R语言实战代码合集,聚焦高通量组学数据分析全流程,覆盖TCGA/GEO数据获取与质控、基因注释、差异表达分析、功能富集(GO/KEGG/GSEA)、肿瘤突变负荷(TMB&a…

2026/10/20 11:38:25

Automa Chrome插件v1.28.27:声明式Web UI自动化与CI集成实践

简介:Automa 是一款面向前端开发者、测试工程师及自动化需求用户的免费开源 Chrome 浏览器插件,通过无代码拖拽式工作流编排,轻松实现网页自动填写、数据抓取、截图、重复任务执行等 WebUI 自动化操作,显著降低浏览器自动化门槛。…

2026/10/20 12:38:36

大模型私有化部署实战:从硬件选型到监控运维的完整指南

1. 大模型私有化部署到底在解决什么问题第一次接触大模型私有化部署,很多人脑子里冒出来的第一个念头是“把模型下载下来跑起来不就行了”。真到生产环境里走一圈就会发现,下载权重只是万里长征的第一步,后面还有一堆硬骨头要啃。所谓私有化部…

2026/10/20 12:38:36

从“无标题”到好标题:项目定义与命名的实操路径

“无标题”这三个字,大概是我在开发目录里见过最多的命名了。新开一个文档、初始化一个仓库、写完第一版方案,随手保存成“无标题1”几乎是肌肉记忆。你可能觉得这只是个临时占位,等东西做出来再补名字也不迟。但我的经验恰恰相反&#xff1a…

2026/10/20 12:38:36

AgentCore 架构解析:智能体运行时的状态管理与多智能体协作机制

1. 从一次深夜调试说起:AgentCore 到底解决了什么痛点上个月帮一个做智能客服的朋友排查问题,他们的系统接了三四个大模型,每个模型都有自己的工具调用格式、自己的记忆管理方式、自己的任务编排逻辑。结果就是,每换一个模型&…

2026/10/20 12:38:36

MiroFish实测:多智能体协作预测,AI辩论如何提升决策可靠性

MiroFish实测分享:让一群AI互相“吵架”来预测未来如果你关注过AI预测这个方向,应该能感受到一个尴尬的现状:市面上的预测工具要么是单一模型闷头算,要么是黑箱式的“输入历史数据、输出预测结果”,中间过程完全不可控…

2026/10/20 12:38:36

提示词工程实战:从四要素框架到系统提示词与评测迭代

最近这段时间,圈子里不少人都在讨论一份关于提示工程的白皮书——足足68页,从入门方法论到进阶实践技巧都覆盖到了。说实话,提示工程这个概念火起来也有两年多了,但大多数资料要么太学术,读完还是一头雾水;…

2026/10/20 12:33:35

DeepSeek导出PDF指令指南:从HTML排版到打印设置

最近又有朋友问我:DeepSeek到底能不能直接导出PDF?他在对话框里试了好几种说法,什么“请把对话导出为PDF”“生成一个下载链接”,结果DeepSeek要么还给他一段Markdown文本,要么直接说明自己无法生成文件。这个问题我遇…

2026/10/19 18:06:35

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/20 1:05:37

单片机C运行时从启动到多任务:中断安全与共享资源冲突

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

2026/10/20 1:05:37

GCC编译四步详解:预处理、编译、汇编、链接实战

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

2026/10/20 1:05:37

FIW线是什么?FEP注塑线与普通氟塑料线的区别及应用指南

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

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑