help with dynamic array structure.

J

John Carson

Steven Taylor said:
I'm learning C++ from C++ Primer Plus 5th edition. I'm struggling at
the moment with declaring an array of three structures by using 'new'
to allocate memory. (this is one of the programming exercises at
the end of each chapter). My attempt is as per below. I get a
compile error indicating that -

"base operand of '->' has no pointer type 'candybar' "

// Q-09.cpp -- Question 9
#include <iostream>
struct candybar
{
//char brand[20];
std::string brand; //in this context - must use std::string
float weight;
int calories;
};
int main()
{
using namespace std;
candybar * snack = new candybar[3];

snack[0]->brand = "Mocha Munch"; // above error starts here
snack[0]->weight = 2.3;
snack[0]->calories = 350;


Replace all of the -> operators with the . operator.

snack is a pointer, but using the subscript operator dereferences the
pointer. Thus snack[0] is of type candybar, not pointer to candybar.
 
K

Karl Heinz Buchegger

Steven said:
I'm learning C++ from C++ Primer Plus 5th edition. I'm struggling at
the moment with declaring an array of three structures by using 'new' to
allocate memory. (this is one of the programming exercises at the end
of each chapter). My attempt is as per below. I get a compile error
indicating that -

"base operand of '->' has no pointer type 'candybar' "

// Q-09.cpp -- Question 9
#include <iostream>
struct candybar
{
//char brand[20];
std::string brand; //in this context - must use std::string
float weight;
int calories;
};
int main()
{
using namespace std;
candybar * snack = new candybar[3];

snack[0]->brand = "Mocha Munch"; // above error starts here

Your problem is here.
It is the way array indexing is defined in C++

a[index] is equivalent to *(a_as_ptr+index)

where a_as_ptr denotes a pointer to the first element of the array.

What you wanted to write was:

snack pointer
snack+0 index offset of index 0 to that pointer
*(snack+0) object at the index offset to that pointer
(*(snack+0)).brand the brand component of the object at the index
offset to that pointer

Due to the way array indexing is defined you can replace parts of the last expression.

(*(snack+0)).brand is equivalent to

snack[0].brand

So in short:
Even if snack is a pointer, snack[0] is no longer of pointer type, but is already
the object in the array. Therefore you don't use ->, but simply access the component
directly with a '.' operation.
 
Y

yinquan

John Carson said:
Steven Taylor said:
I'm learning C++ from C++ Primer Plus 5th edition. I'm struggling at
the moment with declaring an array of three structures by using 'new'
to allocate memory. (this is one of the programming exercises at
the end of each chapter). My attempt is as per below. I get a
compile error indicating that -

"base operand of '->' has no pointer type 'candybar' "

// Q-09.cpp -- Question 9
#include <iostream>
struct candybar
{
//char brand[20];
std::string brand; //in this context - must use std::string
float weight;
int calories;
};
int main()
{
using namespace std;
candybar * snack = new candybar[3];

snack[0]->brand = "Mocha Munch"; // above error starts here
snack[0]->weight = 2.3;
snack[0]->calories = 350;


Replace all of the -> operators with the . operator.

snack is a pointer, but using the subscript operator dereferences the
pointer. Thus snack[0] is of type candybar, not pointer to candybar.
==================================================
This Programme has a litte problem.First using string class ,you must use
headfile <string>
The other hand,I suggest you'd better use form like string a (" ") to
initiate variable of string class.
 
H

Howard

Karl Heinz Buchegger said:
Even if snack is a pointer, snack[0] is no longer of pointer type, but is
already
the object in the array. Therefore you don't use ->, but simply access the
component
directly with a '.' operation.

Really? Wow...that's just strange. I guess I've never used an array of
pointers like that, because I sure didn't know this. (I tend to use vectors
nowadays for most dynamic array uses.)

So, suppose I actually _need_ a pointer from that array. How do I get it?

Like this?

candybar* pBar = &(snack); // Like this?

That sure seems odd.

Somehow, I thought I'd used this kind of notation before somewhere:

(snack)->name = "Snickers";

Would that work?

-Howard
 
J

John Carson

Howard said:
Karl Heinz Buchegger said:
Even if snack is a pointer, snack[0] is no longer of pointer type,
but is already
the object in the array. Therefore you don't use ->, but simply
access the component
directly with a '.' operation.

Really? Wow...that's just strange. I guess I've never used an array
of pointers like that, because I sure didn't know this. (I tend to
use vectors nowadays for most dynamic array uses.)

There is no array of pointers, just a pointer to an dynamically allocated
array. The pointer name functions just the same as the name of a statically
allocated array in terms of accessing elements of the array.
So, suppose I actually _need_ a pointer from that array. How do I
get it?
Like this?

candybar* pBar = &(snack); // Like this?


snack is a pointer, as is snack + i, so you can write:

candybar* pBar = snack + i;
That sure seems odd.

Not to me. Using a subscript on a pointer is equivalent to dereferencing
the pointer. To make the point clear, consider:

int x = 1;
int *ptr = &x;

Then ptr[0] is the same as *ptr, i.e., it is equivalent to x.
Somehow, I thought I'd used this kind of notation before somewhere:

(snack)->name = "Snickers";

Would that work?


No.
 
H

Howard

There is no array of pointers, just a pointer to an dynamically allocated
array.


D'oh! I got confused. Somehow, I was thinking that he'd allocated an array
of pointers. But, that would have been:

candybar** snack = new (candybar*)[10];

My bad. I'll go slink off into a corner and hide my face now.

-Howard
 
B

Benny Andersen

On Fri, 01 Apr 2005 22:27:10 -0800, Steven Taylor

Besides, what is mentioned, you have to use:
delete[] , when deallocating what was allocated using new objects[]

Regards
Benny Andersen
 
J

John Carson

Steven Taylor said:
yinquan wrote:
snip

I was/am a little confused about this as well. When changing the
arrow membership to dot membership form - as suggested by other
posters, the program compiled and ran as intended, without the
"#include <string>" preprocessor directive. I'm not sure why, as I
thought the 'include' file is required.

Steve Taylor

Sometimes one header file will #include another header file, which in turn
may #include another, which may #include another... Apparently on your
system the iostream header #includes the string header, either directly or
indirectly. This is implementation dependent and shouldn't be relied on. So,
yes, you should #include the string header.
 
E

Evan

Theoretically I think it should be, but a lot of compilers include
stuff by default without telling you. Whatever compiler you're using
may be doing the same thing.

As an alternative, <iostream> might be including <string> within it. I
don't know if this is allowed by the standard or not.

(This is OT, but speaking of the standard, do you guys think it's
useful to get? You can buy the PDF version for pretty cheap and I think
I could print it for free and plop it into a binder, but do you think
it's something that is of use beyond compiler and other language tool
development?)
 
S

Steven Taylor

I'm learning C++ from C++ Primer Plus 5th edition. I'm struggling at
the moment with declaring an array of three structures by using 'new' to
allocate memory. (this is one of the programming exercises at the end
of each chapter). My attempt is as per below. I get a compile error
indicating that -

"base operand of '->' has no pointer type 'candybar' "

// Q-09.cpp -- Question 9
#include <iostream>
struct candybar
{
//char brand[20];
std::string brand; //in this context - must use std::string
float weight;
int calories;
};
int main()
{
using namespace std;
candybar * snack = new candybar[3];

snack[0]->brand = "Mocha Munch"; // above error starts here
snack[0]->weight = 2.3;
snack[0]->calories = 350;

snack[1]->brand = "Crunchie";
snack[1]->weight = 1.9;
snack[1]->calories = 400;

snack[2]->brand = "Mars Bar";
snack[2]->weight = 4.5;
snack[2]->calories = 200;

cout << endl;
cout << "Snack brand : " << snack[0]->brand << endl;
cout << "Snack weight : " << snack[0]->weight << endl;
cout << "Snack calories : " << snack[0]->calories << endl;

cout << "Snack brand : " << snack[1]->brand << endl;
cout << "Snack weight : " << snack[1]->weight << endl;
cout << "Snack calories : " << snack[1]->calories << endl;

cout << "Snack brand : " << snack[2]->brand << endl;
cout << "Snack weight : " << snack[2]->weight << endl;
cout << "Snack calories : " << snack[2]->calories << endl;

delete snack;
return 0;
}

Any help would be appreciated, I really can't see why this shouldn't
work. I read the chapter umpteen times but I must be missing something.

Steve Taylor
Melbourne, Australia.
 
S

Steven Taylor

John said:
I'm learning C++ from C++ Primer Plus 5th edition. I'm struggling at
the moment with declaring an array of three structures by using 'new'
to allocate memory. (this is one of the programming exercises at
the end of each chapter). My attempt is as per below. I get a
compile error indicating that -

"base operand of '->' has no pointer type 'candybar' "

// Q-09.cpp -- Question 9
#include <iostream>
struct candybar
{
//char brand[20];
std::string brand; //in this context - must use std::string
float weight;
int calories;
};
int main()
{
using namespace std;
candybar * snack = new candybar[3];

snack[0]->brand = "Mocha Munch"; // above error starts here
snack[0]->weight = 2.3;
snack[0]->calories = 350;



Replace all of the -> operators with the . operator.

snack is a pointer, but using the subscript operator dereferences the
pointer. Thus snack[0] is of type candybar, not pointer to candybar.

Thanks for your hlep John, it certainly compiled ok.

Steve.
 
S

Steven Taylor

Karl Heinz Buchegger wrote:
snip
Your problem is here.
It is the way array indexing is defined in C++

a[index] is equivalent to *(a_as_ptr+index)

where a_as_ptr denotes a pointer to the first element of the array.

What you wanted to write was:

snack pointer
snack+0 index offset of index 0 to that pointer
*(snack+0) object at the index offset to that pointer
(*(snack+0)).brand the brand component of the object at the index
offset to that pointer

Due to the way array indexing is defined you can replace parts of the last expression.

(*(snack+0)).brand is equivalent to

snack[0].brand

So in short:
Even if snack is a pointer, snack[0] is no longer of pointer type, but is already
the object in the array. Therefore you don't use ->, but simply access the component
directly with a '.' operation.
Thanks, much appreciated.

Steve Taylor
 
S

Steven Taylor

yinquan wrote:
snip
==================================================
This Programme has a litte problem.First using string class ,you must use
headfile <string>
The other hand,I suggest you'd better use form like string a (" ") to
initiate variable of string class.

I was/am a little confused about this as well. When changing the arrow
membership to dot membership form - as suggested by other posters, the
program compiled and ran as intended, without the "#include <string>"
preprocessor directive. I'm not sure why, as I thought the 'include'
file is required.

Steve Taylor
 
K

Karl Heinz Buchegger

Howard said:
Karl Heinz Buchegger said:
Even if snack is a pointer, snack[0] is no longer of pointer type, but is
already
the object in the array. Therefore you don't use ->, but simply access the
component
directly with a '.' operation.

Really? Wow...that's just strange. I guess I've never used an array of
pointers like that,

Look closely.
The OP did not allocate an array of pointers.
He allocted an array of objects. Bu the did it in a dynamic
way und thus has a pointer to that array.


--
Karl Heinz Buchegger, GASCAD GmbH
Teichstrasse 2
A-4595 Waldneukirchen
Tel ++43/7258/7545-0 Fax ++43/7258/7545-99
email: (e-mail address removed) Web: www.gascad.com

Fuer sehr grosse Werte von 2 gilt: 2 + 2 = 5
 
K

Karl Heinz Buchegger

Evan said:
Theoretically I think it should be, but a lot of compilers include
stuff by default without telling you. Whatever compiler you're using
may be doing the same thing.

As an alternative, <iostream> might be including <string> within it. I
don't know if this is allowed by the standard or not.

(This is OT, but speaking of the standard, do you guys think it's
useful to get? You can buy the PDF version for pretty cheap and I think
I could print it for free and plop it into a binder, but do you think
it's something that is of use beyond compiler and other language tool
development?)

Depends on what you seek.
If you are an ordinary programmer which needs some form of reference
then I would not suggest the reference. It is written very technically
and for a lot of thins you need to be a detective to figure out why
things are the way they are. There are better books out there
for the purpose of serving as a language reference.
But if you seek some literature to settle discussions about language issues
you will need the Standard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top