Как читать значения из указанных c столбцов в файле CSV для выполнения расчетов - C ++ - PullRequest
0 голосов
/ 02 мая 2020

, поэтому я пытаюсь прочитать некоторые данные из CSV-файла в свою программу, но мне нужны только определенные столбцы c. Я знаю, что в Интернете есть много вещей, касающихся этого, но я не могу соответствовать ни одному из них моим требованиям.

Во-первых, я создал структуру, которая принимает Date и Time (объекты класса) и значение Speed ​​из файла и сохранить его в шаблонном классе Vector, который я сделал сам. Моя основная программа сейчас работает правильно для тестового файла, как это:

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. У меня есть общее представление о том, как это сделать, то есть: 1. Извлечь всю первую строку в строку и игнорировать все, кроме 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;

}

1 Ответ

1 голос
/ 02 мая 2020

Здесь вы можете написать оператор извлечения потока для вашей структуры 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.

Я не знаю, как ваши Date и Time типы определены. Я просто назвал их как std::string. Вам придется самостоятельно обрабатывать строки.

Надеюсь, это полезно.


Редактировать:

Причина, почему вы не можете сделать while(infile >> windlog2.d >> windlog2.t >> windlog2.speed), так как >> читает до пробела / новой строки. Ваши данные немного сложны: они разделены запятыми, и вы проанализировали поля даты и времени. Преимущество подхода, описанного выше, заключается в том, что он позволяет вам передавать данные непосредственно в структуру 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, ' ');
    ...
}

Лично я предпочитаю иметь оператор извлечения потока для типа, поскольку он инкапсулирует все операции чтения в одной функции, но если вы хотите выполнить какую-то другую обработку, вы можете взять Второй подход.

...