Passing and returning 2d arrays in C++ - c++

So I am new to c++ and I have written this piece of c++ code.
#include <iostream>
using namespace std;
int** mat_mult(int mat1[2][2], int mat2[2][2]){
int mat3[2][2] = {{0,0},{0,0}};
for(int i(0);i<2;i++){
for(int j(0);j<2;j++){
for(int k(0);k<2;k++){
mat3[i][j] += mat1[i][k]*mat2[k][j];
}
}
}
return mat3;
}
int** mat_pow(int mat[2][2], int n){
int mat1[2][2] = {{1,0},{0,1}};
while(n){
if(n%2==1){
mat1 = mat_mult(mat, mat1);
}
mat = mat_mult(mat,mat);
n >>= 1;
}
return mat1;
}
int specialFib(int n){
int mat[2][2] = {{0,1},{2,1}};
mat = mat_pow(mat,n);
return (mat[0][0]*2 + mat[0][1]);
}
int main(){
cout << specialFib(3) << endl;
return 0;
}
But compiling this gives me this error,
prog.cpp: In function 'int** mat_mult(int (*)[2], int (*)[2])':
prog.cpp:13: error: cannot convert 'int (*)[2]' to 'int**' in return
prog.cpp: In function 'int** mat_pow(int (*)[2], int)':
prog.cpp:20: error: incompatible types in assignment of 'int**' to 'int [2][2]'
prog.cpp:22: error: cannot convert 'int**' to 'int (*)[2]' in assignment
prog.cpp:25: error: cannot convert 'int (*)[2]' to 'int**' in return
prog.cpp: In function 'int specialFib(int)':
prog.cpp:30: error: incompatible types in assignment of 'int**' to 'int [2][2]'
I tried to find any solution, but no luck. :(

int **mat3 = {{0,0},{0,0}};
This makes mat3 a pointer to a pointer to an integer. You can initialize it to any pointer to a pointer to an integer you want. But {{0,0},{0,0}} is an array, not a pointer to a pointer to an integer.
Perhaps you want:
int mat3[2][2] ...

If you want to dynamically allocate your 2d array then your code should look like that:
int** mat3 = new int*[2];
for(int i = 0; i < 2; ++i)
mat3[i] = new int[2];
and then deallocation:
for(int i = 0; i < 2; ++i) {
delete [] mat3[i];
}
delete [] mat3;
also you must manually initialize its values
as in other answers, I would never use such dynamic arrays, but vector of vectors

You tagged this question C++ so use C++!
You can either use std::array<std::array<int,Xsize>, Ysixe>> if you know both sizes at compile time or std::vector<std::vector<int>> otherwise.

In C++, arrays are very special collection facilities. You should definitely read more about standard container classes and then write everything new from scratch -- Trust me, it will save time! :)
Objects of standard container classes can be returned from a function in the same easy way as primitive types (like int or double).
std::vector<std::vector<int> > GetInts()
{
// ...
return v;
}
Your problem will simply disappear.
Pointers and arrays imply low-level memory management; that is certainly not beginners stuff!

Related

For-loop saying - ERROR Member reference base type 'int [13]' is not a structure or union

What is the problem with my for-loop? It is inside a helper function but the error "Member reference base type 'int [13]' is not a structure or union" is happening across my code. The 'int [13] changes to int[10] when I am using a 10 integer array, so I assume it is a problem there. Here are two examples:
int newisbn13[13];
newisbn13[0] = 9;
newisbn13[1] = 7;
newisbn13[2] = 8;
for (int p = 3; p < newisbn13.length() - 1; p++)
{
newisbn13[p] = isbn10[p-3];
}
ERROR: Member reference base type 'int [13]' is not a structure or union
Also:
int calc_check_digit_13(int input[], int size) {
int sum = 0;
for (int i = 0; i < input.length(); i++)
{
int tempnum = 0;
if (i % 2 == 0)
{
tempnum = input[i];
}
else if (i % 2 == 1)
{
tempnum = input[i] * 3;
}
sum = tempnum + sum;
}
etc. etc. etc.
}
ERROR: Member reference base type 'int *' is not a structure or union
What is causing this error throughout my code? Thank you for your help.
newisbn13 is an array and in contrast to other languages like C# or Java it does not know its size.
You need to use sizeof(newisbn13) instead.
Or since c++17 you can use std::size(newisbn13).
However this will not work for calc_check_digit_13. Because input will decay to a pointer and neither sizeof nor std::size will work there. But probably the parameter size is what you want to use.
for (int i = 0; i < size; i++) {...}
For your first block of code, you make a call to a non-existent member function of type int. In C++, int is a primitive type and has no member functions or member variables.
For the second block, you're calling the same function but on a pointer to an array of ints, so the type is int * and not int[13], but its pretty much the exact same problem.
As churill pointed out, you can use sizeof(int[]) or std::size(int[]) to find the number of elements in the array. If you need a container for integers, I would recommend using std::vector<int> to manage your ints. This template class has tons of quality-of-life methods such as size() that can assist with what you might want to do.

