2016-04-20 15 views
0

私のプロジェクトの1つを稼働させようと一生懸命やっている。私は気象データベースから10,000行のCSVファイルを読み込み、いくつかのデモで特定のフィールドを出力する必要があります。CSVからテンプレートベクターを読み込む

私はこれを独自のテンプレートベクターを使用して設計する予定であり、STLライブラリへのアクセスは許可されていません。 私はちょうど学んでいるし、これは作って数週間されている私は自分自身のためにそれを複雑にしていると思うと今私は進歩する方法を知らないつもりだ。 ここでの主な問題は、私が構造体を読み込んで情報を解析して、必要なものだけを読み込むだけでなく、そのデータをテンプレートベクトルに変換する方法を混乱させることです。

はとにかく、前置きなしに、ここで私のソースコード:

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

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

int main() 
{ 
    Vector<WindLogType> windlog; 
    std::string temp; 
    std::ifstream inputFile("MetData-31-3.csv"); 
    int timeIndex, windSpeedIndex; 

    //18 Elements per line 
    //Need the elements at index 0 & 10 
    while(!inputFile.eof()) 
    { 
     getline(inputFile, WindLogType.d,' '); 
     getline(inputFile, WindLogType.t,','); 
     for(int i = 0; i < 9; i++) 
     { 
      getline(inputFile, temp, ','); 
     } 
     getline(inputFile, WindLogType.speed); 
     windlog.push_back(WindLogType); 
    } 

    return 0; 
} 

Vector.h完全に不要なベクトルクラスのいくつかのものがありますが、彼らはちょうどからのものであった

#ifndef VECTOR_H 
#define VECTOR_H 

template <class elemType> 
class Vector 
{ 
public: 
    bool isEmpty() const; 
    bool isFull() const; 
    int getLength() const; 
    int getMaxSize() const; 
    void sort(); 


// T* WindLogType; 
    Vector(int nMaxSize = 64); //Default constructor, array size of 64. 
    Vector(const Vector&);  //Copy constructor 
    ~Vector();     //Destructor 
    void push_back(int); 
    int operator[](int); 
    int at(int i); 

private: 
    int maxSize, length; 
    elemType* anArray; 
    void alloc_new(); 
}; 

template <class elemType> 
bool Vector<elemType>::isEmpty() const 
{ 
    return (length == 0); 
} 

template <class elemType> 
bool Vector<elemType>::isFull() const 
{ 
    return (length == maxSize); 
} 

template <class elemType> 
int Vector<elemType>::getLength() const 
{ 
    return length; 
} 

template <class elemType> 
int Vector<elemType>::getMaxSize() const 
{ 
    return maxSize; 
} 

//Constructor that takes the max size of vector 
template <class elemType> 
Vector<elemType>::Vector(int nMaxSize) 
{ 
    maxSize = nMaxSize; 
    length = 0; 
    anArray = new elemType[maxSize]; 
} 

//Destructor 
template <class elemType> 
Vector<elemType>::~Vector() 
{ 
    delete[] anArray; 
} 

//Sort function 
template <class elemType> 
void Vector<elemType>::sort() 
{ 
    int i, j; 
    int min; 
    elemType temp; 

    for(i = 0; i < length; i++) 
    { 
     min = i; 
     for(j = i+1; j<length; ++j) 
     { 
      if(anArray[j] < anArray[min]) 
       min = j; 
     } 
     temp = anArray[i]; 
     anArray[i] = anArray[min]; 
     anArray[min] = temp; 
    } 
} 

//Check if vector is full, if not add the item to the vector 
template <class elemType> 
void Vector<elemType>::push_back(int i) 
{ 
    if(length+1 > maxSize) 
     alloc_new(); 
    anArray[length]=i; 
    length++; 
} 

template <class elemType> 
int Vector<elemType>::operator[](int i) 
{ 
    return anArray[i]; 
} 

//Return the vector at position 'i' 
template <class elemType> 
int Vector<elemType>::at(int i) 
{ 
    if(i < length) 
     return anArray[i]; 
    throw 10; 
} 

//If the vector is about to get full, create a new temporary 
//vector of double size and copy the contents across. 
template <class elemType> 
void Vector<elemType>::alloc_new() 
{ 
    maxSize = length*2; 
    int* tmp=new int[maxSize]; 
    for(int i = 0; i < length; i++) 
     tmp[i]= anArray[i]; 
    delete[] anArray; 
    anArray = tmp; 
} 



/** 
//Copy Constructor, takes a reference to a vector and copies 
//the values across to a new vector. 
Vector::Vector(const Vector& v) 
{ 
    maxSize= v.maxSize; 
    length = v.length; 
    anArray = new int[maxSize]; 
    for(int i=0; i<v.length; i++) 
    { 
     anArray[i] = v.anArray[i]; 
    } 
}**/ 
#endif 

