两道C入门题:scanf多组输入怎么判断,最大最小值怎么初始化

发布时间:2026/10/4 1:40:14
两道C入门题:scanf多组输入怎么判断,最大最小值怎么初始化
这两道题来自我学习 C 时做的牛客入门练习BC49 判断两个数的大小、BC95 最高分与最低分之差。题目本身不复杂但多组输入和初始化值得单独说清楚。1. 判断两个数我的原解法为什么是 2每组读两个整数输出它们的大小关系。我的原解法核心保持不变#includestdio.hintmain(void){inta,b;while(scanf(%d %d,a,b)2){charrelation;if(ab)relation;elseif(ab)relation;elserelation;printf(%d%c%d\n,a,relation,b);}return0;}测试输入3 2 2 2 -1 5输出32 22 -15我的出发点是“一组有两个数”因此循环应当在两个转换都成功赋值时进入。scanf的返回值不是读到的字符数也不是简单的成功或失败开关。四种输入四种情况输入情况%d %d的返回值能否处理完整一组3 22能3 x1不能第二次转换匹配失败x0不能第一次转换就匹配失败第一次赋值之前就遇到输入结束EOF不能如果先读到一个整数再遇到文件结束返回 1不是 EOF。EOF 是一个负的整型常量本机值为 -1但代码不该把某个实现值当成所有实现的规定。为什么 ! EOF 和按位取反容易误导while (scanf(%d, n) ! EOF)在输入x时可能继续进入循环返回 0不等于 EOF。错误字符没有被这个%d转换消耗再次尝试还可能失败。如果没安排恢复逻辑就会反复卡在同一个位置。单个整数也应该用 1检查一次完整转换。我原来写的“~2是 0”是错误的。本机 GCC 环境中~2 -3 ~0 -1 ~(-1) 0~是按位取反不是“判断输入成功”。即使在常见的 EOF-1 环境~scanf(...)仍然不能识别返回 0 的匹配失败也不能保证两个数都读到了。用有界字符串输入复现不把测试程序写成死循环#includestdio.hintmain(void){constchar*cases[]{3 2,3 x,x,};for(size_ti0;isizeofcases/sizeofcases[0];i){inta0,b0;intresultsscanf(cases[i],%d %d,a,b);if(resultEOF)printf(EOF\n);elseprintf(matched:%d\n,result);}return0;}输出matched:2 matched:1 matched:0 EOF这个实验验证的是转换和返回值不是完整的交互式输入恢复器。评测题保证合法输入时遇到不完整组直接退出就够用真实交互程序还要定义怎么报告错误、清理输入并重试。scanf也不能自动解决超出整数类型范围的外部输入问题严肃文本解析可以进一步学习fgets与strtol。2. 成绩差我为什么初始化成 max0、min100原题成绩范围是 0 到 100。我的想法是先给最大值一个不大于任何合法成绩的初值最小值给一个不小于任何合法成绩的初值。max 0 min 100这个思路在题目范围内成立不需要因为代码简单就否定它。问题在于如果以后遇到负数、温度或任意整数这两个初值不能直接照搬。原程序还先保存数组再分别扫描最大值和最小值。它能做这件事但没有必要存下所有成绩。每读一个数就可以同时更新两项统计量。更通用的写法用第一个数据初始化#includestdio.hintmain(void){intn,value;if(scanf(%d,n)!1||n0)return1;if(scanf(%d,value)!1)return1;intmin_valuevalue,max_valuevalue;for(inti1;in;i){if(scanf(%d,value)!1)return1;if(valuemin_value)min_valuevalue;if(valuemax_value)max_valuevalue;}printf(%lld\n,(longlong)max_value-(longlong)min_value);return0;}这里先保证有第一个值再让最大值和最小值都等于它。原题的差值最多 100int足够为了在本机常见的 32 位 int 环境扩展测试我在减法之前转成long long。这不代表所有 C 实现的任意 int 差值都必然能装进 long long。输入5 60 80 100 0 75输出100输入1 88输出0扩展测试3 -8 -2 -5输出6。后一个不属于成绩题范围只用来说明初始化方式可复用。为什么这次能省掉数组读完前 i 个值时我维护的两个量始终分别是这 i 个值的最小值和最大值。第 i1 个值只可能扩大边界不需要回看旧数据。因此时间 O(n)额外空间 O(1)。这不是“数组不好”而是输出只依赖两个统计量。如果下一步还要排序或找中位数需求就变了。原代码里还有两个小地方int arr[10000] {-1};只有第一个元素是 -1其余是零不是全部 -1。scanf(%d , value)的尾部空白可能让交互输入继续等待后续非空白字符这里只需要%d。3. 验证比“看着对”多一步本次比较程序测试了大于、等于、小于、负数以及错误首项、错误第二项和空输入成绩程序测试了单值、重复值、0/100 边界和扩展负数并与独立排序结果对照。两题真正可带走的不是两段答案而是两个习惯一组需要几次赋值就检查几次统计初值依赖题目范围想复用就把这个前提拿掉。