2-dimensional array, IF condition checking - c++

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

Related

How to compare all elements of vector one to vector two and if a max element exists then comparing all the elements of vector two to vector three?

I want to compare all element of vector x to all elements of vector y and if I find a element greater in vector y than being compared to, I have to take that particular element of vector y and compare to all elements of vector z and if it is true return true else if i don't find a greater element in first iteration i,e when elements of vector x are compared to vector y i have to break the loop and return false.
I tried to iterate through all the elements of stackarmies but I don't know how to take the first element of vector one and compare with all the elements of vector, since all the vectors are merged into the last vector.
vector<int> stack;
int noofstack, noofoperations, stackno, OperationType;
// Taking the input number of stacks
cin >> noofstack;
vector<vector<int>> stackarmies;
for (int i = 0; i < noofstack; i++)
{
int stacksize;
//Since vectors are dynamic and we don't need to declare the size but as per the problem statement I've added it/
cin >> stacksize;
for (int k = 0; k < stacksize; k++)
{
//Taking the input of all the vectors one by one and then adding all the vectors into one vector
int armyheight;
cin>>armyheight;
stack.push_back(armyheight);
}
stackarmies.push_back(stack);
Test cases
Input 1
2
3 3 5 4
3 1 1 2
Resulting stackarmies: { {3, 5, 4}, {3, 5, 4, 1, 1, 2} }
Desired output: False
We will take first element of vector 1 : 3 and compare with all
elements of vector 2 , in vector 2 no element is greater than 3.
Input 2
2
3 1 0 4
3 2 1 3
Resulting stackarmies: { {1, 0, 4}, {1, 0, 4, 2, 1, 3} }
Desired output: True
We will take first element of vector 1 : 1 and compare with all
elements of vector 2, in vector 2, the first element is greater than 1,
so true
Input 3
2
3 1 9 0
2 0 11
Resulting stackarmies: { {1, 9, 0}, {1, 9, 0, 0, 11} }
Desired output: True
We will take first element of vector 1 : 1 and compare with all
elements of vector 2, in vector 2, the last element is greater than 1,
so true
Input 4
3
3 0 8 0
3 4 0 11
3 0 9 0
Resulting stackarmies: { {0, 8, 0}, {0, 8, 0, 4, 0, 11} , {0, 8, 0, 4, 0, 11, 0, 9, 0} }
Desired output: True
We will take the second element of vector 1: 8 and compare with
all elements of vector 2 , 11 is greater than 8 so we will compare 11 of
vector 2 with vector , since there are no values greater than 11, so it's
false
I don't know how to take the first element of vector one and compare with all the elements of vector, since all the vectors are merged into the last vector.
You're getting ahead of yourself. Why do you want all the vectors merged into the last vector? Answer: you don't; that's just what happened. Why did all the vectors merge into the last vector? Answer: because you have a bug in your code that reads the data. Fix that bug instead of spending ten times as much effort trying to handle the malformed data.
That whole spiel about what you intend to do next is nothing more than a distraction that wastes the time of the people from whom you are asking help. Ask for help with the real problem (the loading bug) instead of driving people away with a confusing question that assumes bad data is good.
There are several ways to fix the bug. I think the most helpful approach is one that would have avoided the bug in the first place. You try to do too much in a single function. Divide and conquer; when you have a non-trivial sub-step, create a function to handle it. Good programming practices lead to fewer bugs.
Specifically, reading the heights of the fighters in a stack is non-trivial. Delegate that to a helper and reduce the body of your outer for loop to a single line.
for (int i = 0; i < noofstack; i++)
{
//* This is non-trivial, so use a helper function.
stackarmies.push_back(read_fighter_heights());
}
This helper function is responsible for reading a line of data, generating a stack (a vector<int>) from it, and returning that stack. That covers most of the body of your loop, leaving only the simple task of pushing the returned stack onto your vector of stacks.
Creating this helper function from your existing code is fairly simple. Mostly, just move the body of the loop into an appropriate function definition. In addition, you should notice that stack is needed (only) in this function, so also move that variable's declaration into the new function's definition.
vector<int> read_fighter_heights()
{
vector<int> stack;
int stacksize;
//Since vectors are dynamic and we don't need to declare the size but as per the problem statement I've added it/
cin >> stacksize;
for (int k = 0; k < stacksize; k++)
{
//Taking the input of all the vectors one by one and then adding all the vectors into one vector
int armyheight;
cin>>armyheight; //* Reading a single integer is trivial, so no need for another function here.
stack.push_back(armyheight);
}
return stack;
}
Presto! Problem solved. All you had to do was be more organized.
Addendum: The reason this solves the problem is that extra step of moving the declaration of stack. In the original code, this variable was declared outside the outer loop, and it was never cleared. The result was that it accumulated values from each line that was read. In this version, the variable is re-initialized before reading each line, so values do not accumulate. You could get the same result by moving the line in the original code, without splitting off a new function. However, splitting off a new function is a good habit to get into, as it almost forces you to declare stack at the right level, avoiding the problem in the first place.
bool CompareVectors(vector<vector<int>> st)
{
bool result = true;
for (int k = 0; k < st.size(); k++)
{
if (k != st.size() - 1)
{
if (result)
{
for (auto i = st[k].begin(); i != st[k].end(); ++i)
{
for (auto j = st[k+1].begin(); j != st[k+1].end(); ++j)
{
if (*i < *j)
{
result = true;
break;
}
else
{
result = false;
}
}
if (result)
{
break;
}
}
}
}
}
return result;
}

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;
}

