Point one array value to another value of the same array - C++ - c++

Imagine I have the following code:
int* firstArray[4];
fill_n(firstArray, 4, 0);
//firstArray values are: 0, 0, 0, 0
int* secondArray[4];
fill_n(secondArray, 4, 1);
//secondArray values are: 1, 1, 1, 1
Would there be a way to link the first value of firstArray to the first value of secondArray so that if I do:
secondArray[0] = 20;
//secondArray values would be: 20, 1, 1, 1 (because I just changed it)
//firstArray values would be: 20, 0, 0, 0 (because it's pointing to the value I just changed)
As far as I've tested and researched I can't do something along those lines.
P.S.: This is to create a Samurai Sudoku (in which some chunks of numbers are shared), so when I modify a value that 2 sudokus share it would be updated in both.

You are mixing up concepts. You don't even need to declare a second array just do this:
int myarray [20];
int * mypointer;
mypointer = myarray;
// then you can use both mypointer[] myarray[] the same way to access array elements
The concept of arrays is related to that of pointers. In fact, arrays work very much like pointers to their first elements, and, actually, an array can always be implicitly converted to the pointer of the proper type.
The [] operator in arrays acts the same way as a as a de-referencing operator, but with the added ability of automatically advancing the pointer according to the data type. This is why Array[1] references the same value as *(Array+1)
however you are declaring an arrays of pointers to integers, which means that you can't "store" integer values in this array, but rather store the value of the address where the integer is located.
Additionally when you declare an array you are essentially declaring a constant pointer, so you can not "steal" it and make it pointer to another location.
Study this Code and it's output (RUN THIS CODE)
#include <iostream>
using namespace std;
void printarray (int arg[], int length) {
for (int n=0; n<length; ++n)
cout << arg[n] << ' ';
cout << '\n';
}
int main ()
{
int first[] = {5, 10, 15, 14, 13};
printarray (first,3);
// int* third[] = {1,1,1}; Not accepted because int is not int*
// storing the addresses of first as pointers in 2 different arrays
int* third[] = {first,first+2,first+3};
int* forth[] = {first,first+2,first+3};
// the memory adress where the pointers TO first is stored
cout << third << endl;
cout << forth << endl;
cout << &third << endl;
cout << &forth << endl;
// the memory adress where the pointer TO the value of first[0] is stored
cout << *third << endl;
cout << *forth << endl;
cout << third[0] << endl;
cout << forth[0] << endl;
// you are defrencing twice
cout << *third[0] << endl;
cout << *forth[0] << endl;
cout << **third << endl;
cout << **forth << endl;
// assign once
first[0] = 77;
// applys to all values
cout << first[0] << endl;
cout << *third[0] << endl;
cout << *forth[0] << endl;
// better yet declare a int* and use it same way your array
int* second;
second = first;
cout << first[0] << endl;
cout << second[0] << endl;
// again change value and the change is reflected everywhere
second[0] = 99;
cout << first[0] << endl;
cout << second[0] << endl;
cout << *third[0] << endl;
cout << *forth[0] << endl;
}
OUTPUT
5 10 15
0x786378c0b860
0x786378c0b880
0x786378c0b860
0x786378c0b880
0x786378c0b840
0x786378c0b840
0x786378c0b840
0x786378c0b840
5
5
5
5
77
77
77
77
77
99
99
99
99

Store int**s instead of int*s this way you can have each entry in the array point to the same address.
You would initialize the first element lets say as:
int *first = new int;
*first = 1;
firstArray[0] = first;
secondArray[0] = first;
Then if you write *first = 20; both arrays will be updated.
There is a problem with your question that you initialize first to 0 and then to 1. If they were the same address then setting to 1 would overwrite the setting to 0.

