Pointer to array in function in c++ - c++

I am a beginner to c++. Pointer is quite confusing to me. Especially on how to use it in functions and array. I tried to create a pointer to array in function and just output it. However it keeps giving me the address of the array instead of the value.
void testing(int* arr){
cout << arr << endl;
}
int main()
{
int my_arr[]{ 4,7,1 };
testing(my_arr);
string y;
getline(cin, y);
return 0;
}
I tried using testing(&my_arr); to output value but it give me errors:
argument of type "int (*)[3]" is incompatible with parameter of type
"int *
'void testing(int *)': cannot convert argument 1 from 'int (*)[3]' to 'int *'
Thanks a lot for any help!

To print the values in an array rather than the starting address, you need to use a loop.
#include <iostream>
#include <string>
// note extra param for length of array.
void testing(int* arr, int len){
for (int i = 0; i < len; ++i)
std::cout << arr[i] << " ";
std::cout << "\n";
}
int main()
{
int my_arr[]{ 4,7,1 };
testing(my_arr, 3);
return 0;
}
You can't pass testing(&my_arr) because &my_arr is of type int (*)[] as per the error message you received. That is not the same as int*.

for printing the arrays, you can either use the array index or pointers arithmetic. The test function could also be written as
void testing(int* arr, int len) {
for (int ctr = 0; ctr < len; ctr++) {
std::cout << *(arr + ctr) << std::endl;
}
}
int main()
{
int my_arr[]{ 4,7,1 };
testing(my_arr, 3);
return 0;
}

