C++ arrays - limit and size - c++

How do you declare an array for a matrix that contains say 4 numbers (2x2)? I assume that int m[4] only allows numbers up to 4. Or does it mean any four numbers? I don't understand the difference.

In a declaration
type array_name[ array_size];
type is the data type that this array stores. The particular value of array under index i, i.e. array_name[i] can be any of the values that type can represent.
In your example int m[4]; declares an array of four integers. The particular value of any of these integers can be any of the values that integer can represent. To know these limits you can print them:
#include <limits>
int imin = std::numeric_limits<int>::min(); // minimum value
int imax = std::numeric_limits<int>::max(); // maximum value

The use of STD should simplify your life in the construction of a matrix :
std::vector<std::vector<int>> M(2, std::vector<int>(2));
But if you want to use arrays :
int x[2][2];

int m [4] would declare an array with 4 uninitialized values of type integer. Remember that these values are zero-indexed,
meaning that to call a value in the array you would call m[0-3]. You may assign any values you like to the array by the following command: m[4] = {Value1, Value2, Value3, Value4} If you prefer, you may also create a loop that will assign values to an array, which can be immensely useful at times.
Keep in mind that arrays are not commonly used in C++, std::vector is far more used, and for good reason.
http://www.cplusplus.com/reference/vector/vector/

int m[4] declares an array of 4 integers. The indexes of the integers will be 0, 1, 2, 3, while the values at those indexes can be any integers. so m[2] = 2003; sets the 3rd value in the array to 2003. As for the 2x2 aspect, you probably want to do something like int m[2][2]; . I think about this as declaring an array of size 2, containing arrays at each spot, instead of ints or floats or whatever. The arrays contained at each spot (there are only two spots so only two arrays in this case) each hold two ints. So if the first value in your matrix is 32, you could set that by doing m[0][0] = 32; or more generally, m[x][y] = value_of_(x,y);
The quickest way to do what you described is probably this, if you know the values ahead of time:
int row0col0 = value at 0th row 0th column;
int row0col1 = value at 0th row 1st column;
int row1col0 = value at 1st row 0th column;
int row1col1 = value at 1st row 1st column;
int m[2][2] = { {row0col0, row0col1}, {row1col0, row1col1} };
or equivalently:
int m[2][2] = {row0col0, row0col1, row1col0, row1col1};
This is referred to as row-major order: elements in a 2d array are sorted first by row, then by column.

Related

C++ Arrays and overflow

I am mis-understanding something about the code below. From my understanding the tester declaration should return a pointer to the first array of two elements, i.e. [1,2], and so *(tester+1) should return [3,4], which only has 2 elements so how does it make sense to call (*(tester + 1))[2] . This example prints the number 5 by the way. Any clarifications much appreciated.
int main() {
int tester[][2]{ 1,2,3,4,5,6 };
cout << (*(tester + 1))[2] << endl;
return 0;
}
When you declare a 2-dimensional array, all the elements are contiguous. The entire array is a single object, so you're not going out of bounds when you just exceed one of the row limits, so longer as you're still in the array. So the next element after tester[1,1] is tester[2,0], and that's what (*(tester + 1))[2] accesses.
[2] is higher than the highest element at [1] because the index starts at [0]
There are three arrays.
[1,2] positions 0,0 and 0,1
[3,4] positions 1,0 and 1,2
[5,6] positions 2,0 and 2,1
Since all of the arrays are next to each other in the data segment, going out of bounds on the second array (tester + 1) bleeds over into the third array giving you the first element of the third array.
i.e. position 1,2 is the same as 2,0
int tester[][2]{ 1,2,3,4,5,6 } creates a 3 by 2 array.
tester[0][0] = 1
tester[0][1] = 2
tester[1][0] = 3
tester[1][1] = 4
tester[2][0] = 5
tester[2][1] = 6
The compiler creates an array using the least amount of memory possible based on your specifications. [][2] explicit says to organize the data in such a fashion that there a x rows and 2 columns. Because you put 6 elements into the tester array, the compiler decides the number of rows to assign by dividing the number of total elements by the number of columns.
Furthermore, (*(tester + 1))[2], is equivalent to tester[2], which would access the element in the first column of the third row. Thus returning 5.
It is another way to write this code which means you define vector but it acts like 2-dimensional array.
int main() {
int tester[3][2]{ {1,2},{3,4},{5,6} };
std::cout<< tester[1][2] <<std::endl;
return 0;
}

Shifting elements in array by N elements

