Getline转换为字符串时会复制换行符

3

我正在逐行读取文件,并将每行添加到一个字符串中。但是,我发现每行的字符串长度增加了1,我认为这是由于换行符造成的。如何避免将其复制到字符串中。

以下是我尝试实现相同功能的代码。

if (inputFile.is_open())
{
    {
        string currentLine;
        while (!inputFile.eof())
            while( getline( inputFile, currentLine ) )
            {
                string s1=currentLine;
                cout<<s1.length();
            }

[更新的描述] 我使用notepad++逐行确定我所选择的长度。所以他们显示一些123、450、500、120,我的程序显示为124、451、501、120。除了最后一行外,所有的line.length()都显示增加了1个值。


6
欢迎来到StackOverflow。我已经为您格式化了代码。第一次是免费的。之后你就得请我喝一杯啤酒了;-) - johnsyweb
std::getline()会丢弃换行符。你如何确定预期的行长度? - hmjd
使用cout<<s1.length(); - typedef1
这是由 std::getline() 读取的行长度,与您预期的不同。 - hmjd
1
也许这是不同平台上换行符的问题?文件来自哪里?您的程序是在哪个平台上编写的? - Christian Ammer
2个回答

7
看起来inputFile使用了Windows风格的换行符(CRLF),但是由于std::getline()默认按照Unix风格(LF)分割输入,导致字符串末尾存在CR (\r)。您需要删除多余的\r。以下是一种方法以及一个小测试:
#include <iostream>
#include <sstream>
#include <iomanip>

void remove_carriage_return(std::string& line)
{
    if (*line.rbegin() == '\r')
    {
        line.erase(line.length() - 1);
    }
}

void find_line_lengths(std::istream& inputFile, std::ostream& output)
{
    std::string currentLine;
    while (std::getline(inputFile, currentLine))
    {
        remove_carriage_return(currentLine);
        output
            << "The current line is "
            << currentLine.length()
            << " characters long and ends with '0x"
            << std::setw(2) << std::setfill('0') << std::hex
            << static_cast<int>(*currentLine.rbegin())
            << "'"
            << std::endl;
    }
}

int main()
{
    std::istringstream test_data(
        "\n"
        "1\n"
        "12\n"
        "123\n"
        "\r\n"
        "1\r\n"
        "12\r\n"
        "123\r\n"
        );

    find_line_lengths(test_data, std::cout);
}

输出:

The current line is 0 characters long and ends with '0x00'
The current line is 1 characters long and ends with '0x31'
The current line is 2 characters long and ends with '0x32'
The current line is 3 characters long and ends with '0x33'
The current line is 0 characters long and ends with '0x00'
The current line is 1 characters long and ends with '0x31'
The current line is 2 characters long and ends with '0x32'
The current line is 3 characters long and ends with '0x33'

需要注意的事项:

  • 您不需要测试EOF。 std::getline()将返回流,当它无法从inputFile中读取更多内容时,将转换为false
  • 您不需要复制字符串来确定其长度。

我使用npp++逐行确定所选内容的长度。因此,它们显示了一些123、450、500、120,而我的程序显示为124、451、501、120。除了最后一行外,所有line.length()都显示增加了1个值。 - typedef1
你能否使用行长度可以手动计数的小测试文件运行程序?对于零长度的行,它会报告什么?(我的报告为0) - johnsyweb

1

这是因为你在使用 MS-Windows,它们会在 "\n" 前添加一个 "\r",而这个 "\r" 没有被移除。


1
这是不正确的,\r也会被删除(https://dev59.com/e2025IYBdhLWcg3wT0Hq#6089413),但如果文件在Windows下存储并在Linux下读取,则会出现问题。 - Christian Ammer
@ChristianAmmer 我敢打赌这就是问题所在!当在Windows机器上以文本模式读取文件时,行尾序列会被替换为\n并被剥离,但每行末尾的这个看不见的字符很容易搞乱读取。要验证这一点非常简单:if (!s.empty() && s.back() == '\r') { std::cout << "gotcha!\n"; } - Dietmar Kühl
@Dietmar:也许对你来说不是问题,但对我来说是个问题(客户端=Windows,服务器=Linux),而且在OP的情况下,这似乎真的是原因。 - Christian Ammer
@Christian 实际上,如果您以二进制模式打开文件(这在这里可能不是情况...),则 \r\n 也不会在 MS-Windows 下转换。无论 getline() 是否足够聪明去处理这项工作,我并不确定。 - Alexis Wilke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接