473,320 Members | 2,073 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

What's the best/a good way to access a variable member of an array of structs?

Hi,

I'm just learning cpp, and the exercise I'm working on is basically as
follows:

1) Create a struct type with 4 members (char, char, char, int).
2) Create an array of, say 3 instances of the struct, and populate them
with data.
3) cin 1, 2, 3, or 4 from the user
4) If the user selected, say, 2, display the contents of the 2nd data
member from each of the structs in the array. Similarly for 1,3, and 4.

I'm trying to find an elegant way to achieve 4).

It's easy to achieve the functionality with a set of ifs/for loops (if
input=1, then for loop thru the struct array, cout <<
stuctInstance[i].FirstMember ....)

But this seems grossly inelegant, as I'm essentially writing the same
for-loop code 4 times - once for each input possibility. I would like
NO ifs, and just ONE for loop, whose key statement intuitively looks
like:

cout << structInstance[i].whicheverMemberTheUserSelected

Does it make sense what I'm looking to do? Is there a standard/elegant
way to achieve this? If I'm not making sense, I'll just post the
"inelegant" solution I have...
tia!

cdj

Apr 21 '06 #1
10 2373
sh*************@gmail.com wrote:
Hi,

I'm just learning cpp, and the exercise I'm working on is basically as
follows:

1) Create a struct type with 4 members (char, char, char, int).
2) Create an array of, say 3 instances of the struct, and populate them
with data.
3) cin 1, 2, 3, or 4 from the user
4) If the user selected, say, 2, display the contents of the 2nd data
member from each of the structs in the array. Similarly for 1,3, and 4.

I'm trying to find an elegant way to achieve 4).

It's easy to achieve the functionality with a set of ifs/for loops (if
input=1, then for loop thru the struct array, cout <<
stuctInstance[i].FirstMember ....)

But this seems grossly inelegant, as I'm essentially writing the same
for-loop code 4 times - once for each input possibility. I would like
NO ifs, and just ONE for loop, whose key statement intuitively looks
like:

cout << structInstance[i].whicheverMemberTheUserSelected

Does it make sense what I'm looking to do? Is there a standard/elegant
way to achieve this? If I'm not making sense, I'll just post the
"inelegant" solution I have...
tia!

cdj


Is this similar to what you want?
Pavel

#include <iostream>
#include <sstream>
using namespace std;

struct S { char a, b, c; int d; };
static S s_;

string formatChar(void *p) {
char a[] = "c";
*a = *(char *)p;
return a;
}
string formatInt(void *p) {
ostringstream os;
os << *(int*)p;
return os.str();
}

typedef string (*Formatter)(void *);
struct FormatMeta {
int fieldOff;
Formatter formatter;
};

static FormatMeta SFM[] = {
{ (char*)(&s_.a) - (char*)(&s_), formatChar },
{ (char*)(&s_.b) - (char*)(&s_), formatChar },
{ (char*)(&s_.c) - (char*)(&s_), formatChar },
{ (char*)(&s_.d) - (char*)(&s_), formatInt }
};

#define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))

int main(int argc, char *argv[]) {
cout << "Enter an integer: =>" << flush;
int i;
if(!(cin >> i).good() || i < 0 || i >= ARR_SIZE(SFM)) {
cout << "Sorry\n";
return 1;
}
S sa[] = { {'a', 'b', 'c', 1}, {'d', 'e', 'f', 2} };
for(int ii=0; ii < ARR_SIZE(sa); ++ii) {
cout << (SFM[i].formatter)((char*)(&sa[ii]) + SFM[i].fieldOff)
<< endl;
}
return 0;
}
Apr 22 '06 #2
Sorry, I meant to answer cdj, of course..

Pavel wrote:

sh*************@gmail.com wrote:
Hi,

I'm just learning cpp, and the exercise I'm working on is basically as
follows:

1) Create a struct type with 4 members (char, char, char, int).
2) Create an array of, say 3 instances of the struct, and populate them
with data.
3) cin 1, 2, 3, or 4 from the user
4) If the user selected, say, 2, display the contents of the 2nd data
member from each of the structs in the array. Similarly for 1,3, and 4.

I'm trying to find an elegant way to achieve 4).

It's easy to achieve the functionality with a set of ifs/for loops (if
input=1, then for loop thru the struct array, cout <<
stuctInstance[i].FirstMember ....)

But this seems grossly inelegant, as I'm essentially writing the same
for-loop code 4 times - once for each input possibility. I would like
NO ifs, and just ONE for loop, whose key statement intuitively looks
like:

cout << structInstance[i].whicheverMemberTheUserSelected

Does it make sense what I'm looking to do? Is there a standard/elegant
way to achieve this? If I'm not making sense, I'll just post the
"inelegant" solution I have...
tia!

