stitch123
stitch123

Reputation: 307

How can I make this repeating code look neater

EDIT: Forgot to mention that I'm on a constrained platform so I'm trying to use as little additional variables as possible.

...
switch (var->type) {
    case (something1):
        if (var->x >= 100 && var->x <= 105) {
            do_something(var);
            return;
        }
        break;

    case (something2):
        if (var->x >= 150 && var->x <= 155) {
            do_something(var);
            return;
        }
        break;

    case (something3):
        if (var->y >= 80 && var->y <= 85) {
            do_something(var);
            return;
        }
        break;

    case (something4):
        if (var->y >= 120 && var->y <= 125) {
            do_something(var);
            return;
        }
        break;
}
... 

Basically the code just checks the type of the variable, checks range on an axis specific to that type, and calls a function if the condition is met, does nothing if not. do_something() is the exact same function within all of the if segments.

I'm sure there's an easy way to write this with less repetition, but I can't seem to figure it out.

Thanks in advance.

Upvotes: 0

Views: 68

Answers (3)

William Pursell
William Pursell

Reputation: 212374

You could do something like:

int
main(int argc, char **argv) {

    struct { int type; int y;} var[] = { 3, 82 };
    struct range { int min; int max; } range;

    switch(var->type) {
    case 1: range = (struct range){100,105}; break;
    case 2: range = (struct range){150,155}; break;
    case 3: range = (struct range){80,85}; break;
    case 4: range = (struct range){120,125}; break;
    }

    if( var->y >= range.min && var->y <= range.max) {
        do_something();
    }
    return 0;
}

If the somethingN are sufficiently small enough integers, this can generalize nicely to something like:

int
main(int argc, char **argv) {

    struct { int type; int y;} var[] = { 3, 82 };
    struct range { int min; int max; } range[] = {
        {0,0},
        {100,105},
        {150,155},
        {80,85},
        {120,125},
    };


    if( var->y >= range[var->type].min && var->y <= range[var->type].max) {
        do_something();
    }
    return 0;
}

As mentioned in the comments, this approach fails to notice that the comparisons are sometimes for member x, and sometimes for y. That can be addressed with something like:

int
main(int argc, char **argv) {

    struct { int type; int x, y;} var[] = { 3, 81, 82 };
    struct range { int *v; int min; int max; } range[] = {
        {&var->x, 0,0},
        {&var->x, 100,105},
        {&var->x, 150,155},
        {&var->y, 80,85},
        {&var->y, 120,125},
    };

    int c = *(range[var->type].v);
    if( c >= range[var->type].min && c <= range[var->type].max) {
        do_something();
    }
    return 0;
}

Upvotes: 1

Gerhardh
Gerhardh

Reputation: 12404

Maybe something like this:

typedef enum {
 something1,
 something2,
 something3,
 something4,
 sometype_max
} some_type;

struct {
 int min;
 int max;
} limits[] = 
{
  [something1] = {100, 105},
  [something2] = {150, 155},
  [something3] = {80, 85},
  [something4] = {120, 125}
};

...

if (var->type < sometype_max)
{
  if ((var->x > limits[var->type].min) && (var->x < limits[var->type].max))
  {
    do_something();
  }    
}

Upvotes: 1

Lee Daniel Crocker
Lee Daniel Crocker

Reputation: 13171

How about:

switch (var->type) {
case (something1):
    if (! (var->x >= 100 && var->x <= 105)) return;
    break;
case (something2):
    if (! (var->x >= 150 && var->x <= 155)) return;
    break;
case (something3):
    if (! (var->y >= 80 && var->y <= 85)) return;
    break;
case (something4):
    if (! (var->y >= 120 && var->y <= 125)) return;
    break;
default:
    return;
}
do_something();

Upvotes: 1

Related Questions