I have an array where each 'element' is composed of 4 consecutive values. Upon update I move the array by 4 values towards the end and insert 4 new values in the beginning.
Shift:
int m = 4;
for (int i = _vsize - 1; i + 1 - m != 0; i--){
_varray[i] = std::move(_varray[i - m]);
}
Insertion:
memcpy(&_varray[0], glm::value_ptr(new_element), 4 * sizeof(float));
where new_element is of type glm::vec4 containing said 4 new values.
Any suggestions on how to improve this?
(Right now Im only shifting by one element, but want the flexibility of being able to shift say 8 times, without having to put this in a loop)
Thank you.
You can try std::copy_backward. You want to copy a range of values to another range in the same container. Since the ranges overlap and you are copying to the right you can't use regular std::copy but must use std::copy_backward instead.
int m = 4; // make this a multiple of your 'element' size
std::copy_backward(&_varray[0], &_varray[_vsize - m], &_varray[_vsize]);
There is also std::move_backward but that doesn't really matter since your float values aren't movable.

I don't understand how to create and use dynamic arrays in C++

Okay so I have;
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Line 4 fills the first element, how do I fill the rest?
Without line 4, line 5 reads "-842150451".
I don't understand what is going on, I'm trying to create a 2 dimensional array using x and y values specified by the user, and then fill each element one by one with numeric values also specified by the user. My above code was an attempt to try it out with a 1 dimensional array first.
The default C++ way of creating a dynamic(ally resizable) array of int is:
std::vector<int> grid;
Don't play around with unsafe pointers and manual dynamic allocation when the standard library already encapsulates this for you.
To create a vector of 5 elements, do this:
std::vector<int> grid(5);
You can then access its individual elements using []:
grid[0] = 34;
grid[1] = 42;
You can add new elements to the back:
// grid.size() is 5
grid.push_back(-42);
// grid.size() now returns 6
Consult reference docs to see all operations available on std::vector.
Should line 3 create an array with 5 elements?
Yes. It won't initialise them though, which is why you see a weird value.
Or fill the first element with the number 5?
new int(grid_x), with round brackets, would create a single object, not an array, and specify the initial value.
There's no way to allocate an array with new and initialise them with a (non-zero) value. You'll have to assign the values after allocation.
Line 4 fills the first element, how do I fill the rest?
You can use the subscript operator [] to access elements:
grid[0] = 34; // Equivalent to: *(grid) = 34
grid[1] = 42; // Equivalent to: *(grid+1) = 42
// ...
grid[4] = 77; // That's the last one: 5 elements from 0 to 4.
However, you usually don't want to juggle raw pointers like this; the burden of having to delete[] the array when you've finished with it can be difficult to fulfill. Instead, use the standard library. Here's one way to make a two-dimensional grid:
#include <vector>
std::vector<std::vector<int>> grid(grid_x, std::vector<int>(grid_y));
grid[x][y] = 42; // for any x is between 0 and grid_x-1, y between 0 and grid_y-1
Or might be more efficient to use a single contiguous array; you'll need your own little functions to access that as a two-dimenionsal grid. Something like this might be a good starting point:
template <typename T>
class Grid {
public:
Grid(size_t x, size_t y) : size_x(x), size_y(y), v(x*y) {}
T & operator()(size_t x, size_t y) {return v[y*size_x + x];}
T const & operator()(size_t x, size_t y) const {return v[y*size_x + x];}
private:
size_t size_x, size_y;
std::vector<T> v;
};
Grid grid(grid_x,grid_y);
grid(x,y) = 42;
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Create an array with 5 elements.
Line 4 fills the first element, how do I fill the rest?
grid[n] = x;
Where n is the index of the element you want to set and x is the value.
Line 3 allocates memory for 5 integers side by side in memory so that they can be accessed and modified by...
The bracket operator, x[y] is exactly equivalent to *(x+y), so you could change Line 4 to grid[0] = 34; to make it more readable (this is why grid[2] will do the same thing as 2[grid]!)
An array is simply a contiguous block of memory. Therefore it has a starting address.
int * grid;
Is the C representation of the address of an integer, you can read the * as 'pointer'. Since your array is an array of integers, the address of the first element in the array is effectively the same as the address of the array. Hence line 3
grid = new int[grid_x];
allocates enough memory (on the heap) to hold the array and places its address in the grid variable. At this point the content of that memory is whatever it was when the physical silicon was last used. Reading from uninitialised memory will result in unpredictable values, hence your observation that leaving out line 4 results in strange output.
Remember that * pointer? On line four you can read it as 'the content of the pointer' and therefore
*grid = 34;
means set the content of the memory pointed to by grid to the value 34. But line 3 gave grid the address of the first element of the array. So line 4 sets the first element of the array to be 34.
In C, arrays use a zero-based index, which means that the first element of the array is number 0 and the last is number-of-elements-in-the-array - 1. So one way of filling the array is to index each element in turn to set a value to it.
for(int index = 0; index < grid_x; index++)
{
grid[index] = 34;
}
Alternatively, you could continue to use a pointer to do the same job.
for(int* pointerToElement = grid; 0 < grid_x; grid_x-- )
{
// save 34 to the address held by the pointer
/// and post-increment the pointer to the next element.
*pointerToElement++ = 34;
}
Have fun with arrays and pointers, they consistently provide a huge range of opportunities to spend sleepless hours wondering why your code doesn't work, PC reboots, router catches fire, etc, etc.
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first
element with the number 5?
Definitely the former. With the operator "new" you are allocating memory
Line 4 fills the first element, how do I fill the rest?
Use operator [], e.g.:
for int (i=0; i < grid_x; i++) { //Reset the buffer
grid[i] = 0;
}
Without line 4, line 5 reads "-842150451".
You are just reading uninitialized memory, it could be any value.
I don't understand what is going on, I'm trying to create a 2
dimensional array using x and y values specified by the user, and then
fill each element one by one with numeric values also specified by the
user. My above code was an attempt to try it out with a 1 dimensional
array first.
Other users explained how to use vectors. If you have to set only once the size of your array, I usually prefer boost::scoped_array which takes care of deleting when the variable goes out of scope.
For a two dimensional array of size not known at compile time, you need something a little bit trickier, like a scoped_array of scoped_arrays. Creating it will require necessarily a for loop, though.
using boost::scoped_array;
int grid_x;
int grid_y;
///Reading values from user...
scoped_array<scoped_array<int> > grid(new scoped_array<int> [grid_x]);
for (int i = 0; i < grid_x; i++)
grid[i] = scoped_array<int>(new int[grid_y] );
You will be able then to access your grid elements as
grid[x][y];
Note:
It would work also taking scoped_array out of the game,
typedef int* p_int_t;
p_int_t* grid = new p_int_t [grid_x];
for (int i = 0; i < grid_x; i++)
grid[i] = new int[grid_y];
but then you would have to take care of deletion at the end of the array's life, of ALL sub arrays.