cannot cast int *(*)[] to int(**)[]

int main()
{
int j;
std::cin >> i >> j;
int (**ptr)[1];
ptr = new (int*[i][1]);//error
for (int index = 0;index < i;++index)
ptr[index] = new (int[j][1]);
}
I have a compiler error.
Then, how can I allocate int(**)[]?
Problem.
Original code except that I've added the missing #include directive – to avoid wrong guesses about your code, and irrelevant issues being discussed, please do include everything in posted code:
#include <iostream>
int main()
{
int j;
std::cin >> i >> j;
int (**ptr)[1];
ptr = new (int*[i][1]);//error
for (int index = 0;index < i;++index)
ptr[index] = new (int[j][1]);
}
Compiling with MinGW g++ 5.1.0:
C:\my\forums\so\116> g++ --version | find "++"
g++ (tdm64-1) 5.1.0
C:\my\forums\so\116> g++ original.cpp
original.cpp: In function 'int main()':
original.cpp:5:17: error: 'i' was not declared in this scope
std::cin >> i >> j;
^
original.cpp:9:35: error: ISO C++ forbids variable length array [-Wvla]
ptr[index] = new (int[j][1]);
^
original.cpp:9:36: error: non-constant array new length must be specified without parentheses around the type-id [-Wvla]
ptr[index] = new (int[j][1]);
^
C:\my\forums\so\116> _
That compiler detected the following problems:
Missing declaration of variable i.
Inadvertent use of C99 variable length array, VLA, due to syntactical error.
Compiling with Visual C++ 2015 update 2:
C:\my\forums\so\116> cl /nologo- 2>&1 | find "++"
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23725 for x86
C:\my\forums\so\116> cl original.cpp
original.cpp
original.cpp(5): error C2065: 'i': undeclared identifier
original.cpp(7): error C2065: 'i': undeclared identifier
original.cpp(7): error C2440: '=': cannot convert from 'int *(*)[1]' to 'int (**)[1]'
original.cpp(7): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
original.cpp(8): error C2065: 'i': undeclared identifier
C:\my\forums\so\116> _
This compiler doesn't support C99 VLAs, and so instead diagnoses
Incompatible types in pointer assignment.
Apparently this is the error message the OP is concerned about, but the OP reported it as
” cannot cast int ()[] to int(**)[]
which is meaningless because one can indeed cast between data pointer types.
So,
The error description in the question is incorrect.
The code has issues (lacking include, lacking variable declaration) in addition to the error singled out by the OP.
It's unclear what the code is meant to do, except in a very abstract sense that allowed advice such as “use a std::vector”.
However, the code snippet
for (int index = 0;index < i;++index)
ptr[index] = new (int[j][1]);
strongly indicates that this is an attempt to do a dynamic size matrix (2D array) of int values, with dimensions specified by the user, and I assume that in the following.
Fix of the original code.
It often helps to name things. In this case, for clarity, we can name the int* type as Int_array_ptr. That indicates the intended usage: not as a pointer to a single int, but as a pointer to the first item of an array of int, i.e. as a pointer to the array.
#include <iostream>
int main()
{
int n_rows;
int n_columns;
std::cin >> n_rows >> n_columns;
using Int_array_ptr = int*;
Int_array_ptr* matrix;
matrix = new Int_array_ptr[n_rows]; // An array of `n_rows` pointers.
for( int i = 0; i < n_rows; ++i )
{
matrix[i] = new int[n_columns](); // The `()` adds zero-initialization.
}
// At this point one can use it like `matrix[row][column] = 42`.
}
The resulting structure is called a jagged array, because it permits the column vectors to be of different lengths (here they're all the same length).
How to do a matrix in general.
A good alternative to matrix-as-jagged-array is to use a single contiguous 1D array as storage, and just provide 2D indexing into this array.
A good to way to manage an array's storage is to use a std::vector.
And a good way to encapsulate an indexing operation plus other array stuff (or most any set of related operations on a common state) is to define a class.
So, this strongly suggests to define a class that provides a 2D indexing operation on a single 1D array whose storage is managed by a std::vector.
The indexing would ideally be via operator[], but as a member operation it can only take 1 argument. And it's a bit of a bother to write e.g. matrix[Location(3,58)] instead of the ideal matrix[3,58] (which would be parsed as use of a comma expression). So, typically operator(), the function call operator, is used instead of [].
It's possible to instead support the notation matrix[3][58], but let's choose the conceptually simpler implementation of operator():
#include <iostream>
#include <vector>
#include <stdlib.h> // EXIT_FAILURE
using namespace std;
class Matrix
{
private:
vector<int> items_;
int n_columns_;
auto index_of( int const row, int const col ) const
-> int
{ return row*n_columns_ + col; }
public:
auto operator()( int const row, int const col )
-> int&
{ return items_[index_of( row, col )]; }
auto operator()( int const row, int const col ) const
-> int
{ return items_[index_of( row, col )]; }
Matrix( int const n_rows, int const n_columns )
: items_( n_rows*n_columns )
, n_columns_( n_columns )
{}
};
auto main() -> int
{
int n_rows;
int n_columns;
std::cin >> n_rows >> n_columns;
if( cin.fail() ) { return EXIT_FAILURE; }
Matrix matrix( n_rows, n_columns );
// At this point one can use it like `matrix( row, column ) = 42`.
}
This is far more code than the original, but
it's reusable code, which saves work,
it's more robust code, with the difficult things (memory management) automated, and
it can even be more efficient, because it manages with a single dynamic allocation.
Seems like you want to allocate 2-D array. So the allocation should be done as:
int i, j; // Initialize some value to i, j.
....
int **ptr = new int*[i];
for(int k = 0; k < i; k++) {
ptr[k] = new int[j];
}
This will make a 2-D array that has i rows and j columns.
You are trying to allocate an array of int (*)[1] objects. You've already noticed that syntax like new int(*)[1] doesn't work because it is parsed as new int followed by the function call operator, so you have to use the new(T) form.
Also, int *[i][1] is not right, because int * is pointer-to-int. Much like you did in int (**ptr)[1], you have to use parentheses to break the * from the int.
So the right syntax for this would be new( int (*[i])[1] ). But unfortunately, the new(T) form is not allowed to contain non-constant expressions inside the parentheses!
Technical information: There is a dedicated grammar (C++14 [dcl.name]/1) for the cases sizeof(T), alignof(T), new(T) and typeid(T) and casts; and it only permits square brackets to be empty or contain a constant-expression inside the square brackets. There is another separate grammar for the new T case ([expr.new]/1) (which knows about [] but not (), and allows non-constant expressions), and both of these are separate to the grammar for parsing declarators in other situations.
So the only solution to this (while retaining the type of ptr) is to use a typedef:
typedef int Arr1[1];
ptr = new Arr1 *[i];
Each row is:
ptr[index] = new int[j][1]; // or "new Arr1[j];"
you have allocate an pointer array, and then each element(pointer) points to an array like
int i = 20, j = 40;
int** ptr = new int*[i];
for (int a = 0; a < i; a++) {
ptr[a] = new int[j];
// ...
delete [] ptr[a];
}
delete [] ptr;
EDIT
back to your code
when you define a type E as int[1];
int j, i;
std::cin >> i >> j;
typedef int E[1];
E **ptr; // int (**ptr)[1];
ptr = new E*[i]; // ptr = new (int*[i][1]);//error
for (int index = 0;index < i;++index)
ptr[index] = new E[j]; // ptr[index] = new (int[j][1]);
so just a pointer to pointer of integer, not like what you said

Instantiation of array class of size unknown at compile time

Below is a small script that prints the sums of the numbers 1 to n, for n = 1,...,20.
#include <iostream>
#include <array>
using namespace std;
int test(int n)
{
array<int,n> myArray;
for (int iii = 0; iii < n; iii++)
myArray[iii] = iii+1;
int nSum;
for (int iii = 0; iii < n; iii++)
nSum += myArray[iii];
return nSum;
}
int main()
{
for (int n = 1; n <= 20; n++)
cout << test(n) << endl;
return 0;
}
Of course, this won't compile:
Main.cpp: In function ‘int test(long unsigned int)’:
Main.cpp:9:13: error: ‘n’ is not a constant expression
array<int,n> myArray;
^
Main.cpp:9:13: note: in template argument for type ‘long unsigned int’
Main.cpp:9:22: error: invalid type in declaration before ‘;’ token
array<int,n> myArray;
^
Main.cpp:11:26: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int iii = 0; iii < n; iii++)
^
Main.cpp:12:14: error: invalid types ‘int[int]’ for array subscript
myArray[iii] = iii+1;
^
Main.cpp:16:26: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int iii = 0; iii < n; iii++)
^
Main.cpp:17:22: error: invalid types ‘int[int]’ for array subscript
nSum += myArray[iii];
^
make: *** [Main.o] Error 1
The problem seems to be (among other things) that n isn't a constant expression, and I get why that is a problem, but I have no idea how to solve it.
I know how to instantiate "regular" arrays with the new function, but I don't understand how it is possible with the array class.
How do I make the test function treat n as a constant?
You have basically two options.
As you already mentioned, std::array needs a compile-time size. So make it known at compile-time! This can be done by converting it to a template parameter.
Change
int test(int n)
{
.
.
.
}
to
template<int n>
int test()
{
.
.
.
}
The problem is that it then has to be called with test<n>() instead of test(n) and this again requires the n in the caller code to be known at compile-time, too, which is not the case with a for-loop. If you know your loop's upper bound during compile-time (like in your current code snippet), it can be done, but it's a bit complicated. And if it's not known, i.e. a user input, you can't use this solution at all.
So this is not a good option here.
Don't use std::array but a container type which doesn't require the size at compile-time but during runtime. A heap-allocated raw array (new int[n]), as you mentioned, is an option, but it's not very C++-ish. Use std::vector instead!
For this, simply change
array<int,n> myArray;
to
vector<int> myArray(n);
PS. In the future, there probably will be std::dynarray (proposed container type) which fits exactly that purpose a bit better than std::vector currently does. It's reflecting the purpose of new int[n] where n is known at runtime but constant during the lifetime of the array, filling the gap between std::array and std::vector. Yet in almost all cases std::vector will do just fine!
You can use a vector instead;
#include <vector>
vector<int> myArray (n); // n zero-initialized elements
use the operator[] like you are using the array.

