在本场 T3,徐老师的口供笔录 中,存在以下数据问题:

注意到,在 Windows 操作系统中,换行符通常为 \r\n,而在类 Linux 操作系统中,换行符通常为 \n

徐老师在造数据时,可能是在 Windows 环境中生成数据后,直接对文本文件进行了某些编辑操作(如使用 Windows 的文本编辑器保存),而没有使用类似于 dos2unix 等操作将数据重新恢复为 \n 的模式,导致本题换行符为 \r\n

本题中由于存在读整行的要求,如果你使用了类似 getchar() 函数来从标准输入中读取和处理换行符(为了避免在接下来使用 std::getline() 时由于第一行后的换行字符而读到一个空串而非预期的整行字符串),那么有可能导致输入时实际和预想的效果存在错位。此外还有可能潜在的问题如,在使用 std::getline() 时,由于字符串的末尾比想象中多一个 \rstd::string::size() 返回的大小可能会比预期大 11 ,等等。

关于 \r 字符,这可能是一个打字机时代的历史遗留问题,在早期,换行符和回车符被当做两个不同的字符,回车(CR, carriage return)的效果是将光标移动到本行的第一个字符,换行(LF, line feed)的效果是将光标移动到下一行,两个字符合用的效果才会是将光标移动到下一行的第一个字符。在 Windows 操作系统中,\r 对应回车,\n 对应换行。

一般来说,出现这种问题应该被归咎于出题人的失误。由于 Judge 的评测环境往往在类 Linux 操作系统,这类现象极易导致单字符读取出现问题。而且 Online Judge 的在线 IDE 往往不能发现这种情况(在线 IDE 的输入窗口可能由于浏览器或前端的某些操作默认将 \r\n 规范化为 \n)。在 Windows 操作系统运行时(无论编译器是 MSVC 还是 MinGW),stdin 默认以文本模式打开,底层会默认将 \r\n 转化为 \n,因此你可能难以在本地复现出该问题,\rgetchar() 等操作不可见。如果显式地在代码中将 stdin 切换到二进制模式,则可以复现出此问题。在类 Linux 操作系统的 C/C++ 编译器中,没有文本模式和二进制模式的区分(或者说所有流都等价于 Windows 的二进制模式)。

1 条评论

  • 1