I want to map struct members so I can eliminate if branches in a loop. What is the best way or convention to implement this in C? I suppose it could be a 2 dimensional array instead…then I could map integers to the char keys?
char chunk[32];
int n;
int i;
char *ptr = config;
while (*ptr != '\0') {
int items_read = sscanf(ptr, "%31[^;]%n", chunk, &n);
if(chunk[0] == 'S' && chunk[1] == 'P') {
for(i=0;i<GLOBAL_MEAS_CUTOFF; i++) {
theMeas[i].signal_path = atoi(&chunk[2]);
}
}
if(chunk[0] == 'T' && chunk[1] == 'L') {
for(i=0;i<GLOBAL_MEAS_CUTOFF; i++) {
theMeas[i].trace_length = atoi(&chunk[2]);
}
}
if(chunk[0] == 'S' && chunk[1] == 'R') {
for(i=0;i<GLOBAL_MEAS_CUTOFF; i++) {
theMeas[i].sample_rate = atoi(&chunk[2]);
}
}
chunk[0]='\0';
if (items_read == 1)
ptr += n;
if ( *ptr != ';' ) {
break;
}
++ptr;
}
I suspect what you (ideally) want is a dictionary:
Of course, the above syntax will never happen in C, but that’s not really important here. The problem is that you would have to write all the code implementing a dictionary data type, and I suspect that’s overkill.
So I suspect what you (really) want is a way to have names that can be used in a loop:
And I’m here to tell you that you can do this (kind of)! The simplest way is with an
enum:Instead of
structmembers, you use an array:To index a “member”, use this:
You can loop through all the “members,” you can use this:
This does break down a little when you want to get character-based comparisons, but we can do a little bit:
Your
ifstatements could be replaced with:Or, more safely:
Which is about as close as I can get.
Note that I’ve deliberately used a naming scheme to facilitate the creation of macros that will automate much of this. Let’s try:
Usage:
That last bit doesn’t seem so bad. It still allows you something close to
struct-like access viatheMeas[i][signal_path], but allows you to iterate over the “members,” and hides most of the heavy lifting behind macros.The
to_strandfrom_strfunctions take a little more macro trickery to automate. You’ll probably need to look into P99 for that. Thefrom_abvfunction isn’t something I’d recommend for the general case, as we have no way of guaranteeing that the next time you make iterable fields you’ll use names with underscores. (Of course, you could drop thefrom_abvfunction and give your members inscrutable names likeSP,TL, andSR, allowing you to directly compare them to your string data, but you’d need to change thestrcmpto amemcmpwith a size argument of(sizeof(#x) - 1). Then all the places you havefrom_abvyou’d just usefrom_str, which can be automatically generated for you.)However,
from_abvisn’t hard to define, and you could honestly just copy and paste yourifblocks from above into it – it’d be slightly more efficient, though if you added a “member” you’d have to update the function (as written, it’ll update itself if you add a member.)