Tomhaus
Tomhaus

Reputation: 33

How to fill array of struct containing pointer arrays

I have an small and quite simple issue in C++. I want to fill array of struct containing double arrays. How can I do that?

typedef struct 
{
    double *inputs[2];
    double *target[1];
} Data;

Data data[] 
{
    new double[2]{10, 20}, new double[1]{30},
    new double[2]{40, 50}, new double[1]{60},
    new double[2]{70, 80}, new double[1]{90},
    new double[2]{100, 110}, new double[1]{120} 
};

and in the main()

printf("data[0]: inputs: %f %f, targets: %f\n",
                   *data[0].inputs[0],
                   *data[0].inputs[1],
                   *data[0].target[0]);

This is my idea, but when I run that it will print this:

data[0]: inputs: 10.000000 30.000000, targets: 40.000000

Of course, at the end of the array data (like 3rd or 4th item) it will cause UNAUTHORIZED ACCESS TO MEMORY

Thank you for your ideas and patience ;)

Upvotes: 2

Views: 164

Answers (3)

JeJo
JeJo

Reputation: 33092

Your problem is here:

typedef struct {
    double *inputs[2];  // this
    double *target[1];  // this
} Data;

This is an array of pointers and hopefully assumed to behave live a dynamic 1D array. Simple fix is:

struct Data {
    double *inputs = nullptr;
    double *target = nullptr;
} ;

However, you have a lot of heap memory allocation using new, which makes a tedious task to delete and thereby the management of your data structure really difficult. I would strongly suggest you to use std::vector<>, which makes your task much easier and more cleaner.

#include <vector>
#include <iostream>

struct Data
{
   std::vector<double> inputs; // use  instead of double *inputs[2];
   std::vector<double> target; // use  instead of double *target[1];
   //Data(const std::vector<double>& a, const std::vector<double>& b) :inputs(a), target(b){}
};

int main()
{
   std::vector<Data> data = // now in your main structure array
   {  { {10, 20}, {30} },
      { {40, 50}, {60} },
      { {70, 80}, {90} },
      { {100, 110},{120} }
   };
   // access using range based loop now
   for(const Data& each_strcut: data)
      std::cout << each_strcut.inputs[0] << " " << each_strcut.inputs[1]
                <<"\t" << each_strcut.target[0] << std::endl;
   return 0;
}

Upvotes: 1

Alan Birtles
Alan Birtles

Reputation: 36613

Using modern c++ makes your code both simpler and safer:

#include <iostream>
#include <array>
#include <vector>

struct Data {
    std::array<double,2> inputs;
    std::array<double,1> target;
};

int main()
{
    std::vector<Data> data = {
        { {10, 20}, {30} },
        { {40, 50}, {60} },
        { {70, 80}, {90} },
        { {100, 110}, {120} }
    };
    std::cout << "data[0]: inputs: " << data[0].inputs[0] << " " << data[0].inputs[1] << ", targets: " << data[0].target[0] << "\n";
}

Your original problem is that double *inputs[2] declares a 2 element array of pointers to double not a pointer to a 2 element array of doubles.

Upvotes: 3

Kaldrr
Kaldrr

Reputation: 2850

Your Data struct contains 2 fields, array of 2 double pointers, and array of 1 double pointers.

That means that initalizing it takes up to 3 double pointers, which means that in your initalization really looks like this

Data data[]{
{new double[2]{ 10, 20 },   new double[1]{ 30 },        new double[2]{ 40, 50 }}, //1st object
{new double[1]{ 60 },       new double[2]{ 70, 80 },    new double[1]{ 90 }}, //2nd object
{new double[2]{ 100, 110 }, new double[1]{ 120 }} //3rd object but 2 parameters??
};

When trying to print it in a loop, 3rd object will cause a segfault, as target field hasn't been properly initalized (when debugging with Visual Studio it's set to null, not sure about other compilers).

Upvotes: 1

Related Questions