2016-09-22 47 views
0

私は3つの異なる速度成分と各速度測定に関連するタイムスタンプを持つテキストファイルを持っています。 text file can be seen hereテキストファイルから構造体配列にコンポーネントベクトルデータを読み込むC++

u成分はx方向に対応し、vはy方向に対応し、wはz方向に対応する。私はちょうど、私が構造なしで、唯一の全体的な速度でこれをやったとき、過去に

struct cmpnts 
{ 
    double x, y, z; 
} 

:今、私はこれらのデータポイントを取るように定義された速度成分のための私の構造、にそれらを配置する必要がありますファイルを読み込んだときに動的配列を作成できるようにポインタを使用しました。これは、各風速ファイルのポイント数が変化するため動的でなければならず、新しいファイルを使用するたびに値を手動で再定義することはできません。

は私のコードは次のように見えた構造ずにこれを行うには:私はこれはしかし、私の構造で動作するように見えることはできません

int main() 
{ 
    int numberofpoints; // the number of data points 
         // char arrays for storing the variables names 
    char ch1[128], ch2[128]; 
    cout << ch1 << endl; 

    // Two pointers for creating the dynamic arrays later 
    double *itime, *windspeed; 

    // create an object for reading a file 
    ifstream imyfile; 

    // open windspeed.txt 
    imyfile.open("windspeed.txt"); 

    if (imyfile.is_open()) // check if the file is open 
    { 
     // read the total number of data points 
     imyfile >> numberofpoints; 

     // double arrays for storing time and the velocity variables 
     itime = new double[numberofpoints]; 
     windspeed = new double[numberofpoints]; 

     // read the two variable names in windspeed.txt file 
     imyfile >> ch1 >> ch2; 

     // read the time and wind speed 
     int i; 
     for (i = 0; i<numberofpoints; i++) 
     { 
      imyfile >> itime[i] >> windspeed[i]; 

     } 

     // close the file 
     imyfile.close(); 
    } 
    else 
    { 
     cout << "unable to open the file"; 
     exit(0); 
    } 
} 

。私はポインタのどこかで文法エラーを起こしていると確信しています(私はC++を初めて使っていますので、何かばかげていると謝ります)。ポインタなしでこれを行うことは可能ですか?構造物に読み取るための私のコードは次のようになります(と明らかにそれは働いていない!):

#include <iostream> 
#include <fstream> 
using namespace std; 

struct cmpnts 
{ 
    double x, y, z; 
}; 

struct wind 
{ 
    cmpnts velocity; 
    cmpnts direction; 
    cmpnts urms; 
    double airdensity; 
}; 

struct turbine 
{ 
    double R, Cp, V, yaw, power; 
    cmpnts direction; 
}; 

int main() 
{ 

    // Read data from file 
    int numberofpoints;   // the number of data points 
    char ch1[128], ch2[128], ch3[128], ch4[128]; // Char arrays for storing the variables names 

    // Pointers for creating the dynamic arrays later 
    double *itime; 
    cmpnts *uSpeed; 
    cmpnts *vSpeed; 
    cmpnts *wSpeed; 

    // create an object for reading a file 
    ifstream imyfile; 

    // open windspeed.txt 
    imyfile.open("windspeed.txt"); 

    if (imyfile.is_open()) // check if the file is open 
    { 
     // read the total number of data points 
     imyfile >> numberofpoints; 

     // double arrays for storing time and the velocity variables 
     itime = new double[numberofpoints]; 
     uSpeed->x = new double[numberofpoints]; 
     vSpeed->y = new double[numberofpoints]; 
     wSpeed->z = new double[numberofpoints]; 

     // read the two variable names in windspeed.txt file 
     imyfile >> ch1 >> ch2 >> ch3 >> ch4; 

     // read the time and wind speed 
     int i; 
     for (i = 0; i<numberofpoints; i++) 
     { 
      imyfile >> itime[i] >> uSpeed[i] >> vSpeed[i] >> wSpeed[i]; 

     } 

     // close the file 
     imyfile.close(); 
    } 
    else 
    { 
     cout << "unable to open the file"; 
     exit(0); 
    } 
} 
+0

「cmpnts * uSpeed;」とは何でしょうか? – kfsone

+0

また、実際にwindspeed.txtがどのように見えるかを示してください。 – kfsone

答えて

1

あなたのコードは次の操作を実行します。

cmpnts *uSpeed; 

