| CodeGuru Home | VC++ / MFC / C++ | .NET / C# | Visual Basic | Newsletters | VB Forums | Developer.com |
|
|||||||
| C++ (Non Visual C++ Issues) Ask or answer C and C++ questions not related to Visual C++. This includes Console programming, Linux programming, or general ANSI C++. |
![]() |
|
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
#1
|
|||
|
|||
|
Declaring & initializing dynamic array of pointers question?
Hello
First time trying out the Code Guru forums, so here it goes. I just completed a first quarter course in Java, and now I’m jumping into a second quarter course in C++. (this is a big jump, first time using pointers & dynamic arrays) I’ve been working on this project for 8 hours now, and I’m stuck at this part in which I need to convert a static array to a dynamic array of pointers, not sure what I’m doing wrong here, hoping someone could point out exactly what it is I’m doing wrong & point me in the right direction as far as fixing it. I got the following problem: Header area int MaxDBsize; struct InvRec { int Part ID; float Price; }; typedef InvRec *InvRecptr; typedef InvRecptr arr[]; //line 23 void main() { ... Cin >> MaxDBsize; arr index = new arr[MaxDBsize] //line73 ... } 1) I get the following error codes: error C2057 ‘<unknown>:’ missing subscript and error C2440 ‘initializing’: cannot convert from ‘struct InvRec *(*)[1]’ to ‘struct InvRec *[]’ 2) among the many things I tried to fix it was changing line 23 to: arr InvRecptr[]; but I get the following errors: : missing ';' before identifier 'InvRecptr' : missing storage-class or type specifiers : fatal error C1004: unexpected end of file found In the first case my reasoning was: declare arr as an array type of inventory record pointers, on line 23, and initialize index (line 73) as an instance of dynamic arr type with a size (MaxDBsize) entered by the user input (cin). I don’t know exactly why this approach fails. In case 2 I tried declaring a variable, arr, as an array of inventory records, and initializing it in line 73, otherwise same reasoning as above. So, what am I doing wrong, and how do I fix it? before I rip the rest of my hair out’ve my head. |
|
#2
|
|||
|
|||
|
Re: Declaring & initializing dynamic array of pointers question?
Please don't pull your hair out!
![]() Change MaxDBsize from int to const int. That will eliminate error C2057. Next, get rid of the typedef statements and replace this line: Code:
arr index = new arr[MaxDBsize]; Code:
InvRec* index = new InvRec[MaxDBsize]; |
|
#3
|
|||
|
|||
|
Re: Declaring & initializing dynamic array of pointers question?
Is there any special reason why you dyanmically need to allocate? This isn't usually necessary in C++, take a look at the following introduction to the 'vector' class...which is the common way of dealing with arrays...
__________________
Ciao, Andreas "Software is like sex, it's better when it's free." - Linus Torvalds Article(s): Allocators (STL) Function Objects (STL) |
|
#4
|
|||
|
|||
|
Re: Declaring & initializing dynamic array of pointers question?
Quote:
Quote:
Quote:
Also, I thnk you should retake the class with better teacher and/or course material. Why? This: Code:
void main() http://www.parashift.com/c++-faq-lit....html#faq-29.3 Also, don't type your code into the message window. Copy and paste it in the CodeGuru message window from your code editor. The reason is that there is no way for someone to know whether that typo error is the reason for compiler errors or not. For example: Code:
Cin Code:
cin As to your code: Code:
#include <iostream>
int MaxDBsize;
struct InvRec
{
int PartID;
float Price;
};
typedef InvRec *InvRecptr;
int main()
{
InvRecptr arr;
std::cin >> MaxDBsize;
arr = new InvRec[MaxDBsize];
delete [] arr;
}
Code:
#include <iostream>
#include <vector>
int MaxDBsize;
struct InvRec
{
int PartID;
float Price;
};
typedef std::vector<InvRec> InvRecArray;
int main()
{
InvRecArray arr;
std::cin >> MaxDBsize;
arr.resize( MaxDBSize );
}
On a side note, teaching pointers and dynamic allocation before teaching vector is IMO the wrong approach to teaching C++. Even the author of the language, Stroustrup, plus many books ("Accelerated C++" for example), also recommend that teaching the student standard classes should be emphasized first instead of hard to use pointers: http://www.research.att.com/~bs/new_learning.pdf The idea is to get the programmer into writing useful, bug-free programs as quicky as possible. To do this, you introduce them to things such as string classes instead of char arrays and pointers, vectors instead of new[]/delete[], etc. Pointers and dynamic allocation are necessary, but they are unnecessary for purposes of creating dynamic arrays. Regards, Paul McKenzie |
|
#5
|
||||
|
||||
|
Re: Declaring & initializing dynamic array of pointers question?
[ moved thread ]
__________________
Marius BancilaHome Page | Blog My CodeGuru articles My latest articles: A TR1 Tutorial: array, tuple, unordered containers, random number generators, regex, smart pointers Customizable alert window Try my VSBuildStatus add-in for Visual Studio 2005, 2008 & 2010 (v1.1). I do not offer technical support via PM or e-mail. Please use vbBulletin codes. |
|
#6
|
|||
|
|||
|
Re: Declaring & initializing dynamic array of pointers question?
Hello:
Thanks for all the help guys. Well the reason I didn't use vectors is that we haven't got to that point yet in the book. I'm sure we'll probably get to that point sometime in the future, in this class or some other class. The textbook we're using is Data Structures and other objects using C++ (Main, Savitch), and chapter 4 is dynamic arrays and pointers. The first project is to convert a static array problem to a dynamic array of pointers & manipulate the functions that way (move pointers instead of Data items). The instuctor provided the base program and we have to "change" it. You're right, should've copied and pasted instead of writing out the appropriate section (it was cin instead of Cin). I now got the declaration and the initialization of the Array to work using the first posters suggestion, thanks btw. But, I guess you're right, it's a dynamic array of structures and not pointers, it needs to be a dynamic array of pointers though. I got another typedef definition under the header, which is: typedef InvRecptr * indexarr // pointer to a dynamic array of inventory record pointers. I tried to change my line 73 index initialization to: InvRec* index = new InvRecptr[MaxDBsize]; (In order to create a dynamic array of pointers) but I get the following error code: : error C2440: 'initializing' : cannot convert from 'struct InvRec ** ' to 'struct InvRec *' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast I’m just starting out with C++ now, so I’m not up with these error codes at all yet. From what I interpret, somehow, using the above initialization, the index (which is an inventory record pointer type) is pointing to a double pointer array (**) of inventory records? I don’t understand how the double pointer ** error is cropping up and/or creeping into the initialization? There is a second problem I am trying to fix .... I altered all the remaining function parameters, after using the new index array initialization (which may not be the right definition, since it’s an array of structures) of: InvRec* index = new InvRecptr[MaxDBsize]; .... which is this structure type error. It involves the following two functions (which I copied and pasted): void readrec (InvRec*& rec) //line89 /*Pre: Input available as expected. Post: Record rec filled with input data.*/ { int x; float y; //InvRec z; int *xptr; float *yptr; cin >> x; cin >> y; //cin >> rec.PartID; //cin >> rec.Price; //rec.PartID =x; //rec.Price=y; xptr->rec.PartID; //line 109 yptr->rec.Price; //line 110 *xptr = x; *yptr = y; cout << "1 test de-ref xptr: " << *xptr << endl; //test to see what is stored cout << "2 test de-ref yptr: " << *yptr << endl; //test to see what is stored }; void readdata (arr DB, int & size) /*Pre: DB is an array of MAXDBSIZE inventory records. Post: 0<=size<=MAXDBSIZE and the first "size" elements of the DB array are filled with input data.*/ { void readrec (InvRec*&); char YN; int *sizeptr = &size; size = 0; do { cout << "More data (Y/y/N/n)? " << endl; cin >> YN; if ((YN == 'Y') || (YN == 'y')) if (size < MaxDBsize) (readrec (DB[size++]); //line 136 << DB[size] << endl; else cout << "Database size may not exceed "<< MaxDBsize << endl; else if ((YN != 'N') && (YN != 'n')) cout << "Please answer Y/y/N/n. "; } while ((YN != 'N') && (YN != 'n')); //DB = new arr[size]; }; All the commented-out stuff are things that I’ve tried & failed with. In the do-while loop of the readdata function, line 136, I’m passing arr DB as an actual parameter to the readrec function, line 89, it’s one element of an array of pointers (at least that’s what I want), but the problem is, I think, that I’m trying to simultaneously do two things in one function, namely: 1) read a structure record composed of a PardID and Price (read record), and 2) while reading in the structure element using user input, simultaneously make it a pointer, so that it doesn’t mismatch with the Formal function parameter, line 89. I may not be approaching it correctly. But anyway, I get the following error codes: : error C2227: left of '->rec' must point to class/struct/union //line 109 : error C2228 left of '.PartID' must have class/struct/union type //line 109 : error C2227: left of '->rec' must point to class/struct/union //line 110 : error C2228: left of '.Price' must have class/struct/union type //line 110 Is it that the class/struct/union type is an array element, a referance pointer Parameter (InvRec*& rec), instead of (InvRec& rec)? But I want it to be an array of pointers so how would I both do: 1) user-input the rec data structure element and 2) maintain an array of pointers (without having to completely change the array type)? Or is it that I just have a simple syntax error in lines 109 & 110, and if so what is the syntax? Thanks again for all the help, rk But the way, what area did they move this thread to? I assumed it was visual C++ programming because that is the C++ program type that we're using in the class. |
|
#7
|
|||||||
|
|||||||
|
Re: Declaring & initializing dynamic array of pointers question?
Quote:
You may have misunderstood the assignment. The only thing that can be converted is an array of T to a dynamic array of T. To do this, yes, you need pointers, where T* is the pointer to the first T, *(T+1) is the second T, *(T+2) is the third T, etc.. The major reasons for T** is if you are 1) Creating a two-dimensional array of type T dynamically 2) You are passing a T* to a function that will initialize the T* to some value Are you doing any of these? If not, then your assignment, sorry to say, doesn't make sense. Quote:
Quote:
Code:
T** p;
p = new T*[10];
for ( int i = 0; i < 10; ++i )
p[i] = new T;
Is this what you're looking for? But it still doesn't match the original problem of array of T to a dynamic array of T. This is where it not only confuses you, it's confusing me. See the reasons for a T** earlier in my post. Quote:
Quote:
Code:
T *a; a = new T[5]; // for example The easiest way to look at it is that the word "array" means to tack on a "*". So when you have an array of T*, you are dealing with "**" -- one "*" for the array, and the other for the T* element of each item in the array. Quote:
Quote:
Your code is generic C++, which is why it was moved to the non-Visual C++ section -- there is nothing in it that is specific to Visual C++, i.e. MFC, ATL or some other class library used by Visual C++. It is all plain C++. Regards, Paul McKenzie Last edited by Paul McKenzie; September 3rd, 2005 at 05:09 PM. |
|
#8
|
|||
|
|||
|
Re: Declaring & initializing dynamic array of pointers question?
Quote:
Code:
type* identifier = new type[array_size]; Code:
// option A - creating an array of InvRec objects InvRec* index = new InvRec[MaxDBSize]; Code:
// option B - creating an array of pointers-to-InvRec InvRec** index = new InvRec*[MaxDBSize]; Code:
InvRec* index = new InvRec*[MaxDBSize]; // doesn't work - new[] returns an InvRec** // and you can't assign an InvRec** to an InvRec*
__________________
Si fractum non sit, noli id reficere. |
|
#9
|
|||
|
|||
|
Re: Declaring & initializing dynamic array of pointers question?
Take a look at these code snippets.
Statically allocated array of objects: Code:
struct T
{
int Data1;
double Data2;
};
T Arr[10];
int main(int argc, char* argv[])
{
//initialization
for (int i=0; i<10; i++)
{
Arr[i].Data1 = 1;
Arr[i].Data2 = 1.2345;
}
return 0;
}
Code:
struct T
{
int Data1;
double Data2;
};
T* Arr[10];
int main(int argc, char* argv[])
{
int i;
//initialization
for (i=0; i<10; i++)
{
Arr[i] = new T;
Arr[i]->Data1 = 1;
Arr[i]->Data2 = 1.2345;
}
//cleanup
for (i=0; i<10; i++)
delete Arr[i];
return 0;
}
Code:
struct T
{
int Data1;
double Data2;
};
int main(int argc, char* argv[])
{
int i;
//initialization
T* Arr = new T[10];
for (i=0; i<10; i++)
{
Arr[i].Data1 = 1;
Arr[i].Data2 = 1.2345;
}
//cleanup
delete[] Arr;
return 0;
}
Code:
struct T
{
int Data1;
double Data2;
};
int main(int argc, char* argv[])
{
int i;
//initialization
T** Arr = new T*[10];
for (i=0; i<10; i++)
{
Arr[i] = new T;
Arr[i]->Data1 = 1;
Arr[i]->Data2 = 1.2345;
}
//cleanup
for (i=0; i<10; i++)
delete Arr[i];
delete[] Arr;
return 0;
}
Code:
struct T
{
int Data1;
double Data2;
T(int D1 = 0, double D2 = 0){Data1 = D1; Data2 = D2;}
};
int main(int argc, char* argv[])
{
vector<T> Arr;
//initialization
for (int i=0; i<10; i++)
Arr.push_back(T(1, 1.2345));
return 0;
}
|
|
#10
|
|||
|
|||
|
Re: Declaring & initializing dynamic array of pointers question?
Quote:
Code:
void readrec (InvRec*& rec) //line89
/*Pre: Input available as expected.
Post: Record rec filled with input data.*/
{
cin >> rec->PartID;
cin >> rec->Price;
}
Code:
void readrec (InvRec& rec) //line89
/*Pre: Input available as expected.
Post: Record rec filled with input data.*/
{
cin >> rec.PartID;
cin >> rec.Price;
}
__________________
Si fractum non sit, noli id reficere. Last edited by HighCommander4; September 3rd, 2005 at 06:57 PM. |
|
#11
|
|||
|
|||
|
Re: Declaring & initializing dynamic array of pointers question?
Thanks for all your help guys. I'm going to go through my whole program from top to bottom again, and take in what everyone has said. You guys helped me understand quite a bit what was going on behind-the-scenes that I didn't fully understand before. If I still have problems, I'll post the whole enchilada tomorrow night .. been at this for about 16 hours now for 3/4 days. Thank god it's not due until the 12th, so I still got plenty of time to work on it. My instructor has been in China for a week now, so the class hasn't been able to contact him for office hours, email help ... that's mainly why I posted my questions on this forum, and I'm glad I did so.
|
|
#12
|
|||
|
|||
|
Re: Declaring & initializing dynamic array of pointers question?
Well I finally got the program to pass the compiler, unfortunately it failed in the link phase during build. Unfortunately the link error doesn't point me out an exact line number for my to narrow down the problem. The error code & still-in-work program (getting close) is as follows:
link errors: Linking... : error LNK2001: unresolved external symbol "void __cdecl sortbyPartID(struct InvRec * *,int)" (?sortbyPartID@@YAXPAPAUInvRec@@H@Z) : error LNK2001: unresolved external symbol "void __cdecl printdata(struct InvRec * *,int)" (?printdata@@YAXPAPAUInvRec@@H@Z) : error LNK2001: unresolved external symbol "void __cdecl readdata(struct InvRec * *,int &)" (?readdata@@YAXPAPAUInvRec@@AAH@Z) Debug/P1WarmUp.exe : fatal error LNK1120: 3 unresolved externals Error executing link.exe. P1WarmUp.exe - 4 error(s), 0 warning(s) but the compiler worked! my code as far as now is: Code:
#include <iostream.h>
int MaxDBsize;
/*Type delcarations - NO MEMORY ALLOCATED (EVEN STATICALLY)*/
struct InvRec /*Inventory record with its fields*/
{
int PartID;
float Price;
};
typedef InvRec *InvRecptr; /*Inventory record pointer type*/
typedef InvRec* arr[];
arr index;
typedef InvRecptr *indexarr; /* Pointer to a dynamic array of inventory record pointers*/
void deallocate (indexarr & ptrs, int & size)
{
for (int i=0; i<size; i++) delete (ptrs[i]);
delete ptrs;
ptrs = NULL;
size = 0;
};
void main ()
{
void readdata (InvRec**, int &);
void sortbyPartID (InvRec**, int);
void printdata (InvRec**, int);
cout << "Enter a size amount for the index array: " << endl;
cin >> MaxDBsize;
InvRec** index = new InvRec*[MaxDBsize];
int dbsize;
char temp;
readdata (index, dbsize);
cout << "Original data:" << endl;
printdata (index, dbsize);
sortbyPartID (index, dbsize);
cout << "Data sorted by PartID:" << endl;
printdata (index, dbsize);
cout << "Please input a non-white space key to end the session." <<endl;
cin >> temp;
};
void readrec (InvRec*& rec)
/*Pre: Input available as expected.
Post: Record rec filled with input data.*/
{
cin >> rec->PartID;
cin >> rec->Price;
};
void readdata (arr DB, int & size)
/*Pre: DB is an array of MAXDBSIZE inventory records.
Post: 0<=size<=MAXDBSIZE and the first "size" elements of the DB array are
filled with input data.*/
{
void readrec (InvRec*&);
char YN;
size = 0;
do
{
cout << "More data (Y/y/N/n)? " << endl;
cin >> YN;
if ((YN == 'Y') || (YN == 'y'))
if (size < MaxDBsize)
readrec (DB[size++]);
else cout << "Database size may not exceed " << MaxDBsize << endl;
else if ((YN != 'N') && (YN != 'n')) cout << "Please answer Y/y/N/n. ";
}
while ((YN != 'N') && (YN != 'n'));
};
void printrec (InvRec* rec)
/*Pre: rec has data.
Post: The data in rec printed out.*/
{
int x;
float y;
int *xptr;
float *yptr;
xptr = &x;
yptr = &y;
cout << *xptr << ' ' << *yptr << endl;
};
void printdata (arr DB, int size)
/*Pre: 0<=size<=MAXDBSIZE and the first "size" elements of the DB array are
inventory records containing data.
Post: They are all printed out in the order pointed at.*/
{
void printrec (InvRec*);
int i;
for (i=0; i<size; i++) printrec(DB[i]);
};
void swap (InvRec *& x, InvRec *& y)
/*Pre: None.
Post: The values of x and y are swapped.*/
{
InvRec *temp;
temp = x;
x = y;
y = temp;
};
int selectsmallestPartID (arr DB, int first, int last)
/*Pre: "first" through "last" elements of the DB array are inventory
records containing data.
Post: A value k is returned such that, for i ranging from first to last,
the relation DB[k].PartID <= DB[i].PartID holds.*/
{
int j, result;
result = first;
int *jptr=&j, *resultptr=&result, *firstptr=&first;
for (j=first+1; j<=last; j++)
if (DB[*jptr] < DB[*resultptr]) resultptr = jptr;
//if (DB[j].PartID < DB[result].PartID) result = j;
return *resultptr;
};
void sortbyPartID (arr DB, int size)
/*Pre: 0<=size<=MAXDBSIZE and the first "size" elements of the DB array are
inventory records containing data.
Post: for i ranging from 1 to size-2, the relation DB[i].PartID <=
DB[i+1].PartID holds.*/
{
int selectsmallestPartID (arr, int, int);
int i, smallindex;
int *iptr=&i, *smallindexptr=&smallindex;
for (i=0; i<=size-2; i++)
{
smallindex = selectsmallestPartID (DB, i, size-1);
swap (DB[i], DB[smallindex]);
//swap (DB[iptr], DB[smallindexptr]);
};
};
The link error says unresolved external symbol void, what does that mean? .. the functions that it references are supposed to have a void return type, so I don't understand what is going on there? Gotta hit the sack here this program is draining & it's hard to concentrate late at night. Last edited by Corporal Kindel; September 4th, 2005 at 07:18 PM. |
|
#13
|
||||
|
||||
|
Re: Declaring & initializing dynamic array of pointers question?
The errors are not : unresolved external symbol void, but:
unresolved external symbol "void __cdecl sortbyPartID(struct InvRec * *,int)" (?sortbyPartID@@YAXPAPAUInvRec@@H@Z), etc... It means that the function : void sortbyPartID (InvRec**, int) is imported from the module, but is not defined in any module. I suppose that it may be due to the difference between the declaration and the definition of the functions. Firstly you should change this line: Code:
typedef InvRec* arr[]; Replace it with: Code:
typedef InvRec** arr; Code:
arr index; // this variable is never used! But, i suggest that you change the declarations: Code:
void readdata (InvRec**, int &); void sortbyPartID (InvRec**, int); void printdata (InvRec**, int); Code:
void readdata (arr, int &); void sortbyPartID (arr, int); void printdata (arr, int); If it does not work, try to put the function declarations outside the main function (i remember that once, i had a bug with a compiler which don't mangled function name in local declarations). Finally, use int main(), not void main() And, please, use code tags. To, do so, enclose your code, with tags like that: [ C O D E] the code here [ / C O D E ] But, don't put the space characters in the tags : i just put them to avoid that the forum interpret them as real code tags. Note also that there is a '/' character in the closing markup. |
|
#14
|
|||
|
|||
|
Re: Declaring & initializing dynamic array of pointers question?
Ok, finally got my program to compile & build, unfortunately, I get the following error at runtime (the program stops during runtime with an exception, and clicking on debug points me to the following program snipit which I copied and pasted below). The error code pointer points to the else n = (int) value; line near the bottom. My program is going to kill me before I'm done with it. Note: the error code program snipit that fails is not even part of my original program.
I need to figure out what this error is (or where it's referring to in my program, which is not clearly defined). I take it that the cin >> (istream operator) is failing in my program somewhere? Is it possible to determine exactly where the istream operator is failing in my program & why? Also, why is the istream operator failing when I have the library #include <iostream.h> correctly included in the header of my program? Code:
/***
* istrint.cpp - definitions for istream class operaotor>>(int) member functions
*
* Copyright (c) 1991-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
* Definitions of operator>>(int) member function(s) for istream class.
* [AT&T C++]
*
*******************************************************************************/
#include <cruntime.h>
#include <internal.h>
#include <stdlib.h>
#include <limits.h>
#include <iostream.h>
#pragma hdrstop
/***
*istream& istream::operator>>(int& n) - extract int
*
*Purpose:
* Extract int value from stream
*
*Entry:
* n = value to update
*
*Exit:
* n updated, or ios::failbit & n=INT_MAX/INT_MIN on overflow/underflow
*
*Exceptions:
* Stream error on entry or value out of range
*
*******************************************************************************/
istream& istream::operator>>(int& n)
{
_WINSTATIC char ibuffer[MAXLONGSIZ];
long value;
char ** endptr = (char**)NULL;
if (ipfx(0))
{
value = strtol(ibuffer, endptr, getint(ibuffer));
if (value>INT_MAX)
{
n = INT_MAX;
state |= ios::failbit;
}
else if (value<INT_MIN)
{
n = INT_MIN;
state |= ios::failbit;
}
else
n = (int) value;
isfx();
}
return *this;
}
Last edited by Corporal Kindel; September 4th, 2005 at 07:16 PM. |
|
#15
|
|||
|
|||
|
Re: Declaring & initializing dynamic array of pointers question?
This is incorrect:
Code:
#include <iostream.h> Also, please use code tags. Regards, Paul McKenzie |
![]() |
| Bookmarks |
|
||||||
| Thread Tools | Search this Thread |
| Display Modes | Rate This Thread |
|
|