In testing() you are trying to use arr element without its index.
Here arr is the only base memory address of that memory. To get value from there you have to specify index.
void testing(int* arr, int len)
{
for(int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
}
In main() you can pass a length of an array.
int main()
{
int my_arr[]{ 4,7,1 };
testing(my_arr, sizeof(my_arr) / sizeof(int));
return 0;
}

Related

error: cannot convert ‘int (*)[4]’ to ‘int**’ | SWAPPING ARRAYS

I am trying to write a function that swap two arrays in O(1) time complexity. However, when i try to write the function parameters, I get the error:
error: cannot convert ‘int (*)[4]’ to ‘int**’
Here is my code:
#include <iostream>
using namespace std;
void swap_array_by_ptr(int* a[], int* b[]) {
int* temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int fr[] = {1,2,3,4};
int rv[] = {4,3,2,1};
swap_array_by_ptr(&fr, &rv);
for (int i = 0; i < 4 ; i++) {
cout << fr[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << rv[i] << " ";
}
}
However, when i tried to define the arrays with 'new' command, this works as expected as below:
#include <iostream>
using namespace std;
void swap_array_by_ptr(int** a, int** b) {
int* temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int fr = new int[4]{1,2,3,4};
int rv = new int[4]{4,3,2,1};
swap_array_by_ptr(&fr, &rv);
for (int i = 0; i < 4 ; i++) {
cout << fr[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << rv[i] << " ";
}
}
Is there any way that i can define the arrays with [] method and swap the arrays by sending these arrays with '&array' method ?
As I believe, there must be a way to do that, I only achieve this when I'm trying to do with 'new' method. However, is there any way to swap two arrays in O(1) complexity with sending parameters as
swap_array_by_ptr(&fr, &rv);
?
Thanks for help.
You can not swap two arrays with O( 1 ). You need to swap each pairs of corresponding elements of two arrays.
In the first program
int fr[] = {1,2,3,4};
int rv[] = {4,3,2,1};
swap_array_by_ptr(&fr, &rv);
the expressions &fr and &rv have type int( * )[4] while the corresponding function parameters in fact has the type int **
void swap_array_by_ptr(int* a[], int* b[]) {
after adjusting the parameters having array types to pointers to the array element types by the compiler.
So the compiler issues an error.
You could use standard function std::swap declared in the header <utility> the following way
std::swap( fr, rv );
But in any case its complexity is O( n ).
In the second program there are at least typos. Instead of
int fr = new int[4]{1,2,3,4};
int rv = new int[4]{4,3,2,1};
you have to write
int *fr = new int[4]{1,2,3,4};
int *rv = new int[4]{4,3,2,1};
In this case you are not swapping arrays themselves. That is the arrays will still store their initial values. You are swapping pointers that point to the dynamically allocated arrays.
To be sure that arrays are not swapped consider the following demonstration program.
#include <iostream>
using namespace std;
void swap_array_by_ptr(int** a, int** b) {
int* temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int fr[] = { 1,2,3,4};
int rv[] = {4,3,2,1};
int *p1 = fr;
int *p2 = rv;
swap_array_by_ptr( &p1, &p2 );
for (int i = 0; i < 4 ; i++) {
cout << p1[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << p2[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << fr[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << rv[i] << " ";
}
cout << endl;
}
It is a syntactic quirk inherited from C that a declaration of a function parameter as an array is automatically converted to a declaration as a corresponding pointer. This is not as odd as it might first seem, however, because it dovetails with the automatic conversion of function arguments of array type to corresponding pointers, also inherited from C.*
Thus, this declaration ...
void swap_array_by_ptr(int* a[], int* b[]) {
... is equivalent to this one:
void swap_array_by_ptr(int **a, int **b) {
. But the arguments you are passing do not match. This, for example,
int fr[] = {1,2,3,4};
declares fr as an array of 4 int. If it were passed as a function argument, it would be automatically converted to a pointer to the first element, thus of type int *. Types int * and int ** are not compatible.
On the other hand, what you actually try to pass, &fr is the address of an array 4 int, of type int(*)[4]. This also is incompatible with int **, because arrays are not pointers.
You could write your function like this:
void swap_array_by_ptr(int (*a)[4], int (*b)[4]) {
int temp[4];
memcpy(temp, a, sizeof(a));
memcpy(a, b, sizeof(b));
memcpy(b, temp, sizeof(temp));
}
That would be compatible with the call in your code. Do note, however, that that is specific to array size 4, and you're not really gaining anything useful from that. You could, however, convert it to a template:
template<class T, std::size_t n>
void swap_array(T (*a)[n], T (*b)[n]) {
T temp[n];
memcpy(temp, a, sizeof(a));
memcpy(a, b, sizeof(b));
memcpy(b, temp, sizeof(temp));
}
That handles arrays of any element type and size,** as long as the sizes match. Of course, it scales as O(N) with array size, in both time and auxiliary space.
Such time scaling is unavoidable. To swap two objects you need to read each at least once and write each at least once, and that requires time proportional to the size of the objects. But you could reduce the space overhead to O(1) by swapping the arrays element by element in a loop. That would very likely be slower, but the time complexity would still be O(N).
Of course, you can also use std::swap() on arrays. It is quite similar to the template above, but uses references to the arrays instead of pointers to them.
*This is a specific case of a much more general behavior.
**So long as the temporary array does not turn out to be too large for the stack.
Change the swap_array_by_ptr function from 'swap_array_by_ptr(int** a, int** b)'
to 'swap_array_by_ptr(int* a, int* b)'.
void swap_array_by_ptr(int* a, int* b) {
int* temp = *a;
*a = *b;
*b = temp;
}
here's a link to a similar question: Swapping 2 arrays in C

returning an array address from function in c++ issue

i'm new to programming , this code gives me syntax error in line => int *result = apply_all(array1,5,array2,3) this is the error: expected primary-expression before '}' token|
i'm trying to write function called apply_all expects 2 arrays of integers and their sizes and dynamically allocates a new array of integers whose size is the product of 2 array sizes.
the function should loop through the 2nd array and multiple each element accross each element of array 1 and store the product in newly created array. the function is returning a pointer of to the newly allocated array.
also i wrote a function which is print to display the 1st & 2nd & newly array.
#include <iostream>
using namespace std;
//function prototype
int *apply_all(int *array1 ,int size1,int *array2,int size2);
void print(int *array,int size);
int main()
{
int array1[] {1,2,3,4,5};
int array2[] {10,20,30};
cout << "Array 1:";
print(array1,5);
cout << "Array 2:";
print(array2,3);
int *result = apply_all(array1,5,array2,3);
cout << "Result : ";
print(result,15);
delete [] result;
return 0;
}
int *apply_all(int *array1 ,int size1,int *array2,int size2)
{
int *result {nullptr};
result = new int[size1 * size2];
for (int i{0};i<size2;i++)
for(int j{0};j<size1;j++)
*(result[i*5+j]) = *(array1[i])**(array2[j]);
return result;
}
void print(int *array,int size)
{
for(auto num:array)
cout << num << endl;
}
On this line:
*(result[i*5+j]) = *(array1[i])**(array2[j]);
since result[i*5+j] gives you an int, you are trying to dereference an int, which is not possible.
You just need to do:
result[i*5+j] = array1[i] * array2[j];
Also, in print, your range-for loop won't work with a pointer. You need to do:
for(int i = 0; i < size; ++i)
cout << array[i] << endl;
Also, in apply_all, your loop bounds are incorrect. i needs to go till size1, and j needs to go to size2.
Here's a demo.
Since you are new, a simple work around would be creating an array with buffer space to store your results in and passing the pointer for this into apply_all. You could then write to this array which (being declared in main) should be very easy to access and cause few errors and use a c-string like ending to know when your results are over and to stop printing from the array (c-strings end with a value of 0 so that programs don't read unrelated memory). eg:
int buf[99];
apply_all(array_1, size1, array_2, size2, buf, size3);
for (int x = 0; buf[x] != end of buf var; x++;)
{
print(buf[x])
}
and
apply_all()
{
buf[start-end] = whatever you want;
buf[end + 1] = some variable that won't appear in buffer; //max int size?
}

Function and Array in C++: Unexpected output

I need some help here please.
I just started learning C++ (coming from Python background).
I'm trying to familiarize myself with arrays and functions. Wrote a bunch of functions to do as stated, above each one.
However, the function which is supposed to sum elements in an array and return their sum, seem to be adding 10 to the result, no matter the argument supplied as input. What am I doing wrong please, as I can't seem to find this out. Any help on general layout of my code also would be appreciated.
// WORKING WITH ARRAYS AND FUNCTIONS
#include<iostream>
using namespace std;
// FUNCTION TO INSTANTIATE ARRAY INT OF LENGTH N.
int* array_creator(int n)
{
static int ary_of_ten[10]; //declare array
for (int i=0; i<n; i++) //use loop to fill it up
{
ary_of_ten[i] = i+1;
}
return ary_of_ten;
}
//FUNCTION TO PRINT ARRAY ELEMENTS
void* array_printer(int arr[], int array_lenght)
{
for (int i=0; i<array_lenght-1; i++)
{
cout << arr[i] << " ";
}
cout << arr[array_lenght-1] << endl;
}
//FUNCTION ACCEPTS INT ARRAYS AND RETURNS ARRAY OF SQUARE OF EACH ELEMENT
int* square_array(int *p, int array_length)
{
const int ary_sz(array_length);
static int sqd_values[10];
for (int i=0; i<ary_sz; i++)
{
*(sqd_values + i) = *(p+i) * *(p+i);
}
return sqd_values;
}
//FUNCTION ACCEPTS INT ARRAYS AND RETURNS SUM OF ITS ELEMENTS
int sum_array(int *arry, int array_length)
{
int summation;
for(int i=0; i<array_length; i++)
{
summation += *(arry + i);
}
return summation;
}
int main()
{
cout << sum_array(array_creator(10), 3) << endl;
array_printer(array_creator(10), 10); //print array of 1-10 elements
array_printer(square_array(array_creator(10), 10), 10); //prt arry of sqrd values
return 0;
}
summation shuld be initialized to 0.
int summation=0;

c++ twodimensional array passed to function

I like to pass a two dimensional array to a function to print it.
Here is my code so far. As you can see on the comment it does not compile, because of an incompatible type.
QUESTION
How can I pass the two dimensional array to printIt ?
If I adjust it to printIt(int a(*)[50][50]) I get the another error during compilation, because returning array is not allowed
using namespace std;
void printIt(int a[50][50]);
int main(int args, char *argv[])
{
int a[50][50];
int j = 0;
for (int i = 1; i < 6; i++)
{
a[i][j] = i;
// the same should be printed out inside printIt
cout << " " << a[i][j];
// not compiling
// argument of type int is incompatible with int(*)[50]
printIt(a[i][j]);
}
}
void printIt( int a[50][50] )
{
cout << " " << a[50][50];
}
Given
int a[50][50];
a[i][j] evaluates to an int.
a[i] evaluates to int [50], an array of 50 integers. If used as an argument to a function call, a[i] decays to a int* in most cases. In rare cases it converts to int (&)[50].
If used as an argument to a function call, a decays to int (*)[50] in most cases. In rare cases it converts to int (&)[50][50].
In your case, the function declaration
void printIt(int a[50][50]);
is equivalent to
void printIt(int a[][50]);
and
void printIt(int (*a)[50]);
Hence, using
printIt(a);
is the right method of calling the function.
However
Given the way you are using the argument in printIt, you probably meant to use:
void printIt(int num)
{
cout << " " << num;
}
After that, it OK to use:
printIt(a[i][j]);
in main.
Because a[i][j] in an integer, it is a value. You are passing a value not an double array Your code should look like that :
#include <iostream>
using namespace std;
void printIt(int a)
{
cout << " " << a;
}
int main(int args, char *argv[])
{
int a[50][50];
int j = 0;
for (int i = 1; i < 6; i++)
{
a[i][j] = i;
// the same should be printed out inside printIt
cout << " " << a[i][j];
// not compiling
// argument of type int is incompatible with int(*)[50]
printIt(a[i][j]);
}
}

Error: cannot convert 'int (*)[3]' to 'int (*)[100]' for argument '1' to 'void repl(int (*)[100], int, int)'

Hello im trying to write this program which replace each negative number with -1 and positive with 1
but an error :
[Error] cannot convert 'int ()[3]' to 'int ()[100]' for argument '1' to 'void replace(int (*)[100], int, int)'
what does that mean ??
#include<iostream>
using namespace std;
void replace(int Arr[][100],int rsize, int csize)
{
for(int r=0;r<rsize;r++)
{
for (int c=0;c<csize;c++)
{
if (Arr[r][c]>0) Arr[r][c]=1;
else if (Arr[r][c]<0) Arr[r][c]=-1;
else Arr[r][c]=0;
}
}
}
int main()
{
int a[4][3]={
{2,0,-5},
{-8,-9,0},
{0,5,-6},
{1,2,3}};
replace(a,4,3);
for(int i=0;i<4;i++)
for (int j=0;j<3;j++)
cout<<a[i][j]<<" ";}cout<<endl;
system ("pause");
return 0;
}
You declared function void replace(int Arr[][100],int rsize, int csize) - it expects 2D array, with 'inner' dimension being 100.
Then you pass to it int a[4][3] which has 'inner' dimension 3. Compiler can't convert it. Those dimensions are used to calculate memory position shift when using Arr[x][y] (it is equivalent to *(Arr + x * 100 + y). That's why compiler can't assign array with 3 to array with 100.
If you want your replace to work with any dimension change it to:
void replace(int* Arr,int rsize, int csize). Then use *(Arr + r*csize + c) to access fields instead of Arr[r][c]
Even better solution: you tagged this question as C++ - use C++ library :) - std::vector<std::vector<int> > or std::array (C++11)
Well you declare a function which takes int[][100], then you pass it an int[4][3]. C++ doesn't work like this. In fact, you can't actually pass arrays by value at all; they decay to pointers implicitly.
If you want your function to take arbitrarily sized arrays, you could just make it take pointers to pointers instead:
void replace(int** Arr,int rsize, int csize)
Then you should throw your code away and use std::vector instead:
void replace(std::vector<std::vector<int>> &Arr)
If you want some compile-time constraints on the size of the array, you could do something like:
template <std::size_t X, std::size_t Y>
void replace (std::array<std::array<int,Y>,X>& Arr)
{
static_assert (Y <= 100, "Inner array is too large");
}
The issue is that you're declaring your argument (Arr[][100]) as having 100 elements. But it's not 100 elements, it's three in your code. I'm assuming what you really want is to be able to pass different sized arrays, and specify the array dimensions in the other arguments. If that's the case, you can just declare the array as an int *. So something like the following will work:
#include "stdafx.h"
#include<iostream>
using namespace std;
void replace(int *Arr, int rsize, int csize);
void print(int *Arr, int rsize, int csize);
int _tmain(int argc, _TCHAR* argv[])
{
int a[4][3] = {
{ 2, 0, -5 },
{ -8, -9, 0 },
{ 0, 5, -6 },
{ 1, 2, 3 } };
print((int *)a, 4, 3);
replace((int *)a, 4, 3);
for (int i = 0; i<4; i++)
{
for (int j = 0; j<3; j++)
{
cout << a[i][j] << " ";
}cout << endl;
}
system("pause");
return 0;
}
void replace(int *Arr, int rsize, int csize)
{
for (int r = 0; r<rsize; r++)
{
for (int c = 0; c<csize; c++)
{
int index = (r * (rsize - 1)) + c;
if (Arr[index] > 0)
{
Arr[index] = 1;
}
else if (Arr[index] < 0)
{
Arr[index] = -1;
}
else
{
Arr[index] = 0;
}
}
}
}
void print(int *Arr, int rsize, int csize)
{
char str[256];
for (int r = 0; r<rsize; r++)
{
sprintf(str, "");
for (int c = 0; c<csize; c++)
{
int index = (r * (rsize - 1)) + c;
if (strlen(str) > 0)
{
sprintf(str, "%s, ", str);
}
sprintf(str, "%s%d", str, Arr[index]);
}
cout << str;
cout << endl;
}
}
Don't follow my example of using the unsafe string functions.
The reason this works is that a two-dimensional int array is just a bunch of one dimensional arrays stacked together. So an int[4][3] is just 12 ints in memory. That's functionally identical to an int[12]. If you declare the input to the function as an int *, then it's a pointer to a block of memory that contains ints, doesn't matter how many. So you can avoid the type cast errors you were getting.
There's lots of risk with doing this if you don't make sure your parameters are correct. For example, if you call the same replace function with the same input array, but claim it has 5 rows, then you'll start reading uninitialized memory. (Possibly uninitialized...more accurately, you'll at least be reading memory that is not what you think it is.) Of course, you can do the same thing without the pointer, that's the whole fun part of C++.