How to declare array of pointers to the another array elements - c++

I have an array.
char tab[200];
and then I want to create array which consists pointers to the previous array elements
char** t = new (char*)[LENGTH];
but i do get
C:\Users\Duke\Desktop\PJC3\main.cpp|37|error: array bound forbidden after parenthesized type-id|
How should I declare it DYNAMICALLY?
EDIT: Is that correct pointing to corresponding elements of the tab array?
char** t = new char*[dlugoscTab];
for(int i = 0; i < dlugoscTab; i++){
*(t + i*sizeof(char)) = (tab + i*sizeof(char));
}

To do it the way you're trying to, you need to just get rid of the parentheses:
char** t = new char*[LENGTH];
for (i = 0; i < LENGTH; i++) {
t[0] = &tab[i];
}
However, there doesn't seem to be much of a reason to use dynamic allocation here, so just use an array of char*:
char* t[LENGTH];
for (i = 0; i < LENGTH; i++) {
t[0] = &tab[i];
}
Or better yet, use a standard container like std::array or std::vector.
The assignment in your edit is incorrect:
*(t + i*sizeof(char)) = (tab + i*sizeof(char));
It will work in this case but only because sizeof(char) is 1. You should not be involving sizeof here. Adding 1 to a pointer does not move it 1 byte, but moves it to point to the next object of the type it is pointing at. You should be doing:
*(t + i) = (tab + i);
But as I've written in my examples above, this is exactly the much easier to understand:
t[i] = &tab[i];

char** t = new (char*)[LENGTH];
Should be:
char** t = new char*[LENGTH];
If you want every ith element in t to point to the ith element in tab, you can simply do this like so:
for(int i=0; i<LENGTH; i++ )
t[i] = & tab[i];

The correct syntax is:
char (*t)[LENGTH] = new char(*)[LENGTH];
But it doesn't make much sense to allocate it with new because that just allocates one pointer, not an array.

Related

Creating memory space for multi-dimensional array

I am studying c++ and found this in the book
array_ptr = new int[3][5][4];
This is used to allocate memory to a multi dimensional array using new. It also states while first dimension can be a variable whose value is supplied at runtime, others must be constant.
I tried to run this code
int *p = new int[3][5][6];
But it is showing an error.
Can someone elaborate.
Here is what you want:
int (*p)[5][6] = new int[3][5][6];
Since C++11 you can ask the compiler to decuce the type of p for you:
auto p = new int[3][5][6];
You don't need anything special to delete such array:
delete [] p;
Logic behind the choice of the type is simple:
In this line: int *p = new int[10] you're creating an array of 10 ints and you use pointer to int to store the address.
In general case, if you're allocating an array of N Ts (where N is the size and T is the type), you use pointer to T to store the address.
Same rule can be applied to multidimensional arrays, because they are in fact nested 1D arrays.
When you try to allocate multidimensional array: p = new int[4][5][6], you're creating an array of 4 arrays of 5 arrays of 6 ints. Thus you need a pointer to array of 5 arrays of 6 ints, which is int (*p)[5][6].
In other words, int [3][4][5] can be viewed as 1D array of size 3. It consists of other arrays of type int [4][5]. Each of these arrays has size 4 and consists of other arrays of type int [5], which in turn contain 5 ints.
P.S. Authors of other answers seem to favor using int *** and allocating memory for each nested array separately. Doing so may seem smart, but in fact it's much slower and dangerous (if you mess up your memory management). The only advantage of that trick is that it provides the convenient interface we all used to (p[z][y][x]).
But there is a much better solution: int *p = new int[x_sz * y_sz * z_sz];. You would need to convert 3D indices to 1D index (p[x + x_sz * (y + z * y_sz)] instead of p[z][y][x]) for it to work, but in my opinion it's still more convenient (and definitely faster).
Of course, in real code, you should use std::vector to store such array and write your own wrapper class, which would compute the index automatically.
A 3d array is not the same as a pointer to int, and you can't make them the same.
If you need dynamic allocation, you can use special class std::vector (best choose), std::array, or write next code:
int ***p = new int**[3];
for (int i = 0; i < 3; ++i) {
p[i] = new int*[5];
for (int j = 0; j < 5; ++j) {
p[i][j] = new int[6];
}
}
In order to create dynamic 3d array you have to use pointer to pointer to pointer)
const int xSize = 3;
const int ySize = 5;
const int zSize = 4;
int*** p = nullptr;
// creating array of pointers to pointers
p = new int** [xSize]
// for each pointer to pointers, create array of pointers
for( int i = 0; i < xSize; ++i )
p[ i ] = new int* [ySize];
// now we have 2d array of pointers, for each of them allocate array
for( int i = 0; i < xSize; ++i )
for( int j = 0; j < ySize; ++j )
p[ i ][ j ] = new int [zSize];
But is much more better to use vectors
vector<vector<vector<int> > > v3d;
v3d.resize( 3 );
for( int i = 0; i < xSize; ++i )
v3d[ i ].resize( ySize );
for( int i = 0; i < xSize; ++i )
for( int j = 0; j < ySize; ++j )
v3d[ i ][ j ].resize( zSize );

