I want to make a 2d, 3 by 3 ,array like this:
double *array;
void setArray(double x, double y, double z){
array = {{x,0,0},
{0,y,0},
{0,0,z}};
}
I read some posts suggested something like this:
double **array = new double*[3];
void setArray(double x, double y, double z){
array[0] = new double*[3];
array[0][0] = x;
array[0][1] = 0;
array[0][2] = 0;
...
if there any method I can set a 2d array directly using values {{x,0,0},{0,y,0},{0,0,z}}?
Thanks in advance.
If you want to use lists like {{x,0,0},{0,y,0},{0,0,z}}, you should use arrays with hard-coded size:
double *array; // no good
double array[3][3]; // OK
Fill them with copying:
void setArray(double x, double y, double z){
double temp[3][3] = {{x,0,0},
{0,y,0},
{0,0,z}};
memcpy(&array, &temp, sizeof(array));
}
If you don't need jagged array, and the size is known at design time you can use this syntax to declare it:
double array[3][3];
However, if you want to use an initialisation list, you could do it like this:
typedef double Array[3][3];
Array& array(double x = 0.0, double y = 0.0, double z = 0.0) {
static double array_[3][3] = {{x,0,0},{0,y,0},{0,0,z}};
return array_;
}
// init:
array(4,5,8);
// access:
array()[0,2];
Related
I have a function in my code of the type:
double f (double x, double y){
...
int entry_1 = 0;
int entry_2 = 1;
...
}
The values for entry_1 and entry_2 will change after some loops inside the function f. The function f will be used in the same way in the main script:
double f_value;
double y_instance = 0.5;
for (int i = 0; i<100; i++){
...
f_value = f(x*i, y_instance);
...
}
Let's suppose that after this loop, entry_1 = 7 and entry_2 = 0, because they changed inside the f function.
If entry_1 and entry_2 were global variables, now I would do something like this:
entry_1 = 0;
entry_2 = 1;
for (int i = 0; i<100; i++){
...
f_value = f(x*i-2, y_instance);
...
}
I don't think is a good idea to set entry_1 and entry_2 as input parameters, because I would be forced to pass some value during the for loops in the main function. I want that entry_1 and entry_2 are manipulated by f during the for loops, and after those loops, reinitialize them from the main function.
You could use a class, and make your program object-oriented:
class Foo
{
public:
double f (double x, double y)
{
return x + y + entry_1; // for example.
}
void setEntry1(double value)
{
entry_1 = value;
}
private:
double entry_1 = 0;
double entry_2 = 1;
};
You then use it like that:
Foo object;
object.setEntry1(0.5);
double z = object.f(0.1, 0.2);
double z1 = object.f(0.2, 0.3);
That allows you to have multiple object performing f with different entry values. And to change those entry values.
You can turn them into parameters of the function.
But instead of by copy, take them by reference :
double f (double& entry_1, double& entry_2, double x, double y)
{ ...... }
That way they can be stored wherever You want, but will retain the modifications between calls of the function.
But a better way would be for it to be private variables of a class.
I have this structure:
struct Vertex {
Vertex(float px, float py, float pz,
float nx, float ny, float nz,
float tx, float ty) : position(px, py, pz),
normals(nx, ny, nz),
texCoords(tx, ty) {}
XMFLOAT3 position;
XMFLOAT3 normals;
XMFLOAT2 texCoords;
};
and I need to fill an array of that with some vectors:
std::vector<XMFLOAT3> positions;
std::vector<XMFLOAT3> normals;
std::vector<XMFLOAT2> texCoords;
The length of the array is given by
int numVertices;
I' d like to fill the array of struct Vertex with the vectors given. How can I do that?
I tried to initialize the array in this way:
Vertex points[numVertices];
but that var does not have a constant value.
Thank you for your help.
std::vector is the best option to create a dynamic array.
It takes care of memory management for you.
You can access the contents of the array using std::vector::data, std::vector::operator[], std::vector::iterator.
You can process each element of a std::vector using a range-for loop.
Instead of
Vertex points[numVertices];
use
std::vector<Vertex> points(numVertices);
If you must use raw arrays, you can try this. Assuming XMFLOAT3, XMFLOAT2 is something like follows:
struct XMFLOAT3 {
XMFLOAT3(float x, float y, float z) : _x(x), _y(y), _z(z) {};
float _x;
float _y;
float _z;
};
struct XMFLOAT2 {
XMFLOAT2(float x, float y) : _x(x), _y(y) {};
float _x;
float _y;
};
define an init function to initialize Vertex array by dynamically allocating and initializing the elements as:
Vertex **
initVertex(int numVertices)
{
Vertex **points = new Vertex *[numVertices];
for (int i = 0; i < numVertices; ++i) {
points[i] = new Vertex(positions[i]._x, positions[i]._y, positions[i]._x,
normals[i]._x, normals[i]._y, normals[i]._z,
texCoords[i]._x, texCoords[i]._y);
}
return points;
}
You can use Vertex **points = initVertex(numVertices) and dereference each element.
If you must have Vertex *points then you can use this function to create the initialized array of Vertices:
Vertex *
initVertex2(int numVertices)
{
char *points_buf = new char[sizeof(Vertex) * numVertices];
Vertex *points = reinterpret_cast<Vertex *>(points_buf);
for (int i = 0; i < numVertices; ++i) {
new (points_buf + i * sizeof(Vertex))
Vertex(positions[i]._x, positions[i]._y, positions[i]._x,
normals[i]._x, normals[i]._y, normals[i]._z,
texCoords[i]._x, texCoords[i]._y);
}
return points;
}
And call it Vertex *points = initVertex2(numVertices) and use array indexing to access each element.
Please take a look at the code below:
#include <iostream>
using namespace std;
int main(){
char matrix[2][2][2];
return 0;
}
int getMatrixData(char matrix[][2][2], int x, int y, int z) {
return matrix[x][y][z];
}
When matrix 3d array passed in as a parameter into a function, why is it ok not to specify the first [] size? How this missing dimension can be explained?
Your code is syntactically incorrect. Assuming you meant int getMatrixData(char matrix[][2][2], int x, int y, int z).
When you pass array arguments to function, array decays to pointer to first element (type char [2][2] in this case).
Now some syntax of array and pointer are similar so you don't find much difference.
When multidimensional array is passed, for example 3d in your case, it can be seen as array of 2-d arrays. So you need to give the type of each element char [2][2] in your case and you can skip the dimension of final array as it will decay to pointer anyway. char [2][2] is the information compiler needs to compute the offset of each element.
offset of matrix[x][y][z] = base address of matrix +
x * sizeof(char [2][2]) +
y * sizeof(char [2]) +
z
If you don't pass the dimensions of initial element, compiler can't resolve sizeof in above equation. Passing skipped dimension is optional.
In c++ I would use multidimensional arrays in a different way. There are many topics on the internet about it.
This topic explains how you could do it using a char***. E.g.:
char getMatrixData(char*** matrix, int x, int y, int z)
{
return matrix[x][y][z];
}
int main()
{
char ***matrix = new char**[2];
for (auto i = 0; i < 2; i++)
{
matrix[i] = new char*[2];
for (auto j = 0; j < 2; j++)
{
matrix[i][j] = new char[2];
}
}
getMatrixData(matrix, 1, 1, 1);
// N.B.! you should normally free the memory using delete []!!
// But in this case the program ends, so the memory is freed anyhow.
return 0;
}
But you could also use the std::vector type
#include <vector>
using std::vector;
using CharVector1D = vector<char>;
using CharVector2D = vector<CharVector1D>;
using CharVector3D = vector<CharVector2D>;
char getMatrixData(CharVector3D const& matrix, int x, int y, int z)
{
return matrix[x][y][z];
}
int main()
{
CharVector3D matrix(2, CharVector2D(2, CharVector1D(2)));
getMatrixData(matrix, 1, 1, 1);
return 0;
}
However, c++ is supposed to be an object oriented programming language. So it is probably better to define an matrix object.
#include <vector>
using std::vector;
template <class T>
class Matrix3D
{
private:
size_t _sizeX;
size_t _sizeY;
size_t _sizeZ;
vector<T> _data;
public:
Matrix3D(size_t const x_size, size_t const y_size, size_t const z_size)
: _sizeX(x_size)
, _sizeY(y_size)
, _sizeZ(z_size)
, _data(vector<T> (x_size*y_size*z_size))
{}
T GetData(size_t const x, size_t const y, size_t const z) const
{
return _data.at(x + (_sizeX * (y + (_sizeY * z))));
}
};
int main()
{
Matrix3D<char> matrix(2, 2, 2);
matrix.GetData(1, 1, 1);
return 0;
}
This is a difficult issue but I'm not sure where to turn. To sum it up from the start, I'm having trouble with arrays in c++. To head off your inevitable response, I have to use arrays, I can't use vectors. The reason being that I will eventually be interfacing this with CUDA which can't accept vectors.
Anyway, I have written my own class to handle 2D arrays and all the stuff that goes with that behind the scenes. The header file is reproduced at the bottom of this question. I use this class to define a 6 x 10 array. I then loop over many items, primarily using the add method of my class. At some point in this complicated loop, the size of my array switches from 6 x 10 to 0 x 1074266112. I have tried to debug my code and figure out what the issue is but for the life of me I cannot find the issue.
I've printed out all the values at the moment the array size changes, and none of them are out of the norm and I'm never trying to index the array outside of the 6x10 size. In fact, it never even happens at the same point of the loop, it just seems to happen randomly for each run. The only constant I can find between each issue is that the new array size is always exactly 0 x 1074266112.
Sorry I can't provide a minimum working example, but this issue only crops up in my large program and I can't reproduce it in a smaller program. I was at least hoping anyone could see if I'm doing anything wrong with my Matrix program below and possibly suggest a method of debugging.
EDIT: If I change this to use a vector rather than an array, the issue goes away. I.e., if I change the relevant parts to vector<double> data and upon instantiating, data = *(vector<double>(x * y)), the issue mentioned above is no longer a problem. However I have no idea what could be the problem with making this an array.
#include <vector>
#include <iostream>
#ifndef MATRIX_H
#define MATRIX_H
using std::vector; using std::cout; using std::endl;
class Matrix {
//Define the private variables associated with any instance of this class.
double * data; //The 1D pointer which points to the array
int w, h; //The width and height of the 2D array that the 1D data array represents
public:
Matrix(){}
Matrix(int x, int y){ setSize(x,y); }
void setSize(int x, int y){ w = x; h = y; data = new double[x * y]; setAll(0); }
//Two methods to get the height and width of the effective 2D array
int getWidth(){ return w; }
int getHeight(){ return h; }
//Several methods used to set and get the values of elements within the array as well as extracting
//rows and columns as vectors.
void set(int x, int y, double value){ data[y*w + x] = value; }
void setAll(double value);
double get(int x, int y){ return data[y*w + x]; }
vector<double> getCol(int x);
vector<double> getRow(int y);
//Several methods to adjust the current value by the input
void increment(int x, int y){ data[y*w + w] += 1; }
void add(int x, int y, double value){ data[y*w + x] += value; }
void subtract(int x, int y, double value){ data[y*w + x] -= value; }
void multiply(int x, int y, double value){ data[y*w + x] *= value; }
void divide(int x, int y, double value){ data[y*w + x] /= value; }
};
void Matrix::setAll(double value){
for (int i = 0; i < w*h; i++){
data[i] = value;
}
}
vector<double> Matrix::getCol(int x){
vector<double> column(h);
for (int i = 0; i < h; i++){ column[i] = data[i*w + x]; }
return column;
}
vector<double> Matrix::getRow(int y){
vector<double> row(w);
for (int i = 0; i < w; i++){ row[i] = data[y*w + i]; }
return row;
}
#endif /* MATRIX_H */
Your increment method is wrong; it depends only on y when from context it looks like you intended to also use x in the array index calculation. If you're calling this increment somewhere in your program, you're probably writing to memory off in la-la land somewhere. I don't know if that's the only cause of your issue, but anyway it will corrupt your heap in probably unhelpful ways.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int width = 100;
int height = 100;
float cam[] = {-1.1,-1.0,1.2};
float D[] = {0.2,0.2,-0.2};
float U[] = {0.0,1.0,0.0};
float* cross(float* v1,float* v2)
{
float el1[] = {(v1[1]*v2[2]-v1[2]*v2[1]),(v1[2]*v2[0]-v1[0]*v2[2]),(v1[0]*v2[1]-v1[1]*v2[0])};
return el1;
}
float* neg3(float* v)
{
float arr[3];
for(int i=0;i<3;i++)
arr[i] = 0.0-(v[i]);
return arr;
}
/*
float* cam_space(float* p)
{
float* e1 = cross(D,U);
float* e2 = cross(D,cross(U,D));
float* e3_n = D;
float ar[4];
ar[0] = e1[0]*p[0]+e1[1]*p[1]+e1[2]*p[2];
ar[1] = e2[0]*p[0]+e2[1]*p[1]+e2[2]*p[2];
ar[2] = -(e3_n[0]*p[0]+e3_n[1]*p[1]+e3_n[2]*p[2]);
ar[3] = p[3];
return ar;
}
*/
float* translate(float* p,float* v)
{
float arr1[3];
for(int i=0;i<=2;i++)
arr1[i] = p[i] + v[i];
return arr1;
}
int main()
{
float* poi;
poi = cam; //undo later
float* nc;
nc = neg3(cam);
cout<<" "<<nc[0]<<" "<<nc[1]<<" "<<nc[2]<<endl;
float arbit[3] = {0.1,0.1,0.1};
float* temp1;
temp1 = translate(poi,arbit);
//float* temp2;
//temp2 = cam_space(temp);
cout<<" "<<nc[0]<<" "<<nc[1]<<" "<<nc[2]<<endl;
cout<<" "<<poi[0]<<" "<<poi[1]<<" "<<poi[2]<<endl;
cout<<" "<<temp1[0]<<" "<<temp1[1]<<" "<<temp1[2]<<endl;
return 0;
}
As you can see, I am outputting nc twice. But both the values differ. The second time nc is displayed, it actually shows the temp1 value, and temp1 actually shows garbage values.
Any help?
float* translate(float* p,float* v)
{
float arr1[3];
for(int i=0;i<=2;i++)
arr1[i] = p[i] + v[i];
return arr1;
}// arr1 ceases to exist from this point.
You are returning the reference of a local variable, arr1. It resides on stack and gets de-allocated on the return of function call. But you are holding a reference to it which is yielding you garbage values. Instead new new[] arr1 and return it. Remember to delete[] it when you are done.
You are returning pointers to local variables left right and centre. Those variables go out of scope at the end of the function body, and the result is undefined behaviour.
A nice way of handling array-modifying functions is to pass the array as a parameter:
void modify_me(float arr[]) // or `modify_me(float * arr)`, same thing
{
arr[0] = 0.5;
arr[1] = -2.25;
}
int main()
{
float myarray[2];
modify_me(myarray); // now myarray[0] == 0.5, etc.
// ...
}
Since you're in C++, you could even use template magic:
template <unsigned int N>
void modify_me(float (&arr)[N])
{
static_assert(N == 3, "You're doing it wrong!"); // C++11 feature
arr[0] = /* ... */
}
Now you get a compile-time error if you try to call this with anything that's not an automatic array of size 3.
Instead of returning pointers to local variables you should return values.
Consider this:
struct V3 { float data[3]; }
V3 neg3(V3 v)
{
for(int i=0;i<3;i++)
v.data[i] = -v.data[i];
return v;
}
translate() returns a local pointer (converted from array type). So what temp1 is referring to, doesn't exist after the function translate() returns.
Same is the case with neg3() also.
If you're using C++, then std::vector<float> will solve all such problem.
You could write this:
std::vector<float> translate(const std::vector<float> & p, const std::vector<float> & v)
{
std::vector<float> vf(3);
for(int i=0;i <3;i++)
vf[i] = p[i] + v[i];
return vf; //semantically, it returns a copy of the local object.
}
Similarly, use std::vector whereever you're using float[3]. And don't use global variables.