cdj


Is this similar to what you want?
Pavel

#include <iostream>
#include <sstream>
using namespace std;

struct S { char a, b, c; int d; };
static S s_;

string formatChar(void *p) {
char a[] = "c";
*a = *(char *)p;
return a;
}
string formatInt(void *p) {
ostringstream os;
os << *(int*)p;
return os.str();
}

typedef string (*Formatter)(void *);
struct FormatMeta {
int fieldOff;
Formatter formatter;
};

static FormatMeta SFM[] = {
{ (char*)(&s_.a) - (char*)(&s_), formatChar },
{ (char*)(&s_.b) - (char*)(&s_), formatChar },
{ (char*)(&s_.c) - (char*)(&s_), formatChar },
{ (char*)(&s_.d) - (char*)(&s_), formatInt }
};

#define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))

int main(int argc, char *argv[]) {
cout << "Enter an integer: =>" << flush;
int i;
if(!(cin >> i).good() || i < 0 || i >= ARR_SIZE(SFM)) {
cout << "Sorry\n";
return 1;
}
S sa[] = { {'a', 'b', 'c', 1}, {'d', 'e', 'f', 2} };
for(int ii=0; ii < ARR_SIZE(sa); ++ii) {
cout << (SFM[i].formatter)((char*)(&sa[ii]) + SFM[i].fieldOff)
<< endl;
}
return 0;
}