Difference between int * array and int array[] in a function parameter

I have seen that the array values ​​will change if the function parameter is "int arr[]" or "int * arr". Where is the difference?
int array[]:
void myFunction(int arr[], int size) {
for (int i = 0; i < size; ++i)
arr[i] = 1;
}
int * array:
void myFunction(int * arr, int size) {
for (int i = 0; i < size; ++i)
arr[i] = 1;
}
Both functions change the array values.
int main(){
int array[3];
array[0] = 0;
array[1] = 0;
array[2] = 0;
myFunction(array, 3);
return 0;
}
There is no difference. Both functions types (after adjustment) are "function taking a pointer to int and an int, returning void." This is just a syntactic quirk of C++: the outermost [] in a function parameter of non-reference type is synonymous with *.
Different ways to express the same thing.You are simply passing an array to functions by pointer.
when you pass an array to functions it implicitly passes it by pointer. because if there is many elements in array pass by value copying it is a Huge overhead. even-though it looks different its same.
you can't use both functions at same time. if you do its compile time error
error: redefinition of 'void myFunction(int*, int)'
it is already defined.
There are no difference. In fact, a declaration of an array return allawys a pointer. Only, when you specify in the declaration that the variable is an array (ie. with []), it is not necessary to specify that it will be a pointer, because this is made implicitly. But when you do not specify this, you must declare it as a pointer if you went affect it a table variable, or a result of "new []". The use of pointers of table has an interest only for a dynamic allocation, when the array size is not known on design-time.