You question is not self coherent :
you write int* secondArray[4]; : secondArray is an array of 4 pointers to int
you write secondArray[0] = 20 : here secondArray is an array of 4 int values
Hyp 1 : arrays of 4 int values
&secondArray[1] is &secondArray[0] + 1. Full stop. That the way arrays work in C++. In that case if secondArray[0] is the same as firstArray[0] then the 2 arrays are at same address and are in fact the same array and your example becomes :
int firstArray[4];
fill_n(firstArray, 4, 0);
//firstArray values are: 0, 0, 0, 0
/* int secondArray[4]; first elements could not be related and you should have : */
int *secondArray = firstArray;
fill_n(secondArray, 4, 1);
//secondArray values are: 1, 1, 1, 1
//firstArray values are also: 1, 1, 1, 1
Hyp 2 : arrays of 4 pointers
You can have first element of both array point to same value while the three others are independent
int array[5];
int *firstArray[4];
int *secondArray[4];
firstArray[0] = &(array[0]);
for(int i=1; i<4; i++)
firstArray[i] = secondArray[i] = &(array[1]);
}
secondArray[0] = &(array[4]);
Then :
int* firstArray[4];
fill_n(firstArray, 4, 0);
//firstArray values are: 0, 0, 0, 0
int* secondArray[4];
fill_n(secondArray, 4, 1);
//secondArray values are: 1, 1, 1, 1
//firstArray values are: 1, 0, 0, 0
and
*(secondArray[0]) = 20;
//secondArray values would be: 20, 1, 1, 1 (because I just changed it)
//firstArray values would be: 20, 0, 0, 0 (because it's pointing to the value I just changed)
That is what you asked for, but it is a very unusual requirement and I'm not sure it is really what you need.

Related

Implement a function that prints an array using pointers

I need to print an array by implementing the use of a function before the main function. So I tried the following function:
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++) {
cout << arr[i];
}
return arr;
}
I encountered two problems when implementing this into the whole code.
First, this is printing what I think is the address of the array and not the actual array. Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument? How can I account for this in my function?
Please keep in mind that I am new to C++ and coding in general. Also, this code was given to me, hence why I do not understand certain aspects of it.
This is my code so you can see what I mean:
#include <iostream>
using namespace std;
// Declare function printArr here
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++)
{cout << arr[i];}
return arr;
}
int main()
{
int arr[5] = {1, 3, 5, 7,9};
int last_num = arr[sizeof(arr)/sizeof(int)-1];
cout << "Before reversing" << endl;
cout << printArr(arr, 5) << endl;
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, 5);
return 0;
}
The declaration and implementation of printArr() is all wrong.
First, this is printing what I think is the address of the array and not the actual array.
The printArr() function itself is printing the contents of the array (well, the first 5 elements anyway), and then returning the address of the array. It is main() that is printing that address afterwards, when it passes the return value of printArr() to std::cout <<.
Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
By getting rid of the return type altogether. There is no good reason to return the array pointer at all in this example, let alone to pass that pointer to std::cout. So printArr() should be returning void, ie nothing.
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument?
Because main() is passing in the element count of the array (5) so that printArr() can know how many elements to actually print, instead of hard-coding that value in the loop. However, your declaration of printArr() does not have a 2nd parameter with which to accept that value, that is why you are getting errors.
How can I account for this in my function?
By adding a 2nd parameter in the function declaration, eg:
#include <iostream>
using namespace std;
// Declare function printArr here
void printArr(int* arr, int size)
{
for (int i = 0; i < size; i++)
{
cout << arr[i] << ' ';
}
cout << endl;
}
int main()
{
int arr[5] = {1, 3, 5, 7, 9};
const int count = sizeof(arr)/sizeof(arr[0]);
int last_num = arr[count-1];
cout << "Before reversing" << endl;
printArr(arr, count);
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, count);
return 0;
}
Live Demo

C++ pass by reference not changing value

