Offset calculation in 3D array - c++

In the following code,
int arr[3][2][2]={1,2,3,4,5,6,7,8,9,10,11,12};
cout<<arr[0][0][5]<<endl;
cout<<arr[1][3][0]<<endl;
I get output as, 6 and 11.
How is it indexing an element out of its range?
eg- here the sizes are, depth= 3 col=2 row=2 , In thet case arr[0][0][5] means 5th row, which doesnt exist! Can anyone throw light on this.

Technically, you are invoking undefined behaviour.*
But, most likely, what's happening is that the compiler is calculating the address to read as:
(int *)arr + x*(2*2) + y*2 + z
because your 3D array is really stored in memory as a contiguous linear array.
So in your [0][0][5] case, it's simply reading the (0*4+0*2+5)=5th element (zero-based) of that linear array, which is 6.
Similarly for [1][3][0], it's reading the (1*4+3*2+0)=10th element, which is 11.
* This was discussed in a question I asked: One-dimensional access to a multidimensional array: well-defined C?.

Remember the last time you had a C-style string that you forgot to terminate?
char str[] = {'a','b','c'};
cout << str;
Remember how you printed "abc" then any random gubbins in memory after it because the program kept reading past the array?
It'll do that; it'll just keep going and pull out whatever happens to be there, even though doing so is undefined. The compiler simply doesn't need to warn you about this; you are supposed to figure it out for yourself.
In your case, the data for the next row probably happens to be in memory at that spot.

It's like that:
int arr[depth][col][row];
int temp = arr[x][y][z];
then temp = arr[x * (col * row) + y * row + z]

Related

C++ vector.erase() function bug

I have this vector:
list.push_back("one");
list.push_back("two");
list.push_back("three");
I use list.erase(list.begin() + 1) to delete the "two" and it works. But when I try to output the list again:
cout<<list[0]<<endl;
cout<<list[1]<<endl;
cout<<list[2]<<endl;
produces:
one
three
three
I tried targeting the last element for erasing with list.erase(list.begin() + 2), but the duplicate three's remain. I imagined index 2 should have been shifted and list[2] should have outputted nothing. list[3] outputs nothing, as it should.
I'm trying to erase the "two" and output the list as only:
one
three
When using cout<<list[2]<<endl; you asume that you still have three elements. But in fact you are accessing remaining data in a part of the memory that is no more used.
You should use list.size () to obtain the number of elements. So, something like:
for ( size_t i = 0; i < list.size (); i++ )
{
cout<<list[i]<<endl;
}
But you erased the element, thus the size of your container was decreased by one, i.e. from 3 to 2.
So, after the erase, you shouldn't do this:
cout<<list[0]<<endl;
cout<<list[1]<<endl;
cout<<list[2]<<endl; // Undefined Behaviour!!
but this:
cout<<list[0]<<endl;
cout<<list[1]<<endl;
In your case, the "three" is just copied to the index 1, which is expected. you is vector.size() == 2 now.
it is because vector will do pre-allocation, which help to improve the performance.
To keep from having to resize with every change, vector grabs a block of memory bigger than it needs and keeps it until forced to get bigger or instructed to get smaller.
To brutally simplify, think of it as
string * array = new string[100];
int capacity = 100
int size = 0;
In this case you can write all through that 100 element array without the program crashing because it is good and valid memory, but only values beneath size have been initialized and are meaningful. What happens when you read above size is undefined. Because reading out of bounds is a bad idea and preventing it has a performance cost that should not be paid by correct usage, the C++ standard didn't waste any time defining what the penalty for doing so is. Some debug or security critical versions will test and throw exceptions or mark unused portions with a canary value to assist in detecting faults, but most implementations are aiming for maximum speed and do nothing.
Now you push_back "one", "two", and "three". The array is still 100 elements, capacity is still 100, but size is now 3.
You erase array[1] and every element after 1 up to size will be copied up one element (note potentially huge performance cost here. vector is not the right data structure choice if you are adding and removing items from it at random locations) and size will be reduced by one resulting in "one", "three", and "three". The array is still 100 elements, capacity is still 100, but size is now 2.
Say you add another 99 strings. This pushes size each time a string is added and when size will exceed capacity, a new array will be made, the old array will be copied to the new, and the old will be freed. Something along the lines of:
capacity *= 1.5;
string * temp = new string[capacity];
for (int index = 0; index < size; index ++)
{
temp[index] = array[index];
}
delete array;
array = temp;
The array is now 150 elements, capacity is now 150, and size is now 101.
Result:
There is usually a bit of fluff around the end of a vector that will allow reading out of bounds without the program crashing, but do not confuse this with the program working.

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.

Reading a dataset file(Hex values) onto a block of memory-part 2

