具体来说,我对 istream& getline ( istream& is, string& str );
感兴趣。 ifstream 构造函数是否有一个选项可以告诉它将所有换行符编码转换为 ‘\n’ 在引擎盖下?我希望能够调用 getline
并让它优雅地处理所有行尾。
更新:为了澄清,我希望能够编写几乎可以在任何地方编译的代码,并且几乎可以从任何地方获取输入。包括带有 ‘\r’ 而没有 ‘\n’ 的罕见文件。最大限度地减少对软件的任何用户的不便。
解决这个问题很容易,但我仍然对在标准中灵活处理所有文本文件格式的正确方法感到好奇。
getline
将整行读取到一个字符串中,直到 ‘\n’。 ‘\n’ 从流中消耗,但 getline 不将其包含在字符串中。到目前为止这很好,但是在字符串中包含的 ‘\n’ 之前可能有一个 ‘\r’。
在文本文件中可以看到 三种类型的行尾:’\n’ 是 Unix 机器上的常规结尾,’\r’(我认为)用于旧的 Mac 操作系统,Windows 使用一对,’\r’后跟’\n’。
问题是 getline
将 ‘\r’ 留在了字符串的末尾。
ifstream f("a_text_file_of_unknown_origin");
string line;
getline(f, line);
if(!f.fail()) { // a non-empty line was read
// BUT, there might be an '\r' at the end now.
}
编辑 感谢 Neil 指出 f.good()
不是我想要的。 !f.fail()
是我想要的。
我可以自己手动删除它(请参阅此问题的编辑),这对于 Windows 文本文件很容易。但我担心有人会输入一个只包含’\r’的文件。在那种情况下,我认为 getline 会消耗整个文件,认为它是一行!
..这甚至没有考虑Unicode :-)
..也许Boost有一种很好的方法来一次从任何文本文件类型中消耗一行?
编辑 我正在使用它来处理 Windows 文件,但我仍然觉得我不应该这样做!这不会分叉 ‘\r’-only 文件。
if(!line.empty() && *line.rbegin() == '\r') {
line.erase( line.length()-1, 1);
}
原文由 Aaron McDaid 发布,翻译遵循 CC BY-SA 4.0 许可协议
正如 Neil 指出的那样,“C++ 运行时应该正确处理适用于您的特定平台的任何行尾约定。”
但是,人们确实在不同平台之间移动文本文件,所以这还不够好。这是一个处理所有三个行尾(“\r”、“\n”和“\r\n”)的函数:
这是一个测试程序: