【问题标题】:C++ Read in file element by element, but executing functions every lineC ++逐个元素读入文件,但每行执行函数
【发布时间】:2018-01-03 16:56:21
【问题描述】:

我有一个需要读入的文件。文件的每一行都非常长,所以我宁愿不要将每一行读入一个临时字符串然后操作这些字符串(除非这实际上不是低效的 -我可能是错的)。文件的每一行都包含一串三元组 - 两个数字和一个复数,用冒号分隔(与复数中使用的逗号相反)。我当前的代码是这样的:

 while (states.eof() == 0)
  {
  std::istringstream complexString;

  getline(states, tmp_str, ':');
  tmp_triplet.row() = stoi(tmp_str);
  getline(states, tmp_str, ':');
  tmp_triplet.col() = stoi(tmp_str);
  getline(states, tmp_str, ':');
  complexString.str (tmp_str);
  complexString >> tmp_triplet.value();
  // Then something useful done with the triplet before moving onto the next one
  }

tmp_triplet 是存储这三个数字的变量。我想要某种方法来每行运行一个函数(具体来说,每行中的三元组被推入一个向量,文件中的每一行表示一个不同的向量)。我确信有一个简单的方法可以解决这个问题,但我只是想要一种方法来检查是否已到达行尾,并在这种情况下运行一个函数。

【问题讨论】:

  • Read file line by line的可能重复
  • 您不必阅读整行。你可以读取一个块,比如 4kb 然后解析它,即搜索:。完成该块后,您保留该块的其余部分并将下一个附加到剩余部分的末尾。如果遇到 EOL,则对向量进行处理。此外,读取整行是否效率低下实际上取决于您拥有多少 RAM 以及行有多长。如果每行最多说 10Mb,那么我就不会为分块算法而烦恼,我会立即阅读整个内容。那么这些线有多大?
  • @freakish,每行大约 1Mb。所以听起来把整个东西读成一个字符串就可以了?
  • @wayward_vagabound 好吧,我假设我们正在谈论可用的 Gbs RAM?如果是这样的话,是的,没关系。 1Mb 对现代计算机来说毫无意义。
  • 还有一个更一般的建议:首先要确保正确性。然后简单。最后是性能。过早的优化是万恶之源。

标签: c++ getline


【解决方案1】:

当你试图计划一些事情时,抽象可以成为你最好的朋友。如果你通过抽象功能来分解你想做的事情,你可以更容易地决定应该使用哪些数据类型以及应该如何规划不同的数据类型,并且通常你会发现一些函数几乎是自己编写的。通常,您的代码将更加模块化(几乎按照定义),这将使其易于重用、维护和适应未来需要的更改。

例如,听起来您想解析一个文件。所以这应该是一个功能。

要执行该功能,您需要读取文件行,然后处理文件行。因此,您可以创建两个函数,每个函数一个,然后调用这些函数。

读入文件行,您只想获取一个文件流,并为每一行返回一个字符串集合。

处理文件行,您需要获取一组字符串并为每个字符串将字符串解析为三元组值。因此,您可以创建一个方法,将字符串分解为三元组,然后在此处使用该方法。

处理一个字符串,你只需要获取一个字符串并将第一部分作为行,第二部分作为列,第三部分作为值。

struct TripletValue
{
    int Row;
    int Col;
    int Val;
};

std::vector<TripletValue> ParseFile(std::istream& inputStream)
{
    std::vector<std::string> fileLines = ReadFileLines(inputStream);
    std::vector<TripletValue> parsedValues = GetValuesFromData(fileLines);
    return parsedValues;
}

std::vector<std::string> ReadFileLines(std::istream& inputStream)
{
    std::vector<std::string> fileLines;
    while (!inputStream.eof())
    {
        std::string fileLine;
        getline(inputStream, fileLine);
        fileLines.push_back(fileLine);
    }
    return fileLines;
}

std::vector<TripletValue> GetValuesFromData(std::vector<std::string> data)
{
    std::vector<TripletValue> values;

    for (int i = 0; i < data.size(); i++)
    {
        TripletValue parsedValue = ParseLine(data[i]);
        values.push_back(parsedValue);
    }

    return values;
}

TripletValue ParseLine(std::string fileLine)
{
    std::stringstream sstream;
    sstream << fileLine;

    TripletValue parsedValue;

    std::string strValue;
    sstream >> strValue;
    parsedValue.Row = stoi(strValue);

    sstream >> strValue;
    parsedValue.Col = stoi(strValue);

    sstream >> strValue;
    parsedValue.Val = stoi(strValue);

    return parsedValue;
}

【讨论】:

  • std::streams 应该通过引用传递,否则您正在调用已删除的函数。
  • 我只是想展示使用抽象将更大的问题分解成更小的部分的高级思维过程,以及如何帮助拼凑如何实现小细节。
猜你喜欢
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-19
  • 2017-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多