2016-09-22 4 views
0

Also habe ich eine Textdatei mit 3 verschiedenen Komponenten der Geschwindigkeit, sowie den Zeitstempel für jede Geschwindigkeitsmessung. Die text file can be seen here.Komponente Vektordaten aus Textdatei in Strukturarray lesen C++

Die Komponente u entspricht der x-Richtung, v der y-Richtung und w der z-Richtung. Nun, ich brauche diese Datenpunkte zu nehmen und sie in meine Struktur für die Geschwindigkeitskomponenten setzen, die wie folgt definiert ist:

struct cmpnts 
{ 
    double x, y, z; 
} 

In der Vergangenheit, als ich das tat, ohne Strukturen und mit nur einer Gesamtgeschwindigkeit, ich habe gerade verwendete Zeiger, damit die dynamischen Arrays beim Lesen der Datei erstellt werden konnten. Dies muss dynamisch sein, da sich die Anzahl der Punkte in jeder Windgeschwindigkeitsdatei ändert, und ich kann den Wert nicht jedes Mal neu definieren, wenn ich eine neue Datei verwende.

dies mein Code ohne die Strukturen zu tun sah wie folgt aus:

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); 
    } 
} 

ich nicht dieses zwar mit meinen Strukturen zu arbeiten zu bekommen scheinen. Ich bin sicher, dass ich irgendwo einen Syntaxfehler mit den Zeigern mache (ich bin neu in C++, also entschuldige ich mich, wenn es etwas dummes ist!). Ist es möglich, dies ohne Zeiger zu tun? Mein Code für den Strukturen zu lesen wie folgt aussieht (und offensichtlich ist es nicht funktioniert!):

#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

Was stellen Sie sich vor das 'cmpnts * uSpeed;' tut? – kfsone

+0

Bitte zeigen Sie auch, wie windspeed.txt tatsächlich aussieht. – kfsone

Antwort

1

Ihr Code macht folgendes:

cmpnts *uSpeed; 

Es wird eine Variable, uSpeed, die kann Halten Sie die Adresse einer cmpnts Instanz im Speicher. Es gibt keine echte Magie für Zeiger, sie sind nur eine Variable, die einen numerischen Wert enthält. Dieser Wert ist der Ort von etwas, seiner Adresse, im Speicher. Wir markieren es als einen Zeiger, um verwirrende Variablen zu vermeiden, die Werte und Variablen sind, deren Werte Adressen sind.

Der Schlüssel hier ist, dass dieser Zeiger nicht initialisiert ist. Es könnte Null enthalten oder es könnte irgendeinen zufälligen Müll enthalten.

Später, schreiben Sie

uSpeed->x = new double[numberofpoints]; 

-> der dereference Operator ist. Die Variable auf der linken Seite muss ein Zeiger auf irgendeine Art von Ding sein, und das Ding auf der rechten Seite wird dann als ein Mitglied der Sache an dieser Adresse angenommen.

Rückruf: Sie haben uSpeed nicht initialisiert.

Aber es gibt ein zweites Problem hier. cmpnts::x ist ein Double, aber Sie versuchen, eine Adresse zuzuweisen.

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

Es ist wirklich nicht klar, was Sie denken, Sie hier machen, aber es sieht aus wie Sie wollte nur:

cmpnts* speed = new cmpnts[numberOfPoints]; 

und dann

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

mit Zeigern arbeiten hart. Tu es nicht. Verwenden Sie modernes 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 

Weiterführende Literatur: std::vector, std::string,

Oder eine Version, die operator<< und operator>> nutzt:

#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 

--- --- Bearbeiten

A std::vector fast umfassen kann jeden Typ, so dass Sie sogar zusammengesetzte Vektoren erstellen können:

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

dies so etwas wie ein 2D-Array von Strings erstellt:

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"); 

An diesem Punkt sieht die stringvecs wie folgt aus:

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

Wir konnten durch Schreiben "Hallo" zugreifen:

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

Nicht vergessen:

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) 

Wenn Sie einen Vektor einer Struktur verwenden:

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

Als erstes müssen Sie in der Lage sein eine Instanz von T innerhalb des Vektors zuzugreifen, darauf zuzugreifen ist Mitglieder:

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 

Ich grub eine Vektor-Sandbox, die ich für jemanden verwendet habe, eine Weile zurück: http://ideone.com/HERvy1

Gehen Sie den Code durch und vergleichen Sie ihn mit dem Ausgang. Sie können auch mehr über std :: vector hier finden: http://en.cppreference.com/w/cpp/container/vector

+0

Vielen Dank dafür, ich schätze es sehr! Für den Vektor, den Sie oben für "Geschwindigkeiten" definieren, kann ich das für verschachtelte Strukturen tun? Zum Beispiel habe ich eine Variable der "Speedentry" -Struktur, die ich "wind1" genannt habe. Ich möchte, dass alle Daten aus der Datei speziell dem vel_ von wind1 zugewiesen werden. Ich kann nicht einfach schreiben, Vektor wind1.vel_ korrekt? –

+0

@CourtneyLeigh Die Vektorklasse präsentiert sich ähnlich wie ein Array, aber unter der Haube weist sie dynamisch Speicher zu, wenn Sie die Größe ändern()/push_back usw. Sie können ein 'std :: vector <'anything'>' erstellen. Wenn Sie nur die Velocity-Vektoren lesen möchten, können Sie einfach einen 'std :: vector velocities' erstellen und sie dort einlesen und ihnen dann zuweisen, wo Sie sie brauchen. Oder Sie können einen 'std :: vector winds 'verwenden und einfach das eine Feld jedes gewünschten Eintrags ausfüllen. Ich füge ein schnelles Beispiel zu der Antwort hinzu. – kfsone