1.错误源头
通过不断搜索最终解决上一篇文章发布的问题,发现原因就在洛谷的官方通知里。图片如下:
特别地,在 Windows 或其他非 Unix 系统下造数据后,把文件传输到 Linux 下后,可能出现换行 符编码不正确的情况。具体地:
- 造数据的时候请注意换行符使用 Unix 格式(即
\n
)而不是 Windows 格式(即\r\n
),如果是在 Windows 系统下造的数据就有可能出现这个问题,如果使用的是 Windows 系统,可以使用系统自带的记事本(Notepad)打开文件然后看一下右下角显示的是 CRLF 还是 LF,如果是后者就没问题(当然,旧版 Mac 格式(即\r
)也是不行的)。
在 Windows 下造数据时避免造出\r\n
格式换行符的方法可以查看附录。 - 洛谷评测机是 Linux 环境,在一些特定题目中,特别是字符串题,如果换行符格式不正确,而用户使用了
getline
(C++ 中)等函数进行读入,就会出现输入错误的情况。这些情况在历次月赛中造成了一定的影响,所以还是需要注意一下。 -
2.总结:
- 在 Linux 环境中,字符串处理相关的题目常常要求保证输入格式的正确性。尤其是在使用
getline
读取字符串的时候,如果输入的换行符格式不符合期望,会导致输入读取异常,以及相应的输出错误。下面通过一个简单的示例来解释这个问题,并提供解决方案。 -
3.示例问题
-
假设我们有一个要求是读取一行输入,然后对其进行处理,比如计算字符串的长度并输出。但是如果输入的行中包含了额外的回车符 (
\r
),则可能会导致程序处理不正确。例如,下面的代码假设我们在一个 Linux 系统中运行:#include <iostream> #include <string> using namespace std; int main() { string s; cout << "请输入一行文本: "; getline(cin, s); // 读取一整行字符串 cout << "字符串的长度是: " << s.length() << endl; // 输出字符串的长度 return 0; }
潜在输入问题
- 如果用户在 Windows 中创建了一个文本文件并在Linux系统中读取这个文件,有可能会在行末出现
\r\n
(即 CRLF),此时通过getline
读取会使字符串末尾包含一个额外的回车符\r
。 - 例如,如果输入为 “Hello World\r”,在读取后,字符串的长度计算将会错误,因为实际长度计算为 13(包含了
\r
),而不是 11(“Hello World” 的实际长度)。 -
4.解决办法
-
1.清洗输入数据:使用
erase
和remove
来排除字符串中的\r
字符 -
#include <iostream> #include <string> #include <algorithm> // std::remove using namespace std; int main() { string s; cout << "请输入一行文本: "; getline(cin, s); // 移除所有 '\r' 字符 s.erase(remove(s.begin(), s.end(), '\r'), s.end()); cout << "字符串的长度是: " << s.length() << endl; return 0; }
2.相应的对于B2122 单词翻转问题,只需要加上s.erase(remove(s.begin(), s.end(), '\r'), s.end());这行代码测试就满分通过了。
-
3.要是有人还有什么疑问可以留言