Below is the first part of a function meant to analyze a Tic-Tac-Toe board.
The aboutToWin() function returns true if a player is "about to win," ie has two in a row. The board is represented such that if player 1 has made a move in that square, the value in the 3x3 matrix will be 1. Player 2 will be -1. If no one has made a move, it will be 0.
The part that I put in this question is the first part, which checks the negative diagonal (ie positions 1, 5, and 9 on the board).
bool aboutToWin(int squares[3][3], int& position, bool p1)
{
// The value you are looking for is 2 for p1 and -2 for p2
int check = 2;
if (!p1)
{
check = -2;
}
// Check negative diagonal
int sum = 0;
// Go through negative diagonal
for (int i = 0; i < 3; i++)
{
sum += squares[i][i];
// Saves the position of the last checked 0 square
// If check passes, this will be the winning square
// If not, it will get handled and overwritten
if (squares[i][i] == 0)
{
// Calculates position from i
position = 1 + (4 * i);
std::cout << "\nPosition: " << position << "\n";
}
}
// If this diagonal added to check, stop the function and return now
if (sum == check)
return true;
...
}
This is the code that I'm running from the main() function to test this functionality:
int p;
std::cout << p;
int a3[3][3] = {{1, 0, 1},
{0, 0, 0},
{0, 0, 1}};
std::cout << "\nShould be 1, 5: " << aboutToWin(a3, p, true) << ", " << p;
The output is the following:
0
Position: 5
Should be true, 5: 1, 0
Why is this? I can see that the value gets changed during the function, but it doesn't transfer out of the function.
The problem with using:
std::cout << "\nShould be 1, 5: " << aboutToWin(a3, p, true) << ", " << p;
is that the order of the evaluation of the arguments is not defined unless you use C++17.
It looks like p is evaluated first in your setup before the call to aboutToWin.
Separate the calls.
auto ret = aboutToWin(a3, p, true);
std::cout << "\nShould be 1, 5: " << ret << ", " << p;

Understanding 2D array with dynamic memory allocation