少しの練習。ここで

は、CSVファイルのサンプルです:

WAST,DP,Dta,Dts,EV,QFE,QFF,QNH,RF,RH,S,SR,ST1,ST2,ST3,ST4,Sx,T 
31/03/2016 9: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 9: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 9: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 
31/03/2016 9:30,15.1,215,27,0,1013.4,1016.8,1017,0,66.6,5,623,22.6,24,25.5,26.1,8,21.63 

WASTは日付が含まれており、Sは、風速が含まれているとして、私は、WAST列とSの列の要素が必要です。

私は人々に私にちょうど解決策を与えて欲しいと思いませんか。構造体&テンプレートベクトルを使ってこのデータを読み込んで解析する方法を理解する必要があります。 本物の「エラー」自体はありません。私は次のどこへ行くのかについて基本的な理解が欠けています。

ご協力いただければ幸いです! ありがとう

答えて

1

簡単で効率的な方法の1つは、列単位のベクトル、つまり列指向の記憶域を持つことです。列指向の記憶域はスペース要件を最小限に抑え、(行指向のストレージの場合のように)個々の構造体メンバーを選択する必要はなく、線形代数アルゴリズム(SIMD最適化を含む)を簡単に適用できます。

fscanfを使用して各行を解析し、各値を別々の変数に解析できます。そして、対応する列に変数push_backを入力します。

fscanfは、日付を解析しませんので、あなたはchar[64]に日付文字列を抽出して、その後time_tに変換することができstruct tmにそのを解析する必要があります。

上記は、CSVのレイアウトと列の種類を知っていることを前提としています。

擬似コード:

vector<time_t> timestamps; 
vector<double> wind_speeds; 

for(;;) { 
    // Parse the CSV line into variables. 
    char date_str[64 + 1]; 
    double wind_speed; 
    fscanf(file, "%64[^,], ..., %lf,...", date_str, ..., &wind_speed, ...); 
    time_t timestamp = parse_date(date_str); 

    // Store the parsed variables into the vectors. 
    timestamps.push_back(timestamp); 
    wind_speed.push_back(wind_speed); 
} 

double average_wind_speed = std::accumulate(wind_speeds.begin(), wind_speeds.end(), 0.)/wind_speeds.size(); 
0

の.csvファイルは、セルを変更することによって区切られ、テーブルの表現、 ""(コマ)であり、 ";" (セミコラム)を使用して行末を指定します。

EDIT:の場合;動作しません、通常の "\ n"が動作します。以下のアルゴリズムは "\ n"で簡単に適用できます

実際、複雑なプログラムを作成する必要はありません。ここではどのように進めるべきかについてのアイデアがあります。あなたが要求しているとおり、メソッドを理解するのに役立つことを願っています。

1- Read every character (store it in a char) and add it to a string (the string += the char). 

1.1- If the character is a ",", increase a counter and then you compare the string to the value desired (Here WAST). 

1.1.2- If the string equales the desired value, save the counter in an integer (It allows knowing the position of the column you want.) 

1.1.2- If not, continue until the end of the line ";" (which means in your case the desired column does not exist) or until you have a match (your string == "WAST") 

NB:あなたはWASTの位置を知っているように、あなたは別のカウンターでそれを行うことができ、Sの位置など

その後:

Initialise a new counter 
2- Compare the new counter to the saved value in 1.1.2. 

2.1.1- If the values match, store the char contents in a string until you have a new coma. 
2.1.2- If not, read every char until you find a new coma. Then increase your counter and restart from 2. 

3- Continue to read the characters until you find a semi-column ";", and restart at step 2, until you finish to read the file. 

この場合には、最初のステップにそれを要約しますあなたが望むものを見つけるか、行の終わりに到着するまで、各列の名前を読みます。カウンター1のおかげで、その位置( "、"(昏睡)に気づいた)を保管してください。 他の行を1つずつ読み込み、新しいカウンタと比較してcounter1を使用して目的の列の位置( "、"(昏睡)に気付く)に文字列を格納します。

これまでのところ、最も強力なアルゴリズムではないかもしれませんが、それは動作し、理解しやすいです。

私はC言語で記述しないようにしました。プログラムされたソリューションを見ずに手順を理解できるようになりました。それがあなたに合っていればいいと思う。

+0

ありがとうございました!私はそれを試してみましょう。 私は ';'改行の区切り文字であり、非常に役に立ちました。 –

+0

私は今について完全にはわかりません。 、私はあなたが通常の\ n車が使用されることを確認することができます。同じアルゴリズムを\ nでも適用できます。 うってつけです。 – L911

関連する問題