Filling an array causes the stack around the array to be corrupted

I'm trying to fill a 4x6 array with random numbers between 0-25 using a for loop inside a for loop. A runtime error occurs after the array is generated- "Stack around the variable "grid" was corrupted. What is causing this to happen?
int grid[4][6];
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 6; x++) {
grid[x][y] = (rand() % 25);
}
}
You're writing out of bounds. Your loop can write, for example, at (5, 3), which is outside the bounds of the array. In order to fix this, use x for the outer loop and y for the inner loop.
I think your indices are backwards, where you have x it should be y and vice versa
As the others have said, you've got the row and column indices backwards. The reason this is a problem is that in C and C++, the 2D array access:
grid[x][y]
is treated as the equivalent pointer expression:
*(grid + (x*COLS + y))
In this case, since C and C++ use row-major ordering, COLS is 6. Additionally, a 2D array is equivalent to a 1D array of size (ROWS * COLS), meaning that in this case you effectively can address elements 0 through 23 of that 1D array.
Now, looking at your loop structure, you can see that given the pointer arithmetic rule, you'll access element 24 (thus clobbering the stack) when x is 4 and y is 0--that is, *(grid + 4*6 + 0), or the 4th iteration of your inner loop.
Switch your loop order (0 <= x < 4 and 0 <= y < 6) and your problem will go away.
int grid[6][4];
You can use gdb, valgrind or anything else to find out the reason of segmentation fault.

What is being referenced for this matrix?

I was given the following code to use as part of an exercise. I am instructed to create a 3x3 matrix and assign specific values to it.
Here is the code:
void minput(int* m, int row, int col) {
/* assign 3X3 matrix to following value
8 1 6
3 5 7
4 9 2
*/
*(m+0) = 8;
}
What I am trying to figure out is what this piece of code *(m+0) = 8; is for. I know that adding a * in front of any variable means to "give me whatever is that the address".
What does the +0 do?
*(m+0) is equivalent to m[0]. So the whole statement is assigning 8 to m[0].
it dereferences m (gives you the value at it) I'm guessing it's + 0 so that you can add in different values and get the resulting part of the matrix
Arrays are contiguous in memory, so if you were to add 1 instead of 0, you would set the next value in the matrix to 8.
*(m+0) = 8 is the same as m[0] = 8, it dereferences the pointer to the first element then assigns to it the value 8. In your code you represent the matrix via a one-dimensional array, so you probably want to index your (i,j) component as
m+i*col + j or, equivalently, m[i*col+j], i.e. the line
*(m+i*col+j) = x // can also write is as m[i*col+j] = x
assigns x to the (i,j) component.

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.