C++, error invalid conversion from `int*' to `int'

I have the following C++ code:
#include <iostream>
using namespace std;
int main(){
}
int findH(int positionH[]){
return positionH; //error happens here.
}
The compiler throws an error:
invalid conversion from `int*' to `int'
What does this error mean?
positionH[] is an array, and its return type is int.
The compiler will not let you do that. Either make the parameter an int:
int findH(int positionH){
return positionH;
}
Or make the return type a pointer to an int:
int* findH(int positionH[]){
return positionH;
}
Or convert the array to an integer before return:
int findH(int positionH[]){
return positionH[0];
}
This line is invalid C++ (and invalid C too, which your code appears to be written in):
int bla[2] = findH(field, positionH);
bla is an array of 2 elements and cannot be initialised that way. findH returns int.
This error is coming while you are trying to do:
int *p =10;
that means you are assigning int value to pointertoint *p .
But pointer is storing address that means *p is taking 10 as address.
So
just do:
int i=10;
int *p=&i;
or
p=&i;
it will not give any error.
The error was caused because you returned a pointer and the compiler is expecting a int.
There is a very BIG difference between int * and int.
Also why are you returning positionH, arrays are passed by reference, there is no need to return it.
Better code would be
void option1(char** field, int[])
{
int findH(char **, int[]);
int positionH[2];
findH(field, positionH);
//positionH passed by reference, no need to return it
}
void findH(char **field, int positionH[])
{
for(int n = 0;n < 14 ; n++)
{
for(int m = 0; m < 14; m++)
{
if(field[m][n] == 'H')
{
positionH[0] = n;
positionH[1] = m;
}
}
}
}