I have a block of code that is trying to read the data from a dataset on to a randomly allocated block of memory. I don't know what exactly is inside the dataset but they access matrix values(Hex values) and put on to a memory location. And it works perfectly fine!
const unsigned int img_size = numel_img * sizeof(float);// (1248*960)4bytes= 4.79MB
for (unsigned int i=0; i<p_rctheader->glb_numImg; ++i)// 0 to 496(Total no of images)
{
const unsigned int cur_proj = i; // absolute projection number
// read proj mx
double* const pProjMx = pProjMatrixBuffers + cur_proj * 12;
ifsData.read((char*) (pProjMx), 12 * sizeof(double));
ifsData.seekg(img_size, ios::cur);
}
where pProjMatrixBuffers is
double** pProjMatrixBuffers = new double* [rctheader.glb_numImg]; //
pProjMatrixBuffers[0] = new double[rctheader.glb_numImg * 12]; //
for (unsigned int i=1; i<rctheader.glb_numImg; ++i) {
pProjMatrixBuffers[i] = pProjMatrixBuffers[0] + i * 12;
}
There is a another read operation after this :
rctgdata.adv_pProjBuffers = new float* [num_proj_buffers];// 124 buffers
rctgdata.adv_pProjBuffers[0] = new float[num_proj_buffers * numel_img];// (1.198MB per image*124)*4bytes
// set it to zero
memset(rctgdata.adv_pProjBuffers[0], 0, num_proj_buffers * numel_img * sizeof(float));
for (unsigned int i=1; i<num_proj_buffers; ++i) {
rctgdata.adv_pProjBuffers[i] = rctgdata.adv_pProjBuffers[0] + i * numel_img;
}
for (unsigned int i=0; i<numProjsInIteration; ++i)// (0 to 124)
{
const unsigned int cur_proj = numProcessedProjs + i; // absolute projection number// 0+124->124+124->248+124->372+124
// read proj mx
ifsData.read((char*) (pProjMatrixBuffers[cur_proj]), 12 * sizeof(double));
// read image data
ifsData.read((char*) (rctgdata.adv_pProjBuffers[i]), numel_img * sizeof(float));
}
******EDITS****************************
Basically this code, reads Projection matrix from the dataset which is 12 doubles followed by 1248*960 image pixels.(floats). This goes on for 124 times inside for loop.
Q1.If you see in the above code, pProjMatrixBuffers[cur_proj] is read twice, which could have been done once. (Correct me if I am wrong).
Q2.How will rctgdata.adv_pProjBuffers[i] know where to start accessing the data from in the dataset? I mean location in the dataset. I am sorry if I have confused you. Please ask me for more information if needed. Thank you so much for all the help in advance!!
There is no way a 2-dimensional MxN-array can be allocated as such using new. The workaround in this code consists of an allocation of a 1-dimensional array of M pointers and another allocation of an array for the MxN elements. Then the M pointers are set to point to the M first elements of each row within the array for the elements.
Here we have two 2-dimensional arrays which I call (for obvious reasons) D and F. It's not clear how big D is - what's the value of rctheader.glb_numImg?
The first loop reads 12 doubles into a row of D and skips the float data for a row of F, doing a seekg with the appropriate positive offset to be added to the current position (i.e., forward). This is done rctheader.glb_numImg times.
There is something I don't see in this code: a single seekg back to the beginning of the file, after the first loop and before the second loop.
The second loop reads (once more) 12 doubles for each of the 124 rows and then, in one fell swoop, 1248*960 floats for each row. There is no need to reposition after these reads since the data for the second image immediately follows the data for the first image, and so on. (It's slightly irritating that num_proj_buffers and numProjsInIteration should have the same value, i.e., 124.)
It looks as if the second read loop would re-read what the first loop read. But since I don't know for sure that p_rctheader->glb_numImg is also 124, I can't really confirm that.
Calculating the size of what is read by 123 iterations of the second loop as
(1248*960*4 + 12*8)*124
this would account for ~0.5 GB - but the file size was reported as being ~2.5 GB.
Also note that one index within the second loop is computed as
unsigned int cur_proj = numProcessedProjs + i;
but the initial setting of numProcessedProjs is unclear.
To answer Q2, you allocate one big block of memory with new double[header.numImg * 12], and you also allocate a bunch of row pointers with new double* [header.numImg]. The first row pointer [0] points at the beginning of the memory (because it was used in the new call). The for loop then sets each row pointer [i] to point into the big block at 12-item increments (so each row should have 12 items in it). So for instance [1] points at the 12th item in the big block, [2] points at the 24th item, etc.
I haven't quite figured out what you mean by Q1 yet.

Double buffer vs double array c++

I was asked to create a matrix with 5 rows and unknown column.
And my boss want me to use a 1 dimensional buffer. concatenated by 5 rows buffer.
I don't get what is that mean, can some one provide me a simple example please!
With array I can do
double[][] arr = new double[5][someNumber];
But he says then the size would be limited.
So I don't know what he means by using a DOUBLE buffer, I am not very good #C++
Thank you very much, an example would be nice!
For R rows and C columns declare double arr[R * C], and arr[i * C + j] is the element at cell [i, j].
This generalizes to arbitrary dimensions.
Flattening out an array like that can be a very useful optimization, especially when you use dynamic arrays such as std::vector, where you can get a single dynamic array rather than one for each row.
Sounds like you're saying
double *arr[5];
for(unsigned int x = 0; x < 5; ++x)
{
arr[x] = new double[someNumber];
}
Since, you know that you have 5 for sure, and an unknown part my assumption is this is how you're referring to it.

Finding the middle of an array without knowing the length

Find the middle of the string or array with an unknown length. You may
not traverse the list to find the length. You may not use anything to
help you find the length - as it is "unknown." (ie. no sizeof (C) or count(C#) etc...)
I had this question as an interview question. I'm just wondering what the answer is. I did ask if i could use sizeof, he said "no, the size of the string or array is unknown - you just need to get to the middle."
BTW, i'm not sure if this is actually possible to solve with no traversing. I almost felt as though he may have wanted to see how confident i am in my answer :S not sure...
His English was bad - also not sure if this contributed to misunderstandings. He directly told me that i do not need to traverse the list to get to the middle :S :S I'm assuming he meant no traversing at all..... :S
Have two counters, c1 and c2. Begin traversing the list, incrementing c1 every time and c2 every other time. By the time c1 gets to the end, c2 will be in the middle.
You haven't "traversed the list to find the length" and then divided it by two, you've just gone through once.
The only other way I can think of would be to keep taking off the first and last item of the list until you are left with the one(s) in the middle.
You (or your interviewer) are very vague in what the data is (you mentioned "string" and "array"); there's no assumption that can be made, so it can be anything.
You mentioned that the length of the string is unknown, but from your wording it might seem like you (or the interviewer) actually meant to say unknowable.
a) If it's just unknown, then the question is, how can it can be determined? In the case of strings, for example, you can consider the end to be '\0'. You can then apply some algorithms like the ones suggested by the other answers.
b) If it's unknowable, the riddle has no solution. The concept of middle has no meaning without a beginning and an end.
Bottom line, you cannot talk about a middle without a beginning and an end, or a length. Either this question was intentionally unanswerable, or you did not understand it properly. You must know more than just the beginning of the memory segment and maybe its type.
The following code will find the middle of an array WITHOUT traversing the list
int thearray[80];
int start = (int)&thearray;
int end = (int)(&thearray+1);
int half = ((end-start) / 4)/ 2;
std::cout << half << std::endl;
EDITS:
This code assumes you are dealing with an actual array and not a pointer to the first element of one, thus code like:
int *pointer_to_first_element = (int *)malloc(someamount);
will not work, likewise with any other notation that degrades the array reference into a pointer to the first element. Basically any notation using the *.
You would just use the difference between the addresses of the first and last elements.
I think this problem is aimed to also test your skills in problem analysis and requirements gathering. As others have stated before, we will need at least another piece of data to solve this issue.
My approach is to let clear to the interviewer that we can solve the problem with one constraint in the function call: the caller must provide 2 pointer, one to the beginning and another to the end of the array. Given those 2 pointers, and using basic pointer arithmetic, I reach this solution; please let me know what you think about it.
int *findMiddleArray( int const *first, int const *last )
{
if( first == NULL || last == NULL || first > last )
{
return NULL;
}
if( first == last )
{
return (int *)first;
}
size_t dataSize= ( size_t )( first + 1 ) - ( size_t )first,
addFirst= ( size_t )first,
addLast= ( size_t )last,
arrayLen= ( addLast - addFirst) / dataSize + 1,
arrayMiddle= arrayLen % 2 > 0 ? arrayLen / 2 + 1 : arrayLen / 2;
return ( int * )( ( arrayMiddle - 1 ) * dataSize + addFirst );
}
one way you can find midpoint of array is (for odd length array)
just use two loops ,1st loop start traverse from 0 index and the other (nested) loop will traverse from last index of array. Now just compare elements when it comes same ...that will be the mid point of array. i.e if(arr[i]== arr[j]) . Hope you got the point !
For Even length array ..you can do if(arr[i] == arr[j-1]) Or if(arr[i] == arr[j+1]) as they will never be same .try it by dry run!