如何从 CSV 文件中的特定列中读取值以执行计算 - C++

How to read in values from specific columns in a CSV file to perform calculations - C++

所以我试图将 csv 文件中的一些数据读入我的程序,但我只想要一些特定的列。我知道网上有很多关于此的资料,但我似乎无法满足我的要求。

首先,我创建了一个包含日期和时间(class 对象)和文件中的速度值的结构,并将其存储在我自己制作的 Vector 模板 class 中。我的主程序现在可以正确处理这样的测试文件:

31/12/2013 11:45,55.6

日期和时间一起读,然后分开,没问题。现在这是实际的文件:

WAST,DP,Dta,Dts,EV,QFE,QFF,QNH,RF,RH,S,SR,ST1,ST2,ST3,ST4,Sx,T
31/03/2016 09:00,14.6,175,17,0,1013.4,1016.9,1017,0,68.2,6,512,22.7,24.1,25.5,26.1,8,20.74
31/03/2016 09:10,14.6,194,22,0.1,1013.4,1016.9,1017,0,67.2,5,565,22.7,24.1,25.5,26.1,8,20.97
31/03/2016 09:20,14.8,198,30,0.1,1013.4,1016.9,1017,0,68.2,5,574,22.7,24,25.5,26.1,8,20.92

我想做的是从 WAST 列中提取详细信息,即日期和时间,然后从 S 列中提取速度。我对如何做到这一点有一个通用的想法,即:将整个第一行提取到一个字符串中,并忽略除 WAST 和 S 或类似内容之外的所有内容。但即便如此,我应该如何只在我想要的列下获得每个值?请帮忙。

Main.cpp:

#include <iostream>
#include <string>
#include <fstream>
#include "Date.h"
#include "Time.h"
#include "Vector.h"

using namespace std;

typedef struct {

        Date d;
        Time t;
        float speed;

}WindLogType;

int main()
{

Date dTest;
Time tTest;
float speedtest = 52.5;

Vector<WindLogType> windlog;


ifstream infile("testinput2.csv");

if(!infile){

    cout << "File not found.";

    return -1;

};

WindLogType windlog2;

//int i = 0;

while(!infile.eof()){

    infile >> windlog2.d >> windlog2.t >> windlog2.speed;


    windlog.add(windlog2);

}

for(int i = 0; i < windlog.size(); i++){

    cout << windlog[i].d << " " << windlog[i].t << " Speed: " << windlog[i].speed << endl;

}


infile.close();

return 0;

}

您在这里可以做的是为您的结构 WindLogType 编写一个流提取运算符,用于一次一行地读取文件,从该行中提取您需要的信息并填充结构。

std::getline 不仅可以用来读取整行,还可以使用定界符标记字符串。

您可以尝试使用一些评论来解释以下内容:

#include <fstream>
#include <string>
#include <sstream>

using Date = std::string;
using Time = std::string;

typedef struct {
    Date d;
    Time t;
    float speed;
} WindLogType;

std::istream& operator >> (std::istream& is, WindLogType& sl) {

    // Read a complete line
    std::string line;
    if (std::getline(is, line)) {

        auto iss = std::istringstream{line};

        // Read date from line (up to space)
        std::getline(iss, sl.d, ' ');
        // Read time (up to ',')
        std::getline(iss, sl.t, ',');

        std::string speed;
        // Read speed (up to next comma)
        std::getline(iss, speed, ',');
        sl.speed = std::stof(speed);
    }

    return is;
}

int main()
{
    std::ifstream infile("testinput2.csv");

    if (!infile) {
        std::cout << "File not found.";
        return -1;
    };

    Vector<WindLogType> windlog;
    std::string str;
    std::getline(infile, str); // skip the first line

    WindLogType windlog2;
    while (infile >> windlog2) {
        windlog.add(windlog2);
    }

    return 0;
}

流提取运算符 (>>) 从文件中读取一行。使用该行,它从中创建一个 std::istringstream 对象,然后使用 std::getline.

提取相关信息

我不知道你的 DateTime 类型是如何定义的。我刚刚将它们别名为 std::string。您必须自己对字符串进行处理。

希望这有用。


编辑:

你不能while(infile >> windlog2.d >> windlog2.t >> windlog2.speed)的原因是>>读到白色space/newline。您的数据有点复杂:它是逗号分隔的,并且您已经解析了日期和时间字段。上述方法的好处是它允许您将数据直接流式传输到 WindLog 结构中。

如果您真的不想为您的类型使用流提取运算符,您可以使用相同的代码。它将是这样的:

std::string line;
std::getline(infile, line); // skip the first line

while (std::getline(infile, line)) {
    WindLogType sl;
    auto iss = std::istringstream{ line };

    // Read date from line (up to space)
    std::getline(iss, sl.d, ' ');
    ...
}

我个人更喜欢为一种类型使用流提取运算符,因为它将所有读取操作封装在一个函数中,但如果您想进行一些其他处理,则可以采用第二种方法。