How to get intersection of two Arrays

I have two integer arrays
int A[] = {2, 4, 3, 5, 6, 7};
int B[] = {9, 2, 7, 6};
And i have to get intersection of these array.
i.e. output will be - 2,6,7
I am thinking to sove it by saving array A in a data strcture and then i want to compare all the element till size A or B and then i will get intersection.
Now i have a problem i need to first store the element of Array A in a container.
shall i follow like -
int size = sizeof(A)/sizeof(int);
To get the size but by doing this i will get size after that i want to access all the elemts too and store in a container.
Here i the code which i am using to find Intersection ->
#include"iostream"
using namespace std;
int A[] = {2, 4, 3, 5, 6, 7};
int B[] = {9, 2, 7, 6};
int main()
{
int sizeA = sizeof(A)/sizeof(int);
int sizeB = sizeof(B)/sizeof(int);
int big = (sizeA > sizeB) ? sizeA : sizeB;
int small = (sizeA > sizeB) ? sizeB : sizeA;
for (int i = 0; i <big ;++i)
{
for (int j = 0; j <small ; ++j)
{
if(A[i] == B[j])
{
cout<<"Element is -->"<<A[i]<<endl;
}
}
}
return 0;
}
Just use a hash table:
#include <unordered_set> // needs C++11 or TR1
// ...
unordered_set<int> setOfA(A, A + sizeA);
Then you can just check for every element in B, whether it's also in A:
for (int i = 0; i < sizeB; ++i) {
if (setOfA.find(B[i]) != setOfA.end()) {
cout << B[i] << endl;
}
}
Runtime is expected O(sizeA + sizeB).
You can sort the two arrays
sort(A, A+sizeA);
sort(B, B+sizeB);
and use a merge-like algorithm to find their intersection:
#include <vector>
...
std::vector<int> intersection;
int idA=0, idB=0;
while(idA < sizeA && idB < sizeB) {
if (A[idA] < B[idB]) idA ++;
else if (B[idB] < A[idA]) idB ++;
else { // => A[idA] = B[idB], we have a common element
intersection.push_back(A[idA]);
idA ++;
idB ++;
}
}
The time complexity of this part of the code is linear. However, due to the sorting of the arrays, the overall complexity becomes O(n * log n), where n = max(sizeA, sizeB).
The additional memory required for this algorithm is optimal (equal to the size of the intersection).
saving array A in a data strcture
Arrays are data structures; there's no need to save A into one.
i want to compare all the element till size A or B and then i will get intersection
This is extremely vague but isn't likely to yield the intersection; notice that you must examine every element in both A and B but "till size A or B" will ignore elements.
What approach i should follow to get size of an unkown size array and store it in a container??
It isn't possible to deal with arrays of unknown size in C unless they have some end-of-array sentinel that allows counting the number of elements (as is the case with NUL-terminated character arrays, commonly referred to in C as "strings"). However, the sizes of your arrays are known because their compile-time sizes are known. You can calculate the number of elements in such arrays with a macro:
#define ARRAY_ELEMENT_COUNT(a) (sizeof(a)/sizeof *(a))
...
int *ptr = new sizeof(A);
[Your question was originally tagged [C], and my comments below refer to that]
This isn't valid C -- new is a C++ keyword.
If you wanted to make copies of your arrays, you could simply do it with, e.g.,
int Acopy[ARRAY_ELEMENT_COUNT(A)];
memcpy(Acopy, A, sizeof A);
or, if for some reason you want to put the copy on the heap,
int* pa = malloc(sizeof A);
if (!pa) /* handle out-of-memory */
memcpy(pa, A, sizeof A);
/* After you're done using pa: */
free(pa);
[In C++ you would used new and delete]
However, there's no need to make copies of your arrays in order to find the intersection, unless you need to sort them (see below) but also need to preserve the original order.
There are a few ways to find the intersection of two arrays. If the values fall within the range of 0-63, you can use two unsigned longs and set the bits corresponding to the values in each array, then use & (bitwise "and") to find the intersection. If the values aren't in that range but the difference between the largest and smallest is < 64, you can use the same method but subtract the smallest value from each value to get the bit number. If the range is not that small but the number of distinct values is <= 64, you can maintain a lookup table (array, binary tree, hash table, etc.) that maps the values to bit numbers and a 64-element array that maps bit numbers back to values.
If your arrays may contain more than 64 distinct values, there are two effective approaches:
1) Sort each array and then compare them element by element to find the common values -- this algorithm resembles a merge sort.
2) Insert the elements of one array into a fast lookup table (hash table, balanced binary tree, etc.), and then look up each element of the other array in the lookup table.
Sort both arrays (e.g., qsort()) and then walk through both arrays one element at a time.
Where there is a match, add it to a third array, which is sized to match the larger of the two input arrays (your result array can be no larger than the largest of the two arrays). Use a negative or other "dummy" value as your terminator.
When walking through input arrays, where one value in the first array is larger than the other, move the index of the second array, and vice versa.
When you're done walking through both arrays, your third array has your answer, up to the terminator value.