これは、変数、uSpeedを作成するできメモリ内のcmpntsインスタンスのアドレスを保持します。ポインタには本当の魔法はありません。数値だけを保持する変数です。その値は、メモリ内の何か、そのアドレスの場所です。値をアドレスとする値と変数である混乱する変数を避けようとする方法として、これをポインタとしてより多くマークします。

ここで重要なことは、このポインタが初期化されていないことです。それはゼロを含んでいても、ランダムなゴミを含んでいてもかまいません。

後で、あなたが

uSpeed->x = new double[numberofpoints]; 

->を書くにはdereference演算子です。左側の変数はある種のものへのポインタでなければならず、右側のものはそのアドレスのもののメンバーであるとみなされます。

リコール:uSpeedを初期化していません。

しかし、ここに2番目の問題があります。 cmpnts::xはダブルですが、アドレスを割り当てようとしています。

uSpeed->x = new double[numberofpoints]; 
    vSpeed->y = new double[numberofpoints]; 
    wSpeed->z = new double[numberofpoints]; 

それはあなたがここでやっていると思います本当に明確ではないのですが、あなたはちょうど欲しかったように見えます:ポインターでの作業

cmpnts* speed = new cmpnts[numberOfPoints]; 

、その後

imyfile >> itime[i] >> speed[i].x >> speed[i].y >> speed[i].z; 

は難しいです。それをしないでください。最新のC++を使用してください。

#include <iostream> 
#include <fstream> 
#include <vector> 
#include <string> 

struct Vector // note upper case for my own class 
{ 
    double x_, y_, z_; // the '_' distinguishes a member from a variable 
}; 

struct SpeedEntry 
{ 
    int time_; 
    Vector vel_; 
}; 

int main() 
{ 
    // create an object for reading a file 
    std::ifstream imyfile("windspeed.txt"); 
    if (!imyfile.is_open()) // check if the file is open 
    { 
     std::cerr << "unable to open the file"; 
     return 1; // non-zero return from main = failure 
    } 

    // read the total number of data points 
    size_t numberOfPoints; 
    imyfile >> numberofpoints; 
    imyfile.ignore(); // ignore end of line/whitespace 

    // for storing time and the velocity variables 
    std::vector<SpeedEntry> speeds; 
    speeds.reserve(numberOfPoints); 

    // read the two variable names in windspeed.txt file 
    // we're ignoring these values so... 
    std::string vars[4]; 
    imyfile >> vars[0] >> vars[1] >> vars[2] >> vars[3]; 
    std::cout << "vars are " << vars[0] << ", " << vars[1] << ", " << vars[2] << ", " << vars[3] << "\n"; 

    // Now read each of the lines 
    for (size_t i = 0; i < numberOfPoints; ++i) 
    { 
     SpeedEntry entry; 
     if (!(imyfile >> entry.time_ >> entry.vel_.x_ >> entry.vel_.y_ >> entry.vel_.z_)) { 
      std::cerr << "Error reading entry #" << (i+1) << "\n"; 
      return 2; 
     } 
     speeds.push_back(entry); 
    } 

    std::cout << "Read " << speeds.size() << " entries\n"; 

    // c++11 range-based loop 
    for (auto&& entry : speeds) 
    { 
     std::cout << "Read: " << entry.time_ << " : " 
        << entry.vel_.x_ << ',' << entry.vel_.y << ',' << entry.vel.z_ 
        << '\n'; 
    } 
} // file closes automatically when `imyfile` goes out of scope 

さらに読書:std::vectorstd::string

それともoperator<<operator>>を活用したバージョン:

#include <iostream> 
#include <fstream> 
#include <vector> 
#include <string> 

struct Vector // note upper case for my own class 
{ 
    double x_, y_, z_; // the '_' distinguishes a member from a variable 
}; 

// implement input and output operators for Vec 
std::istream& operator >> (std::istream& in, Vector& vec) 
{ 
    return in >> vec.x_ >> vec.y_ >> vec.z_; 
} 
std::ostream& operator << (std::ostream& out, const Vector& vec) 
{ 
    return out << vec.x_ << ' ' << vec.y_ << ' ' << vec.z; 
} 

struct SpeedEntry 
{ 
    int time_; 
    Vector vel_; 
}; 

// implement input and output operators for SpeedEntry 
std::istream& operator >> (std::istream& in, SpeedEntry& entry) 
{ 
    return in >> entry.time_ >> entry.vel_; 
} 

std::ostream& operator << (std::ostream& out, const Vector& vec) 
{ 
    return out << entry.time_ << ' ' << entry.vel_; 
} 