Can someone please help me understand the last line in this snippet of code? I don't understand how that dynamically allocates the 2D array. I understand that on line 6, it's creating a pointer named 'a' and pointing it to an array of integers of size 5 as defined by 'c'.
What I don't understand is how that "new int" statement works with the r thrown into the equation. Thanks in advance.
#include <iostream>
const int c = 5; //num of columns
int main () {
int r = 5;
int (*a)[c];
a = new int[r][c]; // allocate array
}
If you have a type T and are going to allocate an array of size N then this expression
new T[N]
returns the address of the type T * of the first element of the allocated array.
So you should write
T *a = new T[N];
For example if T is equivalent to the type int
typedef int T;
or
using T = int;
then the above allocation can be written
int *a = new int[N];
the size of element of the array is equal to sizeof( int ) and usually is 4 bytes.
Now let's assume that you are going to allocate an array of elements of type int[M] where M is a constant integer expression.
You can write
typedef int T[M];
or
using T = int[M];
and
T *a = new T[N];
So you allocated an array of N elements where each element has size sizeof( int[M] and the pointer a points to the first element of the array.
Because T is equivalent tp int [M] you can write
int ( *a )[M] = new int [N][M];
that is this statement allocates an array of N elements of the type int[M] and the pointer a gets the address of the first element of the allocated array.
Returning to your program example
int r = 5
int (*a)[c];
a = new int[r][c];
you can rewrite it the following way
typedef int T[c];
or
using T = int[c];
and
T *a = new T[r];
that is this statements allocates an array of r elements (objects) of type int[c] and a is pointer to the first element of the allocated array.
You're just making a pointer to a one-dimensional array, which requires two indexes to access elements. Nothing crazy, not quite undefined behavior, but not good either.
#include <iostream>
const int c = 5; //num of columns
int main () {
int r = 5;
//Creates a pointer to an array of 5 integer pointers.
int (*a)[c];
a = new int[r][c]; // allocate array
std::cout << *a << std::endl;
std::cout << a << std::endl;
std::cout << std::endl;
std::cout << "Displaying deferenced, unallocated array." << std::endl;
for(int i=0; i<c;++i){
std::cout << *a[i] << std::endl;
}
std::cout << "Diplaying pointers in the array." << std::endl;
std::cout << "Note how it's not a 2d array." << std::endl;
for(int i=0;i<c;++i){
for(int j=0;j<r;++j){
std::cout << a[i] << " ";
}
std::cout << std::endl;
}
std::cout << "Allocating array 1d, 1d style fails..." << std::endl;
/*
for(int i=0;i<c;++i){
a[i] = 23; //Syntax error! Requires two indexes.
}
*/
std::cout << "Allocating 1d array 2d style... success!?" << std::endl;
for(int i=0;i<r;++i){
for(int j=0;j<c;++j){
a[i][j] = 13;
}
}
std::cout << "Displaying allocated array." << std::endl;
for(int i=0;i<r;++i){
for(int j=0;j<c;++j){
std::cout << a[i][j] << " ";
}
std::cout << std::endl;
}
delete [] a;
}
Outputs:
0x100202ba0
0x100202ba0
Displaying deferenced, unallocated array.
0
0
0
0
0
Diplaying pointers in the array.
Note how it's not a 2d array.
0x100202ba0 0x100202ba0 0x100202ba0 0x100202ba0 0x100202ba0
0x100202bb4 0x100202bb4 0x100202bb4 0x100202bb4 0x100202bb4
0x100202bc8 0x100202bc8 0x100202bc8 0x100202bc8 0x100202bc8
0x100202bdc 0x100202bdc 0x100202bdc 0x100202bdc 0x100202bdc
0x100202bf0 0x100202bf0 0x100202bf0 0x100202bf0 0x100202bf0
Allocating array 1d, 1d style fails...
Allocating 1d array 2d style... success!?
Displaying allocated array.
13 13 13 13 13
13 13 13 13 13
13 13 13 13 13
13 13 13 13 13
13 13 13 13 13
Program ended with exit code: 0

How do you change a Block in Eigen?

I'm having trouble reassigning a Block. In the code below I store the matrix A in two different ways:
as 3 ArrayXds, one for each row
as an ArrayXXd
.
// data
ArrayXXd A (3, 3);
A << 0, 1, 2, 3, 4, 5, 6, 7, 8;
std::vector<ArrayXd> A_rows = {A.row(0), A.row(1), A.row(2)};
// std::vector<ArrayXd> solution
// first row
ArrayXd & current_row = A_rows[0];
// read it, write it, do stuff
// start working with the second row
current_row = std::ref(A_rows[1]);
cout << current_row << endl << endl; // prints 3 4 5
cout << A << endl; // A is unchanged
// Eigen solution
// first row
Block<ArrayXXd, 1, -1> && current_row_block = A.row(0);
// read it, write it, do stuff
// start working with the second row
current_row_block = std::ref(A.row(1)); // doesn't compile
cout << current_row_block << endl;
cout << A << endl;
The error message is:
error: use of deleted function 'void std::ref(const _Tp&&) [with _Tp = Eigen::Block<Eigen::Array<double, -1, -1>, 1, -1, false>]'
current_row_block = std::ref(A.row(1));
^
Is it possible to fix the second approach or should I move to storing the matrix as std::vector<ArrayXd>?
Related question: Passing a reference of a vector element to a threaded function
You don't need a Block<...> to reference a row. You only need an index.
int current_row_id = 0;
std::out << A.row(current_row_id) << std::end;
current_row_id = 1;
std::out << A.row(current_row_id) << std::end;
For your std::vector<ArrayXd> approach, as you are make copies of the rows, you can not change the original A.

pointer c++ explanation

I am confused with this block of code:
ipPtr = ipPtr + 3; // 5
cout << *ipPtr << endl;
Why the cout is not 5 but some random large number? can anyone explain to me please. As my understanding I thought the cout << *ipPtr << endl; is pointed to the *ipPtr above it. Am I right ?
#include <iostream>
void main(){
using namespace std;
int iaArray[] = {1,2,3,4,5};
int* ipPtr = 0;
ipPtr = &(iaArray[1]);
cout << *ipPtr << endl;//2
++ipPtr;
cout << *ipPtr << endl;//3
ipPtr = ipPtr + 3; //not 5 but random number.
cout << *ipPtr << endl;
}
Because you have incremented the pointer past the end of the array. You seem to have forgotten that you wrote ++ipPtr before adding 3 to it.
&(iaArray[1])
|
iaArray = { 1, 2, 3, 4, 5 } ?
| |
++ipPtr ipPtr + 3
Because when you add 3 to the pointer it's already on the third position of the array, so it ends up after the last element.
ipPtr = &(iaArray[1]);
//Pointing to the second position (first one is 0)
++ipPtr;
//Pointing to the third position
//3 + 3 = 6
ipPtr = ipPtr + 3;
The array only has 5 positions so it prints whatever is in that memory location not 5 which is in the fifth position.