I would like to know - is there any way to copy array to a function in C/C++? Not pass it just an address, but create a copy... Like for int value. For example here we send not a copy(((:
void arrayAbs(int array[], int size) {
for ( int i = 0; i < size; i++ ) {
if ( array[i] < 0 ) {
array[i] *= -1;
}
}
}
This is not possible for arrays - at least when the size of the array is not known at compile time. Since you are passing size as a separate parameter, it appears that a solution with a fixed-size array would not work in your situation.
However, you can use std::vector<int> instead. This container will be copied when you pass it by value. As an additional benefit, it knows its size, so passing int size would become unnecessary.
C and C++ arrays are not copyable. But you can use an array-like standard library container type, such as std::array:
template <size_t N>
void arrayAbs(std::array<int, N> a)
{
for ( int i = 0; i < a.size(); i++ ) {
if ( a[i] < 0 ) {
a[i] *= -1;
}
}
}
Here, a is passed by value, so it is a copy of the array passed in by the caller.
You can not do this with arrays. Either arrays are converted to pointers to their first elements when passed to a function (in C and C++) or if the parameter is defined as a reference to an array then the reference is passed. in any case neither copy of an array is created.
In C++ you could use standard class std::array. in this case you indeed could work with a copy of the original array. In C you could use an analogy of std::array in C++ by wrapping an array in a structure.
In C++: Use std::array. In C: Wrap it in a struct.
typedef struct {
int array[10];
} wrapper;
wrapper function(wrapper wrapped_array) {
wrapped_array.array[0] = 42;
return wrapped_array;
}
int main() {
wrapper wa;
wrapper wa2 = function(wa);
}
Related
I am trying to return an array Data Member from one smaller 2D Array Object, and trying to insert the array into a larger 2D array object. But when attempting this, I came into two problems.
First problem is that I want to return the name of the 2D array, but I do not know how to properly syntax to return 2D Array name.
This is what my 2D Array data member looks like
private:
int pieceArray[4][4];
// 2D Smaller Array
and I want to return this array into a function, but this one causes a compiler error:
int Piece::returnPiece()
{
return pieceArray; //not vaild
// return the 2D array name
}
I tired using this return type and it worked:
int Piece::returnPiece()
{
return pieceArray[4][4];
}
But I am unsure if this is what I want, as I want to return the array and all of it's content.
The other problem is the InsertArray() function, where I would put the returnPiece() function in the InsertArray()'s argument.
The problem with the InsertArray() is the argument, heres the code for it:
void Grid::InsertArray( int arr[4][4] ) //Compiler accepts, but does not work
{
for(int i = 0; i < x_ROWS ; ++i)
{
for (int j = 0; j < y_COLUMNS ; ++j)
{
squares[i][j] = arr[i][j];
}
}
}
The problem with this is that it does not accept my returnPiece(), and if i remove the "[4][4]", my compiler does not accept.
Mostly all these are syntax errors, but how do I solve these problems?
Returning the whole pieceArray in returnPiece()
The correct syntax for the argument in InsertArray()
The argument of InsertArray() accepting the returnPiece()
These 3 are the major problems that I need help with, and had the same problem when I attempt to use the pointer pointer method. Does anyone know how to solve these 3 problems?
When passing your array around, you have to decide whether or not you want to make a copy of the array, or if you just want to return a pointer to the array. For returning arrays, you can't (easily) return a copy - you can only return a pointer (or reference in C++). For example:
// Piece::returnPiece is a function taking no arguments and returning a pointer to a
// 4x4 array of integers
int (*Piece::returnPiece(void))[4][4]
{
// return pointer to the array
return &pieceArray;
}
To use it, call it like so:
int (*arrayPtr)[4][4] = myPiece->returnPiece();
int cell = (*arrayPtr)[i][j]; // cell now stores the contents of the (i,j)th element
Note the similarity between the type declaration and using it - the parentheses, dereferencing operator *, and brackets are in the same places.
Your declaration for Grid::InsertArray is correct - it takes one argument, which is a 4x4 array of integers. This is call-by-value: whenever you call it, you make a copy of your 4x4 array, so any modification you make are not reflected in the array passed in. If you instead wanted to use call-by-reference, you could pass a pointer to an array instead:
// InsertArray takes one argument which is a pointer to a 4x4 array of integers
void Grid::InsertArray(int (*arr)[4][4])
{
for(int i = 0; i < x_ROWS; i++)
{
for(int j = 0; j < y_COLUMNS ; j++)
squares[i][j] = (*arr)[i][j];
}
}
These type declarations with pointers to multidimensional arrays can get really confusing fast. I recommend making a typedef for it like so:
// Declare IntArray4x4Ptr to be a pointer to a 4x4 array of ints
typedef int (*IntArray4x4Ptr)[4][4];
Then you can declare your functions much more readable:
IntArray4x4Ptr Piece::returnPiece(void) { ... }
void Grid::InsertArray(IntArray4x4Ptr arr) { ... }
You can also use the cdecl program to help decipher complicated C/C++ types.
It seems like you need to read up more on pointers in C++ and on pass by reference vs. pass by value.
Your returnPiece method is defined as returning the value of a single cell. Given the index (e.g., [4][4]) you return a copy of the contents of that cell, so you won't be able to change it, or more correctly, changing it would change the copy.
I'm sure someone will give you the correct syntax, but I would really recommend learning this stuff since otherwise you may use the code that you do get incorrectly.
Here is how I would do it:
class Array {
public:
Array() {
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
(*this)(i, j) = 0;
}
}
}
int &operator()(int i, int j)
{
return pieceArray[i][j];
}
private:
int pieceArray[4][4];
};
You can then do something like:
Array x; // create 4x4 array
x(1, 2) = 3; // modify element
Trouble with Adam Rosenfield's arrayPtr in that Piece::pieceArray can change out from under you. (Copy-by-reference vs Copy-by-value.)
Copy-by-value is inefficient. But if you really want to do it, just cheat:
struct FOO { int piece [4][4]; };
FOO Piece::returnPiece()
{
FOO f;
memcpy( f.piece, pieceArray, sizeof(pieceArray) );
return f;
}
void Grid::InsertArray( const FOO & theFoo )
{
// use theFoo.piece[i][j]
}
Of course, a better, more Object-Oriented solution, would be to have returnPiece() create and return a Piece or Array object. (As Juan suggested...)
I have a program in which the object array's size is determined during the runtime, so it's dynamically allocated (2D array, read from file). I also have a function which takes these objects as parameters. The problem is if the function parameters are 2D arrays that are passed to the function the 2nd dimension should be determined. However, in my case it is not. My program won't compile since the prototype does not have the 2nd dimension mentioned.
Here is what I tried:
//global variables
int residentCount=0;
int hospitalCount=0;
Resident** residents;
Hospital** hospitals;
bool readFromFiles(const string, const string, const int); //sizes are determined in here
void print(Hospital*[hospitalCount], Resident*[residentCount]); //declaration issue
How can I solve this?
You are programming in C++, so you should:
avoid dynamic allocation and handling memory management on your own always when it's possible
take advantage of objects with automatic storage duration instead, follow RAII idiom
avoid using C-style arrays and actually avoid writing C code that is just compilable as C++ in general
use great features that C++ provides, especially those bundled within STL
avoid using global variables when local equivalents suffice
This is how it could look like:
typedef std::vector<Resident> Residents;
typedef std::vector<Hospital> Hospitals;
// passing by const reference:
void print(const std::vector<Hospitals>&, const std::vector<Residents>&);
int main()
{
std::vector<Hospitals> hospitals;
std::vector<Residents> residents;
...
} // <-- lifetime of automatics declared within main ends here
Note that hospitals and residents will be objects with automatic storage duration, usable in similar manner than your C-style 2D arrays. When the execution goes out of the scope of main, these vectors are destructed and memory, where their elements (including elements of their elements) resided before is automatically cleaned up.
Also note that I suggest you to pass by const reference, i.e. const std::vector<Hospitals>&, which prevents the copy of passed object being created and const keyword explicitely tells to the caller: "Although you pass this object by reference, I will not change it."
Just pass a pointer to the first element of the array and the dimensions, that's enough, example:
void PrintHospitals(Hospital* Hospitals, size_t HospitalRows, size_t HospitalColumns)
{
size_t i, j;
Hospital* hospital;
for (i = 0; i < HospitalRows; i++)
for (j = 0; j < HospitalColumns; j++)
{
hospital = Hospitals + HospitalColumns * i + j;
PrintHospital(hospital);
}
}
int main()
{
Hospital hospitals[10][20];
// ...
PrintHospitals(&hospitals[0][0], 10, 20);
return 0;
}
Here is a solution using templates to create two-dimensional array wrappers for existing data:
template<typename T>
class Array2d {
public:
int Rows;
int Cols;
T** Data;
Array2d(int rows, int cols, T** data) :
Rows(rows),
Cols(cols),
Data(data) { }
};
void print(Array2d<Hospital> h, Array2d<Resident> r) {
for (int i = 0; i < h.Rows; i++) {
for (int j = 0; j < h.Cols; j++) {
//Print Data[i][j] element here
}
}
// Other print code
}
int main()
{
Resident** residents;
Hospital** hospitals;
//Init data arrays
Array2d<Hospital> h(10, 10, hospitals);
Array2d<Resident> r(10, 10, residents);
print(h, r);
}
I want to create a function that takes an integer as it's parameter and returns an array in C++. This is the pseudo-code I had in mind:
function returnarray(integer i)
{
integer intarr[i];
for (integer j = 0; j < i; j++) { intarr[j] = j; }
return intarr;
}
I tried the common way of declaring returnarray as function* returning a pointer, but then I can't take an integer as my parameter. I also can't assign j to intarr[j]. I'd really like to avoid making a pointer to an int just so I could use the parameter.
Is there any way of doing this and being able to assign j to intarr[j] without making a pointer for it?
EDIT:
forgot to write that I want to avoid vectors. I use them only if I really have to! (my reasons are mine).
Thanks :D
You can't return a stack-allocated array- it's going to go out of scope and the memory deallocated. In addition, C++ does not allow stack-allocated variable-length arrays. You should use a std::vector.
std::vector<int> returnarray(int i) {
std::vector<int> ret(i);
for(int j = 0; j < i; j++) ret[j] = j;
return ret;
}
your code isn't even near valid c++ so i assume you're total beginner
use std::vector
#include <vector>
std::vector<int> yourFunction( int n )
{
std::vector<int> result;
for( int i = 0; i < n; ++i )
{
result.push_back( i );
}
return result;
}
Disclaimer: code untouched by compilers' hands.
Cheers & hth.,
Two remarks, before using the excellent #DeadMG 's solution:
1) You never want to avoid vectors. If v is a vector, and you really want a pointer, you can always have a pointer to the first element by writing &v[0].
2) You can't return an array. You will return a pointer to a fresh memory zone that you'll have to delete once finished with it. Vectors are only arrays with an automatic deletion facility, so you won't leak memory.
You need to use dynamic memory. Something like this
int* returnArray(int size) {
int* array = new int[size];
for(int i = 0; i < size; ++i)
array[i] = i;
return array;
}
Not that I'd particularly recommend this approach in general, but you can use templates to do this without resorting to dynamic memory allocation. Unfortunately you can't return arrays from functions, so you'd need to return a struct with the array inside.
template <int N>
struct int_array_type {
int ints[N];
};
template <int N>
int_array_type<N> returnarray() {
int_array_type<N> a;
for (int i = 0; i < N; ++i)
a.ints[i] = i;
return a;
}
...
int_array_type<10> u = returnarray<10>();
std::copy(u.ints, u.ints+sizeof(u.ints)/sizeof(u.ints[0]),
std::ostream_iterator<int>(std::cout, "\n"));
I have got a small problem with 1D array in c++. I have got a function line this:
void func(int (&array)[???])
{
// some math here;
"for" loop {
array[i] = something;
}
}
I call the functions somewhere in the code, and before I made math I'm not able to know dimension of the array. The array goes to the function as a reference!, because I need it in the main() function. How I can allocate array like this?, so array with ?? dimension goes to the function as reference then I have to put the dimension and write to it some values.
Since you're using C++, why not use a std::vector<> instead?
Other have mentioned that you should use std::vector in C++ and they are right.
But you can make your code work by making func a function template.
template <typename T, size_t N>
void func(T (&array)[N])
{
// some math here;
"for" loop {
array[i] = something;
}
}
Use a pointer, not a reference:
void func(int *a, int N);
Or, easier, use a vector:
void func(std::vector<int> &a);
Vectors can be allocated by simply saying
std::vector<int> a(10);
The number of elements can be retrieved using a.size().
If the array you pass to func is a stack array, and not a pointer, you can retain its size by using a function template:
template <class T, size_t N>
void func(T(&array)[N])
{
size_t array_length = N; // or just use N directly
}
int main()
{
int array[4];
func(array);
}
That said, as others have already pointed out, std::vector is probably the best solution here.
As well as vector which has been suggested you could possibly use valarray which is also part of STL and is intended specificially to handle mathematical collections.
What you have to realize, is that arrays are pointers. A definition like int array[5] will allocate space for 5 integers on the stack and array will be the address of the first value. Thus, to access the first value in the array, you can write
array[0] or *array (which is the same as *(array + 0))
In the same way to retrieve the address of the third element, you can write
&array[2] or array + 2
Since arrays are pointers, you don't have to worry about the runtime size of your array if you would like to pass it to a function, simply pass it as a pointer:
void func(int *array)
{
int size;
//compute size of the array
for (int i = 0; i < size; ++i)
{
//do whatever you want with array[i]
}
}
I am trying to return an array Data Member from one smaller 2D Array Object, and trying to insert the array into a larger 2D array object. But when attempting this, I came into two problems.
First problem is that I want to return the name of the 2D array, but I do not know how to properly syntax to return 2D Array name.
This is what my 2D Array data member looks like
private:
int pieceArray[4][4];
// 2D Smaller Array
and I want to return this array into a function, but this one causes a compiler error:
int Piece::returnPiece()
{
return pieceArray; //not vaild
// return the 2D array name
}
I tired using this return type and it worked:
int Piece::returnPiece()
{
return pieceArray[4][4];
}
But I am unsure if this is what I want, as I want to return the array and all of it's content.
The other problem is the InsertArray() function, where I would put the returnPiece() function in the InsertArray()'s argument.
The problem with the InsertArray() is the argument, heres the code for it:
void Grid::InsertArray( int arr[4][4] ) //Compiler accepts, but does not work
{
for(int i = 0; i < x_ROWS ; ++i)
{
for (int j = 0; j < y_COLUMNS ; ++j)
{
squares[i][j] = arr[i][j];
}
}
}
The problem with this is that it does not accept my returnPiece(), and if i remove the "[4][4]", my compiler does not accept.
Mostly all these are syntax errors, but how do I solve these problems?
Returning the whole pieceArray in returnPiece()
The correct syntax for the argument in InsertArray()
The argument of InsertArray() accepting the returnPiece()
These 3 are the major problems that I need help with, and had the same problem when I attempt to use the pointer pointer method. Does anyone know how to solve these 3 problems?
When passing your array around, you have to decide whether or not you want to make a copy of the array, or if you just want to return a pointer to the array. For returning arrays, you can't (easily) return a copy - you can only return a pointer (or reference in C++). For example:
// Piece::returnPiece is a function taking no arguments and returning a pointer to a
// 4x4 array of integers
int (*Piece::returnPiece(void))[4][4]
{
// return pointer to the array
return &pieceArray;
}
To use it, call it like so:
int (*arrayPtr)[4][4] = myPiece->returnPiece();
int cell = (*arrayPtr)[i][j]; // cell now stores the contents of the (i,j)th element
Note the similarity between the type declaration and using it - the parentheses, dereferencing operator *, and brackets are in the same places.
Your declaration for Grid::InsertArray is correct - it takes one argument, which is a 4x4 array of integers. This is call-by-value: whenever you call it, you make a copy of your 4x4 array, so any modification you make are not reflected in the array passed in. If you instead wanted to use call-by-reference, you could pass a pointer to an array instead:
// InsertArray takes one argument which is a pointer to a 4x4 array of integers
void Grid::InsertArray(int (*arr)[4][4])
{
for(int i = 0; i < x_ROWS; i++)
{
for(int j = 0; j < y_COLUMNS ; j++)
squares[i][j] = (*arr)[i][j];
}
}
These type declarations with pointers to multidimensional arrays can get really confusing fast. I recommend making a typedef for it like so:
// Declare IntArray4x4Ptr to be a pointer to a 4x4 array of ints
typedef int (*IntArray4x4Ptr)[4][4];
Then you can declare your functions much more readable:
IntArray4x4Ptr Piece::returnPiece(void) { ... }
void Grid::InsertArray(IntArray4x4Ptr arr) { ... }
You can also use the cdecl program to help decipher complicated C/C++ types.
It seems like you need to read up more on pointers in C++ and on pass by reference vs. pass by value.
Your returnPiece method is defined as returning the value of a single cell. Given the index (e.g., [4][4]) you return a copy of the contents of that cell, so you won't be able to change it, or more correctly, changing it would change the copy.
I'm sure someone will give you the correct syntax, but I would really recommend learning this stuff since otherwise you may use the code that you do get incorrectly.
Here is how I would do it:
class Array {
public:
Array() {
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
(*this)(i, j) = 0;
}
}
}
int &operator()(int i, int j)
{
return pieceArray[i][j];
}
private:
int pieceArray[4][4];
};
You can then do something like:
Array x; // create 4x4 array
x(1, 2) = 3; // modify element
Trouble with Adam Rosenfield's arrayPtr in that Piece::pieceArray can change out from under you. (Copy-by-reference vs Copy-by-value.)
Copy-by-value is inefficient. But if you really want to do it, just cheat:
struct FOO { int piece [4][4]; };
FOO Piece::returnPiece()
{
FOO f;
memcpy( f.piece, pieceArray, sizeof(pieceArray) );
return f;
}
void Grid::InsertArray( const FOO & theFoo )
{
// use theFoo.piece[i][j]
}
Of course, a better, more Object-Oriented solution, would be to have returnPiece() create and return a Piece or Array object. (As Juan suggested...)