int main() 
{ 
    std::ifstream imyfile("windspeed.txt"); 
    if (!imyfile.is_open()) // check if the file is open 
    { 
     std::cerr << "unable to open the file"; 
     return 1; // non-zero return from main = failure 
    } 

    // read the total number of data points 
    size_t numberOfPoints; 
    imyfile >> numberofpoints; 
    imyfile.ignore(); // ignore end of line/whitespace 

    // read the two variable names in windspeed.txt file 
    // we're ignoring these values so... 
    std::string vars[4]; 
    imyfile >> vars[0] >> vars[1] >> vars[2] >> vars[3]; 
    std::cout << "vars are " << vars[0] << ", " << vars[1] << ", " << vars[2] << ", " << vars[3] << "\n"; 

    // for storing time and the velocity variables 
    std::vector<SpeedEntry> speeds; 
    speeds.reserve(numberOfPoints); 

    // Now read each of the lines 
    for (size_t i = 0; i < numberOfPoints; ++i) 
    { 
     SpeedEntry entry; 
     if (!(imyfile >> entry)) { 
      std::cerr << "Error reading entry #" << (i+1) << "\n"; 
      return 2; 
     } 
     speeds.push_back(entry); 
    } 

    std::cout << "Read " << speeds.size() << " entries\n"; 

    // c++11 range-based loop 
    for (auto&& entry : speeds) 
     std::cout << "Read: " << entry << '\n'; 
} // imyfile closes automatically when it goes out of scope 

---編集---

std::vectorはほとんど包含することができます任意のタイプなので、化合物ベクトルを作成することもできます:

std::vector<std::vector<std::string>> stringvecs; 

これは文字列の2Dアレイのようなものを作成:この時点で

std::vector<std::vector<std::string>> stringvecs; 

// allocates 5 empty std::vector<strings> in stringvecs 
stringvecs.resize(5); 

// push "hello world" onto the first entry 
stringvecs[0].push_back("hello"); 

を、stringvecsは次のようになります。

stringvecs { 
    [0] : std::vector of std::string containing { "hello" }, 
    [1] : empty std::vector of std::string 
    [2] : ""  ""  ""  "" 
    [3] : ""  ""  ""  "" 
    [4] : ""  ""  ""  "" 
} 

我々は、書面で "こんにちは" にアクセスできます。

std::cout << stringvecs[0][0] << "\n"; 

覚えていること:

stringvecs is of type std::vector<std::vector<std::string>> 
if stringvecs.empty() == false 
    stringvecs[0] is of type std::vector<std::string> (returned by reference) 
    if stringvecs.empty() == false && stringvecs[0].empty() == false 
    stringvecs[0][0] is of type std::string (returned by reference) 

あなたは構造体のベクトルを使用している:

struct T { 
    int i_; 
    bool b_; 
    std::string s_; 
}; 
std::vector<T> ts; 

あなたはそれのメンバーにアクセスできるようにするには、ベクター内Tのインスタンスにアクセスするための最初の必要性:

ts.emplace_back(1, false, "first"); // creates a T with these values 
ts.emplace_back(2, true, "seconds"); 

std::cout << ts[0].s_ << "\n"; // access member "s_" of the first entry 
std::cout << ts[1].i_ << "\n"; // prints 2, array indexes are 0-based 

ここで私が誰かのために使ったベクターサンドボックスを掘りました:http://ideone.com/HERvy1

コードを歩き、出力と突き合わせてください。 std :: vectorの詳細については、こちらをご覧ください:http://en.cppreference.com/w/cpp/container/vector

+0

ありがとう、本当にありがとう! 上記の「スピード」で定義したベクトルについては、ネストされた構造の場合はそれが可能ですか?たとえば、「風速1」という名前の「Speedentry」構造の変数があります。私はファイルからのすべてのデータをwind1のvel_に特に割り当てたいと思う。私はただ書くことができない、ベクトル wind1.vel_正しい? –

+0

@CourtneyLeighベクトルクラスは配列のようなものですが、フードの下ではresize()/ push_backなどのように動的にメモリを割り当てます。 'std :: vector <'anything'>'を作成できます。読み込みたいのはベロシティベクトルだけですが、それを 'std :: vector velocities'にしてそれを読み込んで、必要な場所に割り当てることができます。または、 'std :: vector winds'を使用して、必要な各項目の1つのフィールドに値を設定します。答えにすばやい例を追加します。 – kfsone

関連する問題