在算法比赛中高效处理多行输入
在算法比赛中高效处理多行输入:while(scanf) 循环的实用技巧
大家好,我是算法爱好者。今天想和大家聊聊在ACM/ICPC、LeetCode 或其他算法比赛中,一个超级实用的输入技巧:使用 while(scanf("%f", &n) != EOF)
这样的循环来处理输入数据。特别是在题目要求读取多行或不定数量输入时,这种方法能让你省时省力,避免了繁琐的循环计数和边界判断。
如果你是新手,可能会用 for
循环或固定次数的 scanf
,但在比赛中,输入数据往往是“直到文件结束”(EOF)才停止的。这种情况下,while(scanf)
就是你的救星。下面我用一个简单例子来演示如何应用它,并分享一些心得。
为什么需要这种输入方式?
在算法比赛中,许多题目(如OJ系统的测试用例)会提供多组数据,每组可能有不定数量的行。传统方法如:
for(int i = 0; i < 100; i++) { // 假设最多100行scanf("%f", &n);// 处理
}
容易出错:如果实际行数少于100,会读到垃圾数据;如果多于100,又会遗漏。
而 while(scanf("%f", &n) != EOF)
的逻辑是:不断尝试读取,直到遇到EOF(文件结束)才停止。scanf
返回读取成功的项目数,如果失败(如EOF),返回 EOF(通常是 -1)。这完美适应了比赛的输入格式!
示例代码:读取浮点数并输出三位小数
假设题目要求:从标准输入读取多个浮点数,每行一个,直到输入结束。然后将每个数输出为三位小数格式。
以下是完整的C代码实现:
#include <stdio.h>int main() {float n = 0.0f; // 初始化浮点变量while (scanf("%f", &n) != EOF) { // 循环读取直到EOFprintf("%.3f\n", n); // 输出三位小数}return 0;
}
输入样例(多行浮点数):
1.23456
-0.789
3.1415926
42.0
输出结果:
1.235
-0.789
3.142
42.000
代码详解
- 头文件:只需
#include <stdio.h>
,因为我们用scanf
和printf
处理I/O。 - 变量声明:
float n = 0.0f;
– 用f
后缀确保是单精度浮点,避免编译警告。 - while 循环:
scanf("%f", &n)
:尝试读取一个浮点数到n
中。- 如果成功,返回 1(读取了一个项目);如果遇到 EOF,返回 EOF(-1),循环结束。
- 这确保了只处理有效输入,不会多读或少读。
- 输出:
printf("%.3f\n", n);
– 四舍五入到三位小数,并换行。注意\n
比\r\n
更通用,在OJ中不易出错。
编译运行:用 gcc main.c -o main
编译,然后重定向输入文件测试(如 ./main < input.txt
)。
在算法比赛中的优点
- 高效快速:
scanf
是C语言中最快的输入函数之一,比cin
(C++)快几倍。在时间紧迫的比赛中,这能帮你节省宝贵毫秒。 - 简洁无脑:不用担心行数不确定的问题,一行代码搞定循环。
- 通用性强:不止浮点数,换成
%d
读整数、%s
读字符串都行。甚至多变量:scanf("%d %d", &a, &b)
。 - 兼容多测试用例:许多题目第一行是 T(测试次数),但如果题目说“多组直到EOF”,直接用这个循环。
举个扩展例子:如果题目有 T 组,每组一个整数 N 和 N 个浮点数:
#include <stdio.h>int main() {int T;scanf("%d", &T); // 先读测试次数for(int t = 0; t < T; t++) {int N;scanf("%d", &N);for(int i = 0; i < N; i++) {float x;scanf("%f", &x);printf("%.3f\n", x);}}return 0;
}
但如果题目是“无 T,直接多组直到EOF”,就改成嵌套的 while:
while(scanf("%d", &N) != EOF) {for(int i = 0; i < N; i++) {float x;scanf("%f", &x);// 处理}
}
注意事项与常见坑
- EOF 判断:在本地测试时,用 Ctrl+D (Linux/Mac) 或 Ctrl+Z (Windows) 模拟EOF。
- 输入格式:确保格式字符串匹配(如
%f
只读浮点,别读整数时用%d
)。 - 溢出与精度:浮点用
double
更安全(改%lf
和&d
),尤其大数题目。 - C++ 兼容:如果你用C++,可以
#include <cstdio>
并用std::scanf
,但推荐纯C风格以求速度。 - 调试技巧:加
fflush(stdin);
清缓冲(但比赛中少用),或用getchar()
吃换行符如果有混合输入。
结语
掌握 while(scanf != EOF)
是算法比赛输入处理的入门神技。它让你的代码更robust(健壮),让你有更多时间思考算法核心。建议多练几道POJ或HDU的简单I/O题,很快就能上手!
如果你有类似输入难题,欢迎评论区讨论。下一个博客,我们聊聊快速排序的优化~ 点赞收藏不迷路哦!