繁体   English   中英

及时从 std::ifstream 读取 CSV

[英]Reading CSV from std::ifstream in good time

我正在尝试从std::ifstream读取 x、y、z 值。 以下是它目前工作方式的大致轮廓:

struct Vec3 {

    Vec3(const double x, const double y, const double z) :
        x(x), y(y), z(z)
    {}

    double x, y, z;
}

std::vector<Vec3> readFile(std::ifstream& is) {
    std::vector<Vec3> retval;
    std::string str;
    while (std::getline(is, str)) {
        std::vector<std::string> strings;
        std::stringstream ss(str);
        for (std::string entry; std::getline(ss, entry, ','); ) {
            strings.push_back(entry);
        }
        const auto x = std::stof(strings[0]);
        const auto y = std::stof(strings[1]);
        const auto z = std::stof(strings[2]);
        retval.emplace_back(x, y, z);
    }
    return retval;
}

这工作得相当好,但是所涉及的string数量(以及使用sprintf_s以达到出色效果的相应文件写入 function 的相对简单性)让我想知道是否有更快的方法来读取ifstream并构造std::vector<Vec3> . 此外,使用std::getline两次,以及每次都构造一个std::stringstream让我觉得这段代码有一些不必要的开销。 我尝试了几种方法,例如使用ifstreamoperator>> ,但这要么没有产生真正的改进,要么开始破坏 output。

我们可以做出的保证是每行的格式是带有逗号分隔符的三个数字。

这对你有用吗:

double x, y, z;
char c; // comma
while (is >> x >> c >> y >> c >> z) {
  retval.emplace_back(x, y, z);
}

我设法找到了一个比问题中发布的原始实现更好的组合,这在很大程度上受到了@0x499602D2 的回答的启发。

std::vector<Vec3> readFile(std::ifstream& is) {
    double x, y, z;
    std::vector<Vec3> retval;
    std::string str;
    while (std::getline(is, str)) {
        sscanf_s(str.c_str(), "%lg%*c%lg%*c%lg", &x, &y, &z);
        retval.emplace_back(x, y, z);
    }
    return retval;
}

消除while循环非常有帮助。 至于奇怪的 sscanf 格式, %lg防止了floatdouble之间的转换错误(我们正在读取并存储为double )并且%*c指示识别字符但不存储它,因此有效地跳过了逗号。 它看起来像代码高尔夫,但它有效(或至少看起来有效)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM