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

标签 c++ arrays struct

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

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

最佳答案

您的代码执行以下操作:

cmpnts *uSpeed;

这会创建一个变量 uSpeed,它可以保存 cmpnts 的地址内存中的实例。指针并没有真正的魔力,它们只是一个保存数值的变量。该值是某物在内存中的位置,即它的地址。我们将其标记为指针更多是为了尝试避免混淆作为值的变量和作为地址的变量。

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

稍后,你写

uSpeed->x = new double[numberofpoints];

->dereference运算符(operator)。左边的变量必须是指向某种类型事物的指针,然后假定右边的事物是该地址事物的成员。

记忆一下:你没有初始化uSpeed .

但是这里还有第二个问题。 cmpnts::x是 double ,但您正在尝试为其分配地址。

    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::vector , std::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

--- 编辑---

A std::vector几乎可以包含任何类型,因此您甚至可以构建复合 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] :  ""        ""     ""      ""
}

我们可以通过以下方式访问“hello”:

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)

当您使用结构 vector 时:

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

您首先需要访问 vector 中 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

我在这里找到了一个我曾为某人使用过的 vector 沙箱:http://ideone.com/HERvy1

遍历代码并将其与输出匹配。您还可以在此处找到有关 std::vector 的更多信息:http://en.cppreference.com/w/cpp/container/vector

关于c++ - 将文本文件中的分量 vector 数据读入结构数组 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39629714/

相关文章:

java - 我需要从这个 2D String 方法返回什么?

c++ - 逐元素移动第一个元素指向的数组的函数

c++ - C++中的自动构造函数生成?

arrays - 如何为多个结构体数组获取一个函数?

c++ - 帧缓冲区大小发生变化但无法设置视口(viewport)

c++ - 加入声明和赋值时是否不调用默认构造函数?

c++ - 如何推送字符数组?

C++ 映射 : add pair to the end of the map

java - 从 Java 字符串中获取数据

go - 使用 Go 范围语法的意外行为