Dynamic sized array of pairs: Setting values for first/second

I keep getting errors "subscript requires array or pointer type" when working with an array of pairs. I've looked at all the other threads with similar problems, but have been unable to resolve it.
I dynamically declared an array of pairs which looks like:
pair<T, int> *m_Array;
And set the array size with:
m_Array = new pair<T, int>[c];
Now what I am failing to do is access the first and second of the pair, in an index of the array. I get the error when I try to do things like this.
for (int i = 0; i < m_Size; i++) {
m_Array->first[i] = rhs.m_Array->first[i];
m_Array->second[i] = rhs.m_Array->second[i];
}
It intuitively seems like it should be more like the following code, but my IDE does not like me having m_Array[i]
for (int i = 0; i < m_Size; i++) {
m_Array[i]->first = rhs.m_Array[i]->first;
m_Array[i]->second = rhs.m_Array[i]->second;
}
You're nearly there.
If m_Array is a pointer to some pairs, then m_Array[0] is the first pair; then m_Array[0].first is the "first" member of that first pair.
There is no need for the dereferencing member access operator ->, as the subscription [i] has already dereferenced for you (that is, m_Array[i] means *(m_Array + i)). So you just need the normal member access operator..
So:
for (int i = 0; i < m_Size; i++) {
m_Array[i].first = rhs.m_Array[i].first;
m_Array[i].second = rhs.m_Array[i].second;
}
Or you could skip all this trouble and just write:
for (int i = 0; i < m_Size; i++) {
m_Array[i] = rhs.m_Array[i];
}
Or you could skip that too and change from new and arrays to a nice std::vector, then have it do all the work for you.

How to make pointers to chars in the second array

