Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most efficient way to use different members of struct in a function?

Tags:

c

struct

I'm writing for a very limited resource embedded processor. I have a struct that captures a time series of events, and I'd like to use the same graphing function against different values of different types. Something like (very stripped down; don't sweat uninitialized values, etc):

#define GRAPH_ONE 1
#define GRAPH_TWO 2

struct _event_t {
  unsigned long timestamp;
  int sensorOne;
  float sensorTwo;
}

typedef struct _event_t event_t;

event_t[10] MyEvents;

void GraphSensor(byte graphType) {
    for (unsigned int i = 0; i < 9; i++) {
       // Get minimum value from series
       if (MyEvents[i].?????) ...
    }
}

How can I have my function operate on different members of the struct? I can see doing it with a ton of switch (graphType) statements, but that's pretty ugly. There could easily be 8 or 10 members of the struct. I could move all of those to a separate function and make every bit of data access call that function, always returning a float (which should be OK for my graph). Finally I could convert to C++ classes, which opens other means.

None of those feel right. Is there a better approach, preferably a very lightweight one?

like image 288
user977705 Avatar asked Jul 16 '14 22:07

user977705


2 Answers

You could wrap the accessor you need in a function, and pass that to the function that walks the array and aggregates the results. For example

float getSensor1(const event_t* t)
{
    return t->sensorOne;
}

float getSensor2(const event_t* t)
{
    return t->sensorTwo;
}

void GraphSensor(float (*accessor)(const event_t*)) {
    // Get minimum value from series
    float min_value = MAX_FLOAT;
    for (unsigned int i = 0; i < 9; i++) {
       float x = accessor(MyEvents + i);
       if (x < min_value)
           min_value = x;
    }
}

/* later on . . . */
GraphSensor(getSensor1);
GraphSensor(getsensor2);

You are basically decoupling the access of the data from the operation on it, and homogenizing it all to floats. The aggregation operation could also be encapsulated into a function, too. But that's getting pretty close to map-reduce. :)

like image 95
Randall Cook Avatar answered Sep 26 '22 03:09

Randall Cook


You could change the struct to an array which uses perhaps all floats. In that way the data handling is completely homogeneous.

#define N_SENSORS   12
#define N_EVENTS    10 

float MyEvents [N_EVENTS] [N_SENSORS];

void GraphSensor(byte graphType)
{
    float min = 1e38;
    for (unsigned int i = 0; i < N_EVENTS; i++)
    {
       // Get minimum value from series
       if (MyEvents[i][graphType] < min)
            min = MyEvents[i][graphType];
    }
}

Perhaps the timestamp could be there too in element zero maybe using spreadsheet conventions: integer part is days since 1970 or 1900 and fractional part is portion of the day (so noon = .5).

like image 39
wallyk Avatar answered Sep 22 '22 03:09

wallyk