简体   繁体   English

将文本文件中的分量矢量数据读入结构数组C ++

[英]Reading component vector data from text file into structure array C++

So I have a text file with 3 different components of velocity, as well as the time stamp associated with each velocity measurement. 因此,我有一个文本文件,其中包含3个不同的速度分量以及与每个速度测量值相关的时间戳。 The text file can be seen here . 文本文件可以在这里看到

The u component corresponds to the x direction, v to the y direction, and w to the z direction. u分量对应于x方向,v对应于y方向,w对应于z方向。 Now, I need to take these data points and place them into my structure for the velocity components, which is defined as: 现在,我需要获取这些数据点并将它们放入速度分量的结构中,该结构定义为:

struct cmpnts
{
   double x, y, z;
}

In the past when I did this without structures and with only one overall velocity, I just used pointers so the dynamic arrays could be created when the file was read. 过去,当我不使用结构而仅以一个整体速度执行此操作时,我仅使用指针,因此可以在读取文件时创建动态数组。 This has to be dynamic because the number of points in each windspeed file changes, and I can't manually redefine the value every time I use a new file. 这必须是动态的,因为每个风速文件中的点数都会更改,并且每次使用新文件时都无法手动重新定义该值。

To do this without the structures my code looked like this: 为此,我的代码如下所示:

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

I can't seem to get this to work with my structures though. 我似乎无法使它与我的结构一起使用。 I'm certain I'm making some syntax error somewhere with the pointers (I'm new to C++ so I apologize if it's something dumb!). 我确定我在指针的某个地方犯了一些语法错误(我是C ++的新手,所以我很抱歉,这有点愚蠢!)。 Is it possible to do this without pointers? 没有指针就可以做到吗? My code for reading to the structures looks like this (and obviously it's not working!): 我读取结构的代码看起来像这样(显然不起作用!):

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

Your code does the following: 您的代码执行以下操作:

cmpnts *uSpeed;

This creates a variable, uSpeed, which can hold the address of a cmpnts instance in memory. 这将创建一个变量uSpeed,该变量可以在内存中保存cmpnts实例的地址。 There's no real magic to pointers, they're just a variable that holds a numeric value. 指针没有真正的魔力,它们只是一个拥有数值的变量。 That value is the location of something, its address, in memory. 该值是某物在内存中的位置及其地址。 We mark it as a pointer more as a way to try and avoid confusing variables that are values and variables whose values are addresses. 我们将其更多地标记为指针,以尝试避免混淆作为值的变量和其值为地址的变量。

The key thing here is that this pointer is uninitialized. 这里的关键是该指针未初始化。 It could contain zero or it could contain any random garbage. 它可以包含零,也可以包含任何随机垃圾。

Later on, you write 稍后,您写

uSpeed->x = new double[numberofpoints];

-> is the dereference operator. ->dereference运算符。 The variable on the left has to be a pointer to some type of thing, and the thing on the right is then assumed to be a member of the thing at that address. 左边的变量必须是某种事物的指针,然后假定右边的事物是该地址处事物的成员。

Recall: You did not initialize uSpeed . 回想一下:您没有初始化uSpeed

But there's a second problem here. 但是这里还有第二个问题。 cmpnts::x is a double, but you're trying to assign an address to it. cmpnts::x是双cmpnts::x ,但是您正在尝试为其分配地址。

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

It's really not clear what you think you're doing here, but it looks like you just wanted: 目前还不清楚您在这里做什么,但看起来就像您想要的那样:

    cmpnts* speed = new cmpnts[numberOfPoints];

and then 接着

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

Working with pointers is hard. 使用指针很难。 Don't do it. 不要这样 Use modern C++. 使用现代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

Further reading: std::vector , std::string , 进一步阅读: std :: vectorstd :: string

Or a version that leverages operator<< and operator>> : 或利用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

--- Edit --- -编辑-

A std::vector can encompass almost any type, so you can even build compound vectors: std::vector可以包含几乎所有类型,因此您甚至可以构建复合矢量:

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

this creates something like a 2d-array of strings: 这会创建类似于二维数组的字符串:

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

At this point, the stringvecs looks like this: 此时,stringvecs如下所示:

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

We could access "hello" by writing: 我们可以通过以下方式访问“ hello”:

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

Remember: 记得:

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)

When you are using a vector of a structure: 使用结构的向量时:

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

You first need to access an instance of T within the vector to be able to access it's members: 首先,您需要访问向量中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

I dug up a vector sandbox I used for someone a while back here: http://ideone.com/HERvy1 我在这里挖了一个用于某人的矢量沙箱: http//ideone.com/HERvy1

Walk through the code and match it up with the output. 遍历代码并将其与输出匹配。 You can also find more about std::vector here: http://en.cppreference.com/w/cpp/container/vector 您还可以在此处找到有关std :: vector的更多信息: http : //en.cppreference.com/w/cpp/container/vector

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM