std::getline() 将回车符 \r 读取到字符串中,如何避免这种情况?

Cra*_*son 8 c++ operator-overloading

我需要从 at\xd0\xb5xt 文件中读取一个(engl.: Star)对象的所有属性,如下所示Stern。我需要将字符串替换"leer""",但也可能存在不应替换为 的有效字符串""

\n\n

即对于另一个Stern对象也可以有"leer"代替"Sol"

\n\n

问题:
\n问题是它没有将 替换"leer""". 看起来它保存"leer\\\\r"在对象中而不是仅保存在对象"leer"中,但我也尝试替换"leer\\\\r",但它仍然不起作用。

\n\n

这是Stern应该阅读的文本文件中的一个:

\n\n
0\nSol\n0.000005\n0.000000\n0.000000\nleer\n1\n0\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的operator >>阅读内容:

\n\n
istream& operator>>(istream& is, Stern& obj)\n{\n    string dummy;\n    is >> obj.m_ID;\n    getline(is, dummy);\n    getline(is, obj.m_Bez);\n\n    if (obj.m_Bez == "leer")\n        obj.m_Bez = "";\n\n    is >> obj.m_xKoord >> obj.m_yKoord >> obj.m_zKoord;\n    getline(is,dummy);\n    getline(is,obj.m_Sternbild);\n\n    if (obj.m_Sternbild == "leer")\n        obj.m_Sternbild = "";\n\n    is >> obj.m_Index >> obj.m_PrimID;\n\n    return is;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

斯特恩.h:

\n\n
#ifndef STERN_H\n#define STERN_H\n#include <string>\n#include <iostream>\n\nusing namespace std;\n\nclass Stern\n{\npublic:\n    Stern();\n    // 2.a)\n    //Stern(int m_ID, string m_Bez, float m_xKoord, float m_yKoord, float m_zKoord, string m_Sternbild, int m_Index, int m_PrimID); \n    virtual ~Stern();\n\n    void print() const; // 1.b)\n    friend ostream& operator<<(ostream& os, const Stern& obj); // 1.b)i.\n    friend istream& operator>>(istream& is, Stern& obj);\n\n\nprivate:\n    int m_ID;\n    string m_Bez;\n    float m_xKoord;\n    float m_yKoord;\n    float m_zKoord;\n    string m_Sternbild;\n    int m_Index;\n    int m_PrimID;\n};\n\n#endif /* STERN_H */\n
Run Code Online (Sandbox Code Playgroud)\n

And*_*ing 2

问题在于,在 Windows 中,换行符表示为CR + LFwhich is:"\r\n"而在 Unix 中,换行符表示为LFwhich is "\n"
您的std::getline(...)命令正在读取直到"\n"in"leer\r\n"并丢弃"\n",您得到的字符串将是:

"leer\r"
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题并在 Unix/Windows 之间转换文件,有 2 个工具dos2unixunix2dos. Ubuntu 的等效项是fromdostodos,您需要fromdos将 Windows 文本文件转换为 Unix 文本文件。

要测试文件是否使用CR + LFLF可以执行以下操作:

dos2unix < myfile.txt | cmp -s - myfile.txt
Run Code Online (Sandbox Code Playgroud)

这是在Unix & Linux StackExchange 网站上发表的。


看起来它保存"leer\\r"在对象中而不是仅保存在对象"leer"中,但我也尝试替换"leer\\r",但它仍然不起作用。我仍然不明白为什么我的if (obj.m_Sternbild == "leer\\r")不起作用,因为我认为它应该起作用?

它应该是:

if (obj.m_Sternbild == "leer\r")
Run Code Online (Sandbox Code Playgroud)

无需转义反斜杠\,因为\r已读入字符串。

编辑:

正如@FreelanceConsultant在下面的评论中写道: 上面的答案不是一个通用的解决方案。因为在 Windows 或 Unix 上编译的二进制文件应该适用于这两个平台的文本文件。

有两种解决方案。

显而易见的是,与输入的两个不同版本进行比较。std::getlineWindows 的结果是,"leer\r"Unix 的结果是"leer"

if (obj.m_Sternbild == "leer\r" || obj.m_Sternbild == "leer")
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是将换行符标准化为一种形式,并仅对其进行检查。这是品味和性能的问题,因为您需要创建新的琴弦。请参阅他的回答作为示例。