【问题标题】:C++ check end of line [closed]C ++检查行尾[关闭]
【发布时间】:2019-11-21 14:29:33
【问题描述】:

我在 C++ 中遇到了一个问题,我需要解析一个包含多行的文件(具有随机长度的随机字符串)并将大写字符转换为小写字符并将这些行存储在字符串向量中。 我正在尝试逐字符解析文件,但不知道如何识别行尾。

【问题讨论】:

  • 使用std::stringstd::getline 读取和存储文本行。
  • 只需使用std::getline 或检查'\n' 字符。
  • 这样做,相当于将文件存储在字符串向量中,而不是逐行、逐字符解析字符串向量并将大写转换为小写。我希望尽可能高效,只解析整个文件一次并在解析文件时进行转换。编辑:试图检查 '\n' 但不起作用
  • 当然,'\n' 是行尾字符。如果这对您不起作用,那么您做错了。
  • ` ifstream test("test.txt");字符; while (test >> character) { if (character == '\n') cout

标签: c++ string file end-of-line


【解决方案1】:

如果你真的想解析一个字符一个字符,那么你有很多工作。而且,你有点依赖你的环境。行可以用 '\n' 或 '\r' 或 "\r\n" 终止。

我真的建议使用一个旨在获得完整线路的函数。而这个函数是std::getline。如果您的行不包含空格,您也可以直接使用提取器运算符读取字符串,如下所示:std::string s; ifstreamVariable >> s;

为了独立于这种行为,我们可以实现一个代理类来读取完整的行并将其放入std::string

可以使用代理类和基于范围的向量构造函数将文件读入向量。

为了转换为小写,我们将使用std::transform。这很简单。

请看下面的示例代码。

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>

std::istringstream testDataFile(
R"#(Line 0 Random legth asdasdasfd
Line 1 Random legth asdasdasfd sdfgsdfgs sdfg
Line 2 Random legth asdasdasfd sdfgs sdfg
Line 3 Random legth a sddfgsdfgs sdfg
Line 4 Random legth as sds sg
)#");


class CompleteLine {    // Proxy for the input Iterator
public:
    // Overload extractor. Read a complete line
    friend std::istream& operator>>(std::istream& is, CompleteLine& cl) { std::getline(is, cl.completeLine); return is; }
    // Cast the type 'CompleteLine' to std::string
    operator std::string() const { return completeLine; }
protected:
    // Temporary to hold the read string
    std::string completeLine{};
};

int main()
{
    // Read complete source file into maze, by simply defining the variable and using the range constructor
    std::vector<std::string> strings{ std::istream_iterator<CompleteLine>(testDataFile), std::istream_iterator<CompleteLine>() };

    // Convert all strings in vector ro lowercase
    std::for_each(strings.begin(), strings.end(), [](std::string& s) { std::transform(s.begin(), s.end(), s.begin(), ::tolower); });

    // Debug output:  Copy all data to std::cout
    std::copy(strings.begin(), strings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

    return 0;
}

这是实现此类问题的“更多”-C++ 方式。

顺便说一句,您可以替换 istringstream 并从文件中读取。没有区别。

【讨论】:

  • 据我了解,您将文件中的数据存储在字符串向量中,而不是使用 transform 将大写字符转换为小写字符。这是一种避免行尾的方法,但是这种方法不是比只从文件中读取整个数据一次并在读取时进行转换效率低吗?也可以使用副本将数据读入字符串向量。描述中没有提到,但行没有空格
  • 您也可以将 std::copy 与 std::backinserter 一起使用。但这是一个声明。此方法仅将文件读取一次到向量中。于是,进入记忆。但是,是的,那么你是对的,我需要对向量中的所有字符进行额外的迭代。我们也可以在代理类中进行转换。这将保存对向量的迭代。但是我们仍然会有转换循环。我不确定是否会节省更多时间来执行基于字符的输入。 . .需要测试一下。
  • 我想我会使用你的方法,我在发布之前使用的方法是使用副本和转换循环。虽然我可以逐个字符地解析文件,但找不到一种方法来识别何时读取新行。我想让程序尽可能高效,因为它将在大量数据上进行测试。
  • 找到了一种方法,你可以用nameFile.get(nameCharacter)逐个字符地读取文件,get() 将读取行尾,这样你就可以知道一行何时结束。
【解决方案2】:

ifSteamObject.eof( ) 用于检查文件结尾

if(!obj.eof())
{
   //your code
}

使用它可以解决您的问题

【讨论】:

  • 我的错误,我写在文件的标题末尾,但在我解释的问题和描述中我需要行尾。
  • 它用于检查尝试的输入操作是否失败,因为它到达了文件的末尾。在操作失败之前,它将返回 false。所以它不是文件结尾的通用测试。它通常是无关紧要的。程序通常会读取输入,直到失败,然后才完成。
猜你喜欢
  • 1970-01-01
  • 2012-08-26
  • 1970-01-01
  • 2016-08-24
  • 1970-01-01
  • 1970-01-01
  • 2018-02-16
  • 2010-11-13
  • 2010-10-26
相关资源
最近更新 更多