Apr 22 '06 #3
Pavel wrote:
static FormatMeta SFM[] = {
{ (char*)(&s_.a) - (char*)(&s_), formatChar },
{ (char*)(&s_.b) - (char*)(&s_), formatChar },
{ (char*)(&s_.c) - (char*)(&s_), formatChar },
{ (char*)(&s_.d) - (char*)(&s_), formatInt }


Those offsets are either undefined behavior or darn close. If you use the
offsetof() macro, then their behavior is defined.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 22 '06 #4
>> static FormatMeta SFM[] = {
{ (char*)(&s_.a) - (char*)(&s_), formatChar },
{ (char*)(&s_.b) - (char*)(&s_), formatChar },
{ (char*)(&s_.c) - (char*)(&s_), formatChar },
{ (char*)(&s_.d) - (char*)(&s_), formatInt }
Those offsets are either undefined behavior or darn close. If you use the
offsetof() macro, then their behavior is defined.


Let me rephrase.

Those offsets are defined behavior because they rely on a static instance of
S. If we want to save one S instance, we would need to use a pointer to S to
find those offsets. Such a pointer, pointing to no S instance, would cause
undefined behavior, even when the expression apparently resolves at compile
time. The offsetof() macro is defined to hide these issues, relying on
secretly implementation-defined behavior.
--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!

Apr 22 '06 #5
I am not sure I understand the "saving structure" problem you referred to.

The behavior of my code is well defined. As for the offsetof, I could
(and, probably, should) have used it -- but my way is not worse for the
particular case, just less universal (which was not a requirement). BTW,
offsetof must be implemented somehow. gcc defines it like

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

This "dereferencing" of NULL (when -> operator possibly "evaluates")
seems much less "defined" to me than my code -- but apparently the HOLY
STANDARD believes it is possible to somehow define it, so that the
behavior is at most "unspecified" but not "undefined" in its own terms
(I am not sure gcc stays on 'unspecified' ground here). So, yes, I
wasted a static structure to make the behavior "better defined". I do
not know how to *efficiently* define offsetof with the well-defined
behavior, but for any specific struct it is easy to do it as I did.

Phlip wrote:
static FormatMeta SFM[] = {
{ (char*)(&s_.a) - (char*)(&s_), formatChar },
{ (char*)(&s_.b) - (char*)(&s_), formatChar },
{ (char*)(&s_.c) - (char*)(&s_), formatChar },
{ (char*)(&s_.d) - (char*)(&s_), formatInt }


Those offsets are either undefined behavior or darn close. If you use the
offsetof() macro, then their behavior is defined.

Let me rephrase.

Those offsets are defined behavior because they rely on a static instance of
S. If we want to save one S instance, we would need to use a pointer to S to
find those offsets. Such a pointer, pointing to no S instance, would cause
undefined behavior, even when the expression apparently resolves at compile
time. The offsetof() macro is defined to hide these issues, relying on
secretly implementation-defined behavior.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!


Apr 23 '06 #6
Thanks for the replies everyone!

Um, did I mention that *I'm just learning* cpp? lolol

I don't know if Pavel's code is the sort of thing I'm looking for,
since I don't understand it - lol. I'll see if I can adapt it to my
exercise, and let ya know!

Here's the 3rd grade level solution I came up with (from code file -
not main() - i think it has all the essentials of my question in it
tho.... Is it clear what I originally said about not liking all of the
for loops that do basically the same thing, just with a different piece
of the struct?

thanks again!

cdj
==========
#include <iostream>

using namespace std;

int displayByName();
int displayByTitle();
int displayByBOPName();
int displayByPref();

const int STRSIZE=40;
const int NUM_BOPS=3;

struct bop {
char fullname[STRSIZE];
char title[STRSIZE];
char bopname[STRSIZE];
int preference; //0=fullname, 1=title, 2=bopname
};

bop myBops[NUM_BOPS] = {
{"chris", "master", "bopmaster", 0},
{"josh", "dork", "bopdork", -1},
{"paul", "friend", "bopfriend", 2},
};

void displayBy(int int_X)
{
//bop struct looks like: bopName(char, char, char, int)
//preference member map: 0=fullname, 1=title, 2=bopname
cout << endl;

switch (int_X) {
case 1: displayByName(); break;
case 2: displayByTitle(); break;
case 3: displayByBOPName(); break;
case 4: displayByPref(); break;
default: cout << "Invalid selection\n"; break;
}
}

int displayByName() {
for (int i=0; i<3; i++) {
cout << "user #" << i << ": " << myBops[i].fullname << endl;
}
return 0;
}

int displayByTitle() {
for (int i=0; i<3; i++) {
cout << "user #" << i << ": " << myBops[i].title << endl;
}

return 0;
}

int displayByBOPName() {
for (int i=0; i<3; i++) {
cout << "user #" << i << ": " << myBops[i].bopname << endl;
}

return 0;
}

int displayByPref() {
for (int i=0; i<3; i++) {
switch (myBops[i].preference) {
case 0: cout << "user #" << i << ": " << " Name: " <<
myBops[i].fullname << endl; break;
case 1: cout << "user #" << i << ": " << " Title: " <<
myBops[i].title << endl; break;
case 2: cout << "user #" << i << ": " << " BOP Name: " <<
myBops[i].bopname << endl; break;

default: cout << "user #" << i << ": " << " No valid preference
available" << endl; break;
}
}

return 0;
}

Apr 23 '06 #7
* Pavel:
[top-posting]
Please don't top-post in this group (corrected) -- FAQ.
* Pavel:
[snip] BTW, offsetof must be implemented somehow. gcc defines it like

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

This "dereferencing" of NULL (when -> operator possibly "evaluates")
seems much less "defined" to me than my code -- but apparently the HOLY
STANDARD believes it is possible to somehow define it, so that the
behavior is at most "unspecified" but not "undefined" in its own terms
(I am not sure gcc stays on 'unspecified' ground here). So, yes, I
wasted a static structure to make the behavior "better defined". I do
not know how to *efficiently* define offsetof with the well-defined
behavior, but for any specific struct it is easy to do it as I did.


However an implementation defines offsetof, it's a way that works with
that implementation -- but not necessarily with others.

A standard library implemementation isn't, in general, portable.

It's the standard library specification that's portable, so that code
that relies on that specification can be portable.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Apr 23 '06 #8
sh*************@gmail.com wrote:
Shame on me. I was always sure my code is the most readable in the world.

If you are interested in working further with your code, think of using
a pointer to the structure as an argument to your display.. functions.
This could save you one switch (because then you could implement display
by pref in terms of displayBy()).

Good luck.
Pavel
Thanks for the replies everyone!

Um, did I mention that *I'm just learning* cpp? lolol

I don't know if Pavel's code is the sort of thing I'm looking for,
since I don't understand it - lol. I'll see if I can adapt it to my
exercise, and let ya know!

Here's the 3rd grade level solution I came up with (from code file -
not main() - i think it has all the essentials of my question in it
tho.... Is it clear what I originally said about not liking all of the
for loops that do basically the same thing, just with a different piece
of the struct?

thanks again!

cdj
==========
#include <iostream>

using namespace std;

int displayByName();
int displayByTitle();
int displayByBOPName();
int displayByPref();

const int STRSIZE=40;
const int NUM_BOPS=3;

struct bop {
char fullname[STRSIZE];
char title[STRSIZE];
char bopname[STRSIZE];
int preference; //0=fullname, 1=title, 2=bopname
};

bop myBops[NUM_BOPS] = {
{"chris", "master", "bopmaster", 0},
{"josh", "dork", "bopdork", -1},
{"paul", "friend", "bopfriend", 2},
};

void displayBy(int int_X)
{
//bop struct looks like: bopName(char, char, char, int)
//preference member map: 0=fullname, 1=title, 2=bopname
cout << endl;

switch (int_X) {
case 1: displayByName(); break;
case 2: displayByTitle(); break;
case 3: displayByBOPName(); break;
case 4: displayByPref(); break;
default: cout << "Invalid selection\n"; break;
}
}

int displayByName() {
for (int i=0; i<3; i++) {
cout << "user #" << i << ": " << myBops[i].fullname << endl;
}
return 0;
}

int displayByTitle() {
for (int i=0; i<3; i++) {
cout << "user #" << i << ": " << myBops[i].title << endl;
}

return 0;
}

int displayByBOPName() {
for (int i=0; i<3; i++) {
cout << "user #" << i << ": " << myBops[i].bopname << endl;
}

return 0;
}

int displayByPref() {
for (int i=0; i<3; i++) {
switch (myBops[i].preference) {
case 0: cout << "user #" << i << ": " << " Name: " <<
myBops[i].fullname << endl; break;
case 1: cout << "user #" << i << ": " << " Title: " <<
myBops[i].title << endl; break;
case 2: cout << "user #" << i << ": " << " BOP Name: " <<
myBops[i].bopname << endl; break;

default: cout << "user #" << i << ": " << " No valid preference
available" << endl; break;
}
}

return 0;
}

Apr 23 '06 #9
The clearest Chinese in the world is gobbledygook to someone who only
speaks English... :)

It's my lack of language understanding - not your lack of writing
skills.

Thanks to everyone - you've given me plenty to gnaw on!

cdj

Apr 23 '06 #10
Please don't top-quote. Mixing your comments with the replied-to text makes
each post legible.

Pavel wrote in message news:Ob***************@fe12.lga...
I am not sure I understand the "saving structure" problem you referred to.
Sorry - I said "save" when I meant "reduce the program's footprint by the
size of one structure." So it's the same argument as yours - how to get rid
of the unused static object. No biggie. If this were my program and I needed
one more unused static object, I would just leave it there and I would not
prematurely optimize.
The behavior of my code is well defined. As for the offsetof, I could
(and, probably, should) have used it -- but my way is not worse for the
particular case, just less universal (which was not a requirement). BTW,
offsetof must be implemented somehow. gcc defines it like

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

This "dereferencing" of NULL (when -> operator possibly "evaluates") seems
much less "defined" to me than my code -- but apparently the HOLY STANDARD
believes it is possible to somehow define it, so that the behavior is at
most "unspecified" but not "undefined" in its own terms (I am not sure gcc
stays on 'unspecified' ground here).
Because they are allowed to write it inside that macro, and you are not
allowed to write it outside.

The distinction is simple. GNU will test gcc and support that macro,
regardless where they port gcc. However, if you rely on unspecified
behavior, then it may switch to undefined behavior when GNU changes its
compiler and changes the contents of that macro.
So, yes, I wasted a static structure to make the behavior "better
defined". I do not know how to *efficiently* define offsetof with the
well-defined behavior, but for any specific struct it is easy to do it as
I did.


I suspect your version is perfectly efficient - a hard constant. You can
size an array with it and see.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 23 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: Steven T. Hatton | last post by:
This is something I've been looking at because it is central to a currently broken part of the KDevelop new application wizard. I'm not complaining about it being broken, It's a CVS images. ...
6
by: Peter Frost | last post by:
Please help I don't know if this is possible but what I would really like to do is to use On Error Goto to capture the code that is being executed when an error occurs. Any help would be much...
140
by: Oliver Brausch | last post by:
Hello, have you ever heard about this MS-visual c compiler bug? look at the small prog: static int x=0; int bit32() { return ++x; }
10
by: Adam Warner | last post by:
Hi all, With this structure that records the length of an array of pointers as its first member: struct array { ptrdiff_t length; void *ptr; };
5
by: RocTheEngy | last post by:
Greetings c.l.c... I am trying to understand some structure definitions in working code (e.g. compiles, runs & produces expected results) that I have. I think I've trimmed the code to what is...
5
by: Martin Jørgensen | last post by:
Hi, Consider this code: --- beginning of code --- #include <iostream> using namespace std; class Child{ public:
5
by: sherifffruitfly | last post by:
Hi, I'm just learning cpp, and the exercise I'm working on is basically as follows: 1) Create a struct type with 4 members (char, char, char, int). 2) Create an array of, say 3 instances of...
3
by: Curten | last post by:
Hi, I'm a beginner and need help with the following: I have defined a class A where a private data member is an array of structs; private: vector<a_struct> Data; The values of the...
6
by: jason | last post by:
Hello, I have a question about what kind of datastructure to use. I'm reading collumn based data in the form of: 10\t12\t9\t11\n 24\t11\t4\t10\n ..... I now have a structure which allows me...
29
by: calvert4rent | last post by:
I need to some sort of data type that will hold a listing of ID's and their counts/frequency. As I do some processing I get an ID back which I need to store and keep an accurate count for how many...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.