如何在Kattis编程题中正确使用PHP的feof()函数?
Kattis PHP 处理EOF导致运行时错误的解决方案
问题概述
在Kattis平台解决「different」题目时,本地(含Kattis推荐的shell方式)运行代码完全正常,但提交后始终出现运行时错误。已确认问题出在EOF(文件结束符)的处理逻辑上,尝试过while(feof(STDIN) === False)和while(!feof(STDIN))两种写法均无效,此前10+道无需EOF判断的题目提交均正常,联系Kattis支持未获有效帮助。
现有代码
<?php $Results = []; while(feof(STDIN) === False) { $input = trim(fgets(STDIN)); $data = explode(" ", $input); $data[0] = intval($data[0]); $data[1] = intval($data[1]); if(($data[0] - $data[1]) >= 0) { array_push($Results, ($data[0] - $data[1])); } else { array_push($Results, ($data[1] - $data[0])); } } for($i = 0; $i < count($Results); $i++) { fprintf(STDOUT, "%s", $Results[$i].PHP_EOL); } ?>
已查阅的Kattis官方说明(翻译)
- 关于运行时错误的定义:
运行时错误意味着代码在执行过程中崩溃,可能原因包括内存不足、栈溢出、除零错误、数组越界,或抛出未捕获的异常。
- Kattis PHP语言支持说明:
Kattis支持PHP 7.4版本,代码需从标准输入(STDIN)读取数据,向标准输出(STDOUT)写入结果。PHP程序无需main函数,以常规脚本方式执行。需特别注意输入输出的处理逻辑,尤其是EOF判断,避免读取错误。
错误原因
原代码的核心问题在于feof的判断时机错误:feof函数只有在尝试读取超过EOF时才会返回true。当最后一行输入读取完成后,feof仍返回false,循环会继续执行一次,此时fgets(STDIN)返回false,trim(false)得到空字符串,explode(" ", "")生成仅含空元素的数组,后续访问$data[1]会触发数组未定义索引的错误,这正是导致Kattis运行时错误的直接原因。
正确的EOF处理写法
写法1:直接判断fgets返回值(推荐)
通过判断fgets的返回值是否为false来终止循环,避免多读一次的问题:
<?php while (($input = fgets(STDIN)) !== false) { $input = trim($input); // 跳过空行(若测试用例包含空行) if (empty($input)) { continue; } list($a, $b) = explode(" ", $input); echo abs(intval($a) - intval($b)) . PHP_EOL; } ?>
- 优势:逐行读取,内存占用低,适配任意大小的输入;直接输出结果,无需存储所有结果再循环打印,逻辑更简洁。
写法2:一次性读取全部输入
适合输入数据量不大的场景,一次性读取所有输入后按行处理:
<?php // 读取全部标准输入 $allInput = file_get_contents('php://stdin'); // 按行分割并去除首尾空行 $lines = explode(PHP_EOL, trim($allInput)); foreach ($lines as $line) { if (empty($line)) { continue; } list($a, $b) = explode(" ", $line); echo abs(intval($a) - intval($b)) . PHP_EOL; } ?>
内容的提问来源于stack exchange,提问作者The_Moth
相关产品推荐
相关产品推荐

