将组件矢量数据从文本文件读入结构数组C ++

时间:2016-09-22 03:20:49

标签: c++ arrays struct

所以我有一个包含3个不同速度分量的文本文件,以及与每个速度测量相关的时间戳。 text file can be seen here

u分量对应于x方向,v对应于y方向,w对应于z方向。现在,我需要获取这些数据点并将它们放入我的速度组件结构中,其定义为:

struct cmpnts
{
   double x, y, z;
}

过去当我没有结构并且只有一个整体速度时,我只使用了指针,因此可以在读取文件时创建动态数组。这必须是动态的,因为每个windspeed文件中的点数都会发生变化,每次使用新文件时我都无法手动重新定义该值。

要在没有结构的情况下执行此操作,我的代码如下所示:

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

1 个答案:

答案 0 :(得分:1)

您的代码执行以下操作:

cmpnts *uSpeed;

这会创建一个变量uSpeed,可以在内存中保存cmpnts实例的地址。指针没有真正的魔力,它们只是一个包含数值的变量。该值是某个东西的位置,它的地址,在内存中。我们将它标记为指针,以此作为尝试避免混淆变量的方法,这些变量是值和值为地址的变量。

这里的关键是这个指针是未初始化的。它可以包含零,也可以包含任何随机垃圾。

稍后,你写了

uSpeed->x = new double[numberofpoints];

->dereference运算符。左边的变量必须是指向某种类型的东西的指针,然后右边的东西被假定为该地址处的东西的成员。

召回:您没有初始化uSpeed

但这里存在第二个问题。 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;

这会创建类似于二维字符串数组的东西:

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] :  ""        ""     ""      ""
}

我们可以访问&#34;你好&#34;写作:

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