Dynamic array of dynamic (array of struct) - c++

I have a struct named person as follows:
struct person {
int height, weight;
};
I also created an array of person as follows:
struct Arrayofperson {
int len; //indicates the length of this array(its supposed to be dynamic)
person *p; //this is supposed to be the dynamic array of person.
};
And I do this for an array of array of person as follows:
struct Array_2d_ofperson{
int len; //indicates the length of this array(its supposed to be dynamic)
Arrayofperson *subarray; //this is supposed to be the dynamic 2d array of person.
};
This is my code:
#include <iostream>
#include "test.h"
using namespace std;
#define DLLEXPORT extern "C" __declspec(dllexport)
DLLEXPORT Arrayofperson create_arr_person(int len) {
Arrayofperson arr_p;
arr_p.len = len;
arr_p.p = new person[len];
//populate the array here:
for (int a = 0; a < len; a++) {
arr_p.p[a].height = a; //yes they're the same, but it doesn't matter for now.
arr_p.p[a].weight = a;
};
return arr_p;
}
DLLEXPORT void print_arr_person(Arrayofperson pp) {
printf("length: %d\n", pp.len);
for (int b = 0; b < pp.len; b++) {
printf("height, weight %d, %d\n", pp.p[b].height, pp.p[b].weight);
};
}
DLLEXPORT Array_2d_ofperson create_2darr_person(int len, int sublen) {
Array_2d_ofperson arr_2d_person;
arr_2d_person.len = len;
arr_2d_person.subarray = new Arrayofperson[len];
for (int a = 0; a < len; a++) {
arr_2d_person.subarray[a].len = sublen;
arr_2d_person.subarray[a].p = new person[sublen];
for (int b = 0; b < sublen; b++) {
arr_2d_person.subarray[a].p[b].height = b;
arr_2d_person.subarray[a].p[b].weight = b;
}
};
for (int a = 0; a < len; a++) {
for (int b = 0; b < sublen; b++) {
printf("(a, b): %d, %d", arr_2d_person.subarray[a].p[b].height, arr_2d_person.subarray[a].p[b].weight);
printf("\n");
}
};
return arr_2d_person;
cin.get();
}
DLLEXPORT void print_2darr_person(Array_2d_ofperson pp) {
int len = pp.len;
int sublen = pp.subarray[0].len; //yes I haven't forgotten that it can change between different subarrays.
for (int a = 0; a < len; a++) {
for (int b = 0; b < sublen; b++) {
printf("(a, b): %d, %d", pp.subarray[a].p[b].height, pp.subarray[a].p[b].weight);
printf("\n");
}
};
}
I intend to make a dll(the why is not important here) from the above code(it will have more code later on) and use it in python. So here are my questions:
1) It seems that when I do this on the python side:
from ctypes import *
test = CDLL('test.dll') //the dll from the code above, yes it works.
arr = test.create_arr_person(6)
test.print_arr_person(arr)
arr2 = test.create_2darr_person(2, 3)
#test.print_2darr_person(arr2)
raw_input('h')
I get garbage for printing the array of person and get an access violation error from windows when I try to print the 2d array.
So here are my questions, in order of importance(I don't want to use python api within the dll, because the dll could also be used by other languages)
1) How do I make it so that the memory dedicated to the array/ 2darray stays in memory so that I don't get access violation errors. I've tried doing static Arrayofperson, but it didn't work.
2) How is possible to make it easy to access person in the subarray of the 2d array instead of doing.
pp.subarray[a].p[b]. (I want to do this: pp[a][b], where pp is 2darray of person). I believe it has something to do with overloading the [ ] operator, but I'm not familiar with making classes(thats why i made a struct now).
3) How do I access the array/2darray in python using the same way (I want to do this in python:
test = CDLL('test.dll')
array_of_person = test.create_arr_person(5)
print (array_of_person[0]) #something like this

The problem here is that python does not know how to handle your struct. Check the documentation for ctypes, it has a list of supported python types that you can pass to C functions, and documentation on how to make it handle some more types.
The way you've written it, python thinks that all your functions return an int.
You need to read http://docs.python.org/library/ctypes.html
EDIT:
If you do things right, you will probably end up returning an opaque pointer to your struct from your C function to python. Inside your struct, you can use all C++ features then, including the good stuff, like std::vector.

I tried to compile your code on a Linux machine (gcc 4.4.3) and it works.
Have you considered using STL containers (vector) instead? You can use vectors of vectors to generate multidimensional arrays without having to worry about memory leaks.

You can use the fact that the vector is guaranteed to be a continuous chunk of memory and return a pointer to the first element.
T * p = &v[0]
This pointer can be then accessed as an ordinary array and is safe across module boundaries.
The same technique also works for std::strings that can be accessed via a raw pointer to the storage.
const char * p = s.c_str();
You just have to ensure the object that holds the storage does not accidentally go out of scope before you are done.
Multidimensional arrays can be always projected onto one dimension.
1 1 1
2 2 2
3 3 3
can be stored as:
1 1 1 2 2 2 3 3 3

Related

Objective-C to C++ reading binary file into multidimensional array of float

I want to convert the following code from objective C to C++.
In the class myClass, I have this attribute:
float tab[dim1][dim2][dim3];
In an objective-C file, the multidimensional array is filled from a binary file:
NSData *dataTab=[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"pathOfMyTab" ofType:#""]];
[dataTab getBytes:myClass -> tab length:[dataTab length]];
How could I translate this part into C++ ?
I am assuming that your file contains the byte-representation of the array. If this is the case, then to mimic the behaviour of your Objective-C code using only C++ (the only thing that makes this C++ is the reinterpret_cast<>, otherwise it is just straight C), you could use the following code. I have not added any error checking, but left some comments where you might want to perform some.
float tab[dim1][dim2][dim3];
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef dataTabURL = CFBundleCopyResourceURL(mainBundle, CFSTR("pathOfMyTab"), NULL, NULL);
CFReadStreamRef stream = CFReadStreamCreateWithFile(NULL, dataTabURL); // check for NULL return value
CFReadStreamOpen(stream); // check for errors here
CFReadStreamRead(stream, reinterpret_cast<UInt8 *>(tab), sizeof tab); // check that this function returns the number of bytes you were expecting (sizeof tab)
CFReadStreamClose(stream);
// we own "stream" and "dataTabURL" because we obtained these through functions
// with "create" in the name, therefore we must relinquish ownership with CFRelease
CFRelease(stream);
CFRelease(dataTabURL); // ditto
If you already have the path available in a std::string, then you can use the following C++ code to mimic the behaviour of your Objective-C code:
// make sure to include this header
#include <fstream>
// ... then elsewhere in your .cpp file ...
float tab[dim1][dim2][dim3];
std::string path = "path/to/mytab"; // obtain from somewhere
std::ifstream input(path, std::ios::binary); // check that the file was successfully opened
input.read(reinterpret_cast<char *>(tab), sizeof tab); // check that input.gcount() is the number of bytes you expected
I believe in this case we have to use reinterpret_cast<> because the file contains the actual representation of the array (assuming it was previously written to the file in a similar manner).
You can use a hybrid approach, once you have the CFURLRef containing the path to the resource, you can obtain a file system representation of the URL using this function (providing a suitably sized output buffer to store the result), and from there you should be able to pass that to one of std::ifstream's constructors (although, you may need to cast to the appropriate type).
C++ doesn't support variable-length arrays (the size of arrays must be known at compile time). There is also no matrix type provided by the standard library, so if the dimensions of your table vary at run time, then you will need a completely separate approach to the one in my answer. You could consider serialising the output from Objective-C (using e.g. JSON or another format) such that the dimensions of the matrix are also written to the output, making it easier to parse the file in C++.
Take a look at fstream, fread and read, all read binary files, pick the approach that suits.
On my mind the simplest and fastest way is to use memcpy() to copy NSData' bytes into target array with same structure (dimensions) as a source one. See, for example:
https://github.com/Voldemarus/MultiDimensionalArrayDemo/tree/master
#import "DemoClass.h"
#define DIM1 3
#define DIM2 4
#define DIM3 2
#interface DemoClass() {
int src[DIM1][DIM2][DIM3]; // source (initial) array
int dst[DIM1][DIM2][DIM3]; // destination array
}
#end
#implementation DemoClass
- (instancetype) init
{
if (self = [super init]) {
for (int i = 0; i < DIM1; i++) {
for (int j = 0; j < DIM2; j++) {
for (int k = 0; k < DIM3; k++) {
int value = i*100 + j*10 + k;
src[i][j][k] = value;
}
}
}
}
return self;
}
int getIntFromArray(int *array, int i, int j, int k) {
int offset = j*DIM3 + i*DIM2*DIM3;
return array[offset];
}
void putIntToArray(int *array, int i, int j, int k, int value) {
int offset = j*DIM3 + i*DIM2*DIM3;
array[offset] = value;
}
- (void) run
{
// Step 1. Save array into NSData
NSInteger s = sizeof(int)*DIM1*DIM2*DIM3;
NSData *data = [[NSData alloc] initWithBytes:src length:s];
NSAssert(data, #"NSData should be created");
//Step2 - Create new array
int *bytes = (int *)[data bytes];
memcpy(dst,bytes,s);
// Step 3. Compare src and dst
for (int i = 0; i < DIM1; i++) {
for (int j = 0; j < DIM2; j++) {
for (int k = 0; k < DIM3; k++) {
int template = i*100 + j*10 + k;
int s = src[i][j][k];
int d = dst[i][j][k];
// NSLog(#"i %d j %d k %d -->s = %d d = %d",i,j,k,s,d);
NSAssert(s == template, #"Source array should have value from template");
NSAssert(d == s, #"Destination array should be identical to the source");
}
}
}
}
#end
float tab[dim1][dim2][dim3] looks like a three-dimensional array. The standard implementation is with three nested FOR loops.
So your C++ implementation can look like this:
read dim1, dim2, dim3 from somewhere, usually the first values in the file (for example 12 bytes, 4 bytes for each number)
read the rest of the file in three nested FOR loops
Something like:
for (size_t i = 0; i < dim1; ++i)
for (size_t j = 0; j < dim2; ++j)
for (size_t k = 0; k < dim3; ++k)
tab[i][j][k] = read_float_value(inputFile);
In Objective-C you can write the file in a similar way.
Here are some examples to get you started:
Three dimensional arrays of integers in C++
3D array C++ using int [] operator

C++ Object Array Pointer

I am new to C++ arrays and pointer and came across a few problems. I have some inquiries for the following code I wrote.
Version 1:
int main()
{
string a, b;
int age;
Dog d[5];
Dog *p = new Dog[5];
for (int i = 0; i < 5; i++)
{
d[i].setwe(3 * i);
d[i].setag(i);
p[i] = Dog(d[i]);
}
p[5]->showCnt();
//^^^^^^^^^^^^^^ Error above
for (int j = 0; j < 5; j++)
{
delete [] p;
}
return 0;
}
Version 2:
int main()
{
string a, b;
int age;
Dog d[5];
Dog *p[5];
for (int i = 0; i < 5; i++)
{
d[i].setwe(3 * i);
d[i].setag(i);
//p[i] = Dog(d[i]);
p[i] = &d[i];
}
p[5]->showCnt();
return 0;
}
From what I understand I might have written wrongly in version 1 but I want to understand why p is not seen as a pointer in version 1?
This is the hint I got from error: base operand of '->' has non pointer-type 'Dog'.
I am also unsure which is a better way(version 1 or version 2) to copy an object array to a pointer object array.
I would like to apologise in advanced if I have understood it wrongly. Thank you.
p[5]->showCnt() is ilegal because your array of objects has only 5 positions, starting by 0 and ending on 4. So, you just have to replace p[5]->showCnt() by p[4]->showCnt().
About the better version to use, use version 2 if you want to work with static sizes and use version 1 if you want to manage p dynamically to work with more than 5 objects at some moment of your program runtime. Short answer: version 1 is better!

Initialization of user-defined array in C++ class?

I'm working on knight's tour problem, and want to define a class, but I am having trouble with initialize an array defined by user. So the user inputs from the command line argvs are the chessboard lengths mX and nY; and a starting position(x,y). So basically, how do I initialize an array that's defined by the user?
First question: In the public part, is it right to declare int ** tour?
Second question: How do I refer to the array tour in the following functions in the same class?
Third question: In main, I called K.knight to initialize an array of dimension specified by the user, but it wasn't initialized. How do I initialize an array in main using the function K.knigt(), and be able to use the array in the following function K.knightfunc()?
class Ktour{
public:
int xSize; //m
int ySize; //n
int ** tour; //array to be initialized
int solutionsCount; //tracking solutions
int position; //position count, from 0 to m * n -1
// initialize tour matrix
void knight(int M, int N) {
position = 1;
solutionsCount = 0;
xSize = M;
ySize = N;
tour = new int * [xSize];
for (int i = 0; i < xSize; i++) {
for (int j = 0; j < ySize; j++) {
tour[i][j] = 0;
std::cout << tour[i][j] << std::endl;
}
}
}
....some other functions defined in between...
....
....
};
...
// main
int main(int argc, char *argv[])
{
Ktour K;
//user inputs chessboard length mX and nY; and a starting position(x,y)
int mX = atoi(argv[1]);
int nY = atoi(argv[2]);
int x = atoi(argv[3]);
int y = atoi(argv[4]);
//initialization
K.knight(mX, nY);
//run the recursive function;
K.knightFunc(x,y);
return 0;
}
Yeah, it seems more logical to initialize in the ctor. My take on this is you are creating an array of int pointers, and have not yet allocated the ints that are being pointed to.
You have a few possibilities:
If we are to think of a common chessboard, then since the array size is known in advance, and it's not especially big, just create it in the class:
class Ktour{
...
int tour[8][8];
...
}
although some purists might say you should only "new" such arrays. If it is a much larger array, you certainly should.
A more straightforward syntax like what you're trying to do, for handling arrays of unknown size would be:
class Ktour{
...
int **tour=0;
KTour(int M, int N) {
tour = new int * [M];
for (int i=0; i<M; ++i)
tour[i] = new int [N];
};
~KTour() {
for (int i=0; i<M; ++i)
delete [] tour[i];
delete [] tour;
};
...
}
You access it quite simply, with:
std::cout << tour[i][j];
The above kind of coding is error-prone. To reduce your future strife with memory access errors, you really should use STL container classes (or Boost ones, or Qt ones when using Qt, if their size isn't too limited - but you can use STL in Qt also), since they produce an error in debug when you access out-of-bounds subscripts for your arrays, instead of, e.g. overwriting important pointers, etc. Thus, you could use something like:
class Ktour{
...
std::vector < std::vector<int> > Tour;
KTour(int M, int N) {
// tour.resize(M); // not needed.
tour.assign(M, std::vector <int> (N, 0));
};
~KTour() {
// No need to delete
};
...
}
and you access it with
std::cout << tour[i][j];
(Note: The extra lines in the code are some artifact of the <pre> and <code> tags; necessitated by not all of my indented lines being recognized as code.)

How to return C++ Array Pointer in method

First, I made funciton that return Array[2]'s pointer.
int* ReturnArray(int a, int b) {
static int Array[2];
Array[0] = a;
Array[1] = b;
return Array;
}
And I made simple 2-Dimensional array in Main.
int a, b;
in >> NumberOfSize;
int** S = new int*[NumberOfSize];
for (int i = 0; i < NumberOfSize; i++)
S[i] = new int[2];
Last, I added ReturnArray(a,b) to set the value of S[i]
for (int i = 0; i < NumberOfSize; i++)
{
in >> a >> b;
S[i] = ReturnArray(a, b);
}
But in Main, I cannot get right value in Array S[i][j].
When I changed upper way to under, I can set the right value in array S.
for (int i = 0; i < NumberOfSize; i++)
{
in >> a >> b;
S[i][0] = ReturnArray(a, b)[0];
S[i][1] = ReturnArray(a, b)[1];
}
What happended in upper way?
And How can i get right value in only one call ReturnArray function?
(sorry for my fool english.)
The problem it's that you have a static local variable in the function, that means all calls to the function will share the same array and modify the same array, which means only the values set in the last call will be the ones you use.
One way to solve the problem is to do your dynamic allocation and copy the values separately like you do in your working example. Another possible solution is to use another data structure with proper copy-semantics, like e.g. std::pair or std::tuple, and don't have any static array (or anything static at all) in the function.

Initializing multidimensional dynamical array in c++

I'm having problems declaring a multidimensional dynamical array in c style. I want to declare dynamically an array like permutazioni[variable][2][10], the code i'm using is as following (carte is a class i defined):
#include "carte.h"
//other code that works
int valide;
carte *** permutazioni=new carte**[valide];
for (int i=0; i<valide; i++){
permutazioni[i]=new carte*[2];
for (int j=0; j<2; j++) permutazioni[i][j]=new carte[10];
}
the problem is, whenever i take valide=2 or less than 2, the code just stops inside the last for (int i=0; i<valide; i++) iteration, but if i take valide=3 it runs clear without any problem. There's no problem as well if i declare the array permutazioni[variable][10][2] with the same code and any value of valide. I really have no clue on what the problem could be and why it works differently when using the two different 3d array i mentioned before
You show a 3D array declared as permutazioni[variable][10][2] but when you tried to dynamical allocate that you switched the last two dimensions.
You can do something like this:
#include <iostream>
#define NVAL 3
#define DIM_2 10 // use some more meaningfull name
#define DIM_3 2
// assuming something like
struct Card {
int suit;
int val;
};
int main() {
// You are comparing a 3D array declared like this:
Card permutations[NVAL][DIM_2][DIM_3];
// with a dynamical allocated one
int valid = NVAL;
Card ***perm = new Card**[valid];
// congrats, you are a 3 star programmer and you are about to become a 4...
for ( int i = 0; i < valid; i++ ){
perm[i] = new Card*[DIM_2];
// you inverted this ^^^ dimension with the inner one
for (int j = 0; j < DIM_2; j++)
// same value ^^^^^
perm[i][j] = new Card[DIM_3];
// inner dimension ^^^^^
}
// don't forget to initialize the data and to delete them
return 0;
}
A live example here.
Apart from that it is always a good idea to check the boundaries of the inddecs used to access to the elements of the array.
How about using this syntax? Haven't tested fully with 3 dimensional arrays, but I usually use this style for 2 dimensional arrays.
int variable = 30;
int (*three_dimension_array)[2][10] = new int[variable][2][10];
for(int c = 0; c < variable; c++) {
for(int x = 0; x < 2; x++) {
for(int i = 0; i < 10; i++) {
three_dimension_array[c][x][i] = i * x * c;
}
}
}
delete [] three_dimension_array;
Obviously this could be c++ 11/14 improved. Could be worth a shot.