简体   繁体   中英

Difference dynamic static 2d array c++

Im using opensource library called wxFreeChart to draw some XY charts. In example there is code which uses static array as a serie :

double data1[][2] = {
                { 10, 20, },
                { 13, 16, },
                { 7, 30, },
                { 15, 34, },
                { 25, 4, },
        };

dataset->AddSerie((double *) data1, WXSIZEOF(dynamicArray));

WXSIZEOF ismacro defined like: sizeof(array)/sizeof(array[0])

In this case everything works great but in my program Im using dynamic arrays (according to users input).

I made a test and wrotecode like below:

double **dynamicArray = NULL;
        dynamicArray = new double *[5] ;

        for( int i = 0 ; i < 5 ; i++ )
            dynamicArray[i] = new double[2];

        dynamicArray [0][0] = 10;
        dynamicArray [0][1] = 20;
        dynamicArray [1][0] = 13;
        dynamicArray [1][1] = 16;
        dynamicArray [2][0] = 7;
        dynamicArray [2][1] = 30;
        dynamicArray [3][0] = 15;
        dynamicArray [3][1] = 34;
        dynamicArray [4][0] = 25;
        dynamicArray [4][1] = 4;

dataset->AddSerie((double *) *dynamicArray, WXSIZEOF(dynamicArray));

But it doesnt work correctly. I mean point arent drawn. I wonder if there is any possibility that I can "cheat" that method and give it dynamic array in way it understands it and will read data from correct place

thanks for help

You can't use the WXSIZEOF macro on dynamically allocated arrays. That's for determining the size of an array, you have a pointer to an array :) You can't use that trick with non-compile-time constant arrays.

The parameter wants the number of pairs in the array - and uses a tricky macro to figure it out (using the macro is better for maintainability - there's only one place that uses the size constant).

You can probably simply pass 5 to the function (or whatever variable you use to determine the size of your array).

(I should add that I'm not familiar with this particular API... and it could be doing something funky that would make this not work... but I doubt it)

EDIT. It appears (from some comments) that this function does require contiguous storage.

I don't think you need to write your own function to put these elements contiguous in memory. That would be a lot of reallocation and copying. More likely, you should be using a different class. After browsing their very minimal documentation, it looks like you can use XYDynamicSerie to build a dynamic list of points, then adding it to an XYDynamicDataset or something.

If You define an array like

double myArr[5][2];

All cells occupy a continuous chunk of memory and I'm pretty sure dataset->AddSerie relies on that.

You can't guarantee that if you allocate memory in chunks, using consecutive calls to new.

My proposition is to write a simple class that allocates a continuous chunk of memory for storage and uses operator() to access that memory as a two dimensional array using 2 indices. Internally You can use a vector<double> to manage the storage, and You can pass the address of the first element of that vector to dataset->AddSerie

Please check the code in this C++ FAQ example and try to understand it. The matrix example uses new[] and delete[]. You should use a vector instead, and the type double instead of Fred

Where in the example, there is a private section like this

class Matrix {
 public:
   ...
 private:
   unsigned nrows_, ncols_;
   Fred* data_;
 };

(The example shows a matrix of Freds ) You should use a vector<double>

class Matrix {
 public:
   ...
 private:
   unsigned nrows_, ncols_;
   vector<double> data_;
 };

That will make the code much simpler. You don't even need a destructor, because the vector manages the memory.

Using @Stephen's answer I created xy plot which can easyly process various data without messing with convertion to (double *) and SIZE<...> macro. Maybe this chunk of code will be interesting for someone.

...
// create plot
XYPlot *plot = new XYPlot();

// create dynamic dataset and serie
XYDynamicDataset *ddataset = new XYDynamicDataset();
XYDynamicSerie *dds = new XYDynamicSerie();

///add values. you can simply grab this data from other sources
///    such as std::vector filled by user
dds->AddXY(1.1, 1.1);
dds->AddXY(3.1, 2.1);
dds->AddXY(5.1, 1.8);

ddataset->AddSerie(dds);

ddataset->SetRenderer(new XYLineRenderer());

plot->AddDataset(ddataset);
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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