I have an array of chars. n is array's length
char tab[n];
cin.get(tab, n);
cout<<tab<<"\0"<<endl;
then I create second array
char* t = new char[n];
for(int i = 0; tab[i] != '\0'; i++){
t[i] = tab[i];
}
I would like to have pointers to corresponding element. I mean t[2] contains addres of tab[2]. Then I would like to sort array t so tab stays as it was and only t shuffles but when I make change in the array t for example
t[2] = 'a';
I loose t[3]t[4]....
EDIT:
do{
for(int i = 0; i < n -1; i++){
if(t[i] > t[i+1]){
char* x = &t[i];
t[i] = t[i+1];
t[i+1] = *x
}
n--;
}
}while(n>1);
I would like to have pointers to corresponding element. I mean t2 contains addres of tab2.
So try this:
char** t = new (char*)[n];
for(int i = 0; tab[i] != '\0'; i++){
t[i] = tab+i; // or `&(tab[i])`
To sort the t array based on tab values, use *t[i] to access character values stored in location i of the t array.
See here and here for good tutorials about C pointers.

Sorting an array by reference

I made a simple routine to sort an array witch accepts as a parameter an array of ints the problem is that when i compare the values array[i] shows the correct value in the debugger but array[i + 1] shows a bogus value ... i guess is a pointer issue but i can't figure it out what i am doing wrong.
Here is the code :
typedef int vector[10];
void task1(vector * param)
{
bool ordered = false;
while (!(ordered))
{
int tmp = 0;
ordered = true;
for (int i = 0; i < 9 ; i++)
{
if (*param[i] > *param[i+1])
{
tmp = *param[i];
*param[i] = *param[i + 1];
*param[i + 1] = tmp;
ordered = false;
}
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
vector tavi = {10,88,77,192,7,27,82,1,882,13};
task1(&tavi);
for (int i = 0 ; i < 10 ; i ++)
printf("%d ",tavi[i]);
_getch();
return 0;
}
The subscript-operator ([]) has a higher precedence than the derefence-operator (*), so *param[i] is actually *(param[i]). This means, you first go to the i-th element of param, and then dereference it - that is not what you want (param is not a pointer into an array). You want to dereference param and then go to the i-th element - this would be (*param)[i].
First of all: Why would you write the sorting yourself (not to mention that bubblesort is not exactly fast).
So why not simply use
std::sort(tavi, tavi + 10, std::less<int>());
Of course if you have C++11 or boost its also a good idea to forget about c style arrays and use std::array or boost::array instead:
std::array<int, 10> tavi = {10,88,77,192,7,27,82,1,882,13};
std::sort(tavi.begin(), tavi.end(), std::less<int>());
for (int i = 0 ; i < tavi.size(); i ++)
std::cout<<tavi[i]<<" ";
If however you really want to do it like that, *param[i] is the same as *(param[i]), while you want to use (*param)[i].
vector is type int[10]. Therefore, vector* is type int(*)[10]. That is, a pointer to an array of 10 ints. So the distance between param[i] and param[i+1] is sizeof(int) * 10
When you do this:
if (*param[i] > *param[i+1])
You are comparing one array of 10 ints to the next array of 10 ints. I wish this would simply not compile, unfortunately, what happens is that the arrays are implicitly converted to pointers to their first element. Since i < i+1, the above comparison will never be true.

Initializing array of pointers

I have a Deck object (deck of cards) which is a double-ended queue implemented as a doubly-linked list. I would like to be able to shuffle the queue at will, but the way I would go about it is beyond me. So instead I've opted to pre-shuffle an array a pointers to the cards and enqueue them after the fact. Problem is, the code I have now doesn't seem to be initializing the pointers at all.
void BuildDeck(Deck* deck) {
Card** cards = new Card*[20];
const size_t MAX_INTEGER_LENGTH = sizeof(int) * 4;
char szPostfix[] = "_Card.bmp";
for(int i = 1; i < 21; i++) {
char path[MAX_INTEGER_LENGTH + sizeof(szPostfix) + 1];
sprintf(path,"%d%s",i, szPostfix);
cards[i-1] = new Card(i,path);
}
ShuffleArray(cards);
for (int i = 0; i < 20; i++) {
deck->PushTop(cards[i]);
}
}
void Swap(Card* a, Card* b) {
Card temp = *a;
*a = *b;
*b = temp;
}
void ShuffleArray(Card** cardArray) {
srand(dbTimer());
for (int i = 0; i < 20; i++)
Swap(cardArray[i],cardArray[rand()%20]);
}
I think where I screwed up is in the card[i] = new Card(...) line, but it somehow looks right to me.
Any suggestions would be appreciated.
DISCLAIMER: I know I should be using the standard library for most of this stuff, but I'm trying to teach myself the hard stuff first. It's just the way I learn.
EDIT: I fixed the index problem. Now I've just gotta figure out why some image aren't drawing now... :/ Thanks for the help!
Your code has many problems
You are looping with 1 <= i <= 20 but for an array of 20 elements indexing goes from 0 <= index <= 19. You need to use cards[i-1] = new Card(i,path);
You are allocating the array of pointers cards but you are not deallocating it (memory leak). Either deallocate it with delete[] cards; once you are done or just use a stack based array with Card *cards[20]; instead of allocating it with new.
The way you compute MAX_INTEGER_LENGTH shows you don't really understand what sizeof does.
This is the reason for which the cards don't get shuffled. You wrote a function that swaps two pointers, but the pointers it is swapping are local variables (parameters) of the function, not the elements of the array. One solution is to pass the parameters as pointer references by declaring swap with void Swap(Card *& a, Card *& b), another solution would be passing pointers to pointers (but this would require a more complex syntax of the implementation because of the double indirection and would also require a change in the way you call the function).
In the first for loop your starting index is 0, while in the second for loop the starting index is 0. That could be the problem.
Your code:
for(int i = 1; i < 21; i++) {
char path[MAX_INTEGER_LENGTH + sizeof(szPostfix) + 1];
sprintf(path,"%d%s",i, szPostfix);
cards[i] = new Card(i,path);
}
Here the loop should start from 0 to 20 as:
for(int i = 1 ; i < 21; i++) //incorrect - original code
for(int i = 0 ; i < 20; i++) //correct - fix
And after the fix, you could use i+1 instead of i in :
sprintf(path,"%d%s",i+1, szPostfix);
cards[i] = new Card(i+1,path);
if that is required.