2-dimensional array, IF condition checking

I've came across a problem when coding with C++ 2D array.
Just a little question, what does the code below mean?
...
if(array[x][y] >= 9){
...
}
...
Does that mean when the sum of x and y of the array is greater or equal to 9, then only the body of the IF will run? Or ........?
Please explain and provide some simply examples.
the array is two dimensional, it means the element at array[x][y]
unlike 1D arrays, which only require 1 index, 2D arrays require 2 indices in the form of array[x][y] presumably in a nested for loop.
You can iterate through such an array like this
for (int x = 0; x < arrayLength; x++) {
for (int y = 0; y < array[x]Length; y++) {
// do something with array[x][y]
}
}
where arrayLength is the length of array and array[x] length is the length of array[x].
So in reference to the code that you posted, it's testing to see if the member of the 2D array is greater than or equal to 9.
Ok let's start with the basics.
1D Arrays
How can you imagine a normal array? You could say a normal array is like a number line:
|-------------------------------| where every - is one element in your array
The very first '-' on the left side is the element at myArray[0] (the '|' are just symbolizing that it has a start and a end).
2D Arrays
A 2D array can be visualized as checkerboard, bookshelf or a table with columns and rows.
|-------------------------------|
|-------------------------------|
|-------------------------------|
|-------------------------------|
Just like in chess you need 2 values in order to address an element. If you only specify one value the compiler might know the row of your value but not its column (or the other way around). That means you need x and y coordinates (which is a visual analogy for a coordinate system). In order to address a value you have to do it like this:
myArray[x][y] where x could be the row of our checkerboard and y the column.
In your case your 2D array is most likely filled with integers. The 'if' statement checks if the value stored in myArray[x][y] is larger than 9. If myArray[x][y] is larger than 9 this statement returns true and the code inside will get executed.
After executing the code inside of the 'if' statement the program will continue to execute the code after the if statement. 2D arrays can be understood as an array containing arrays.
If you are thinking 3 dimensional arrays are possible you're right. Here you need 3 coordinates in order to describe a point since you have depth, height and length (here I'm talking about the visual length not the length in terms of total amount of elements.).
I don't know whether this helped but this is of course a very visual approach of explaining how multi-dimensional arrays work.
Example
int myArray[3][3] = {{1, 2, 3}, // row 0
{4, 5, 6}, // row 1
{7, 8, 10}}; // row 2
In this case your if statement would only be executed if x = 2 and y = 2 since myArray[2][2] = 10
It means "IF the element at coordinates (x,y) is greater or equal than 9...".
There is no addition operation. The array is probably declared with the minimum dimensions (x+1, y+1).
int array[2][2] = {{12, 6}, {3, -2}};
int x=1, y=0;
if(array[x][y] >= 9){...} // array[1][0] equals 3, condition is false