c ideas on shrinking this function? - c

I have this huge switch case with nested switch case statements in it that I was wondering if anyone had any ideas on how to clean up?
switch (datatype) {
case STR:
{
switch(operation)
{
case EQUALS:
{
/* perform str compare */
}
case NOTEQUALS:
{
}
case LT:
{
}
case GT:
{
}
case GTE:
{
}
case LTE:
{
}
default:
break;
}
break;
}
case VER:
{
switch(operation)
{
case EQUALS:
{
/* perform version compare */
}
case NOTEQUALS:
{
}
case LT:
{
}
case GT:
{
}
case GTE:
{
}
case LTE:
{
}
default:
break;
}
break;
}
case INT:
{
/* same */
}
case FLOAT:
{
/* same */
}
/* ... more types ... */
/* ... .......... ... */
default:
break;
}

If the values for the operation are contiguous, you could make a table of function pointers. In fact you could make a 2D table of function pointers with a separate function to handle each operation/type combination. e.g
// do some range checking on input params
// invoke the handler
handlers[datatype][operation]();

Create some tables (arrays) with pointers to functions in it. You can then look up func[STR][EQUALS] to make the appropriate call. The call would end up looking like this...
Func[datatype][operation]();

You could try the command pattern.

The NOTEQUALS case can always be written in terms of the EQUALS case; similarly GTE in terms of LT and LTE in terms of GE. So make the outer switch in terms of the operation, and only three of those six cases will need to switch on the datatype.

You could use a big array of function pointers and then call the relevant function based upon indexing to the correct function pointer in the array.

have you considered creatively using a series of function pointers and storing them in a struct?
do it right and you can mimic objects and do something this like:
bool someArbitraryFunction (dataType aDatatype, operations anOperation)
{
someUnknownStruct.datatype = aDatatype;
someUnknownStruct.operation = anOperation;
return someUnknownStruct->doMath(1,2);
}
and then you can put all the needed math functions, enums, and structs in a header file somewhere.
cleans up the "meat" of the code, and makes the math portable (just import it wherever you need it).

Assuming your cases can all return a simple boolean value, all six logic cases can be rewritten in terms of LT and EQUALS, like follows:
switch(operation) {
case EQUALS:
return isEquals();
case NOTEQUALS:
return !isEquals();
case LT:
return isLT();
case GT:
return !isLT() && !isEquals();
case GTE:
return !isLT();
case LTE:
reutrn isLT() || isEquals();
default:
break;
}
This would only require you to write the logic for isLT() and isEquals(), which would do the switching on datatype when necessary. This eliminates a significant amount of unnecessary code duplication, yet doesn't sacrifice a lot of legibility.
This can be combined with function pointers as Stephen Doyle and rikh already suggested, which would eliminate the switch() statement entirely.

Related

React - Conditional Rendering with Switch and boolean case

I would like to clarify a doubt on React Conditional Rendering with Switch Case
I have an implementation with conditions. ie I have to set a string value based on boolean case
For example
let str = "";
switch(some object)
{
case object.yes: // The case here is boolean. IS it possible to set boolean case. I did try but the value is not set correctly based on the case in the str variable.
str = "Yes"
break:
case object.no:
str = "No"
break;
}
IF the above code is not possible, I will use if ... else. But during code review, surely I will be asked why I did not use Switch instead of if ...else. I want to give a convincing answer. I did seach tutorials but I can only find string case and not boolean case for React.
Just want to verify if boolean case is possible.
The cleanest solution is to use an IIFE
const object = {
yes: true,
no: false
}
const str = (() => {
switch (true) {
case object.yes: // The case here is boolean. IS it possible to set boolean case. I did try but the value is not set correctly based on the case in the str variable.
return "Yes";
case object.no:
return "No";
default:
return "Unknown";
}
})();
console.log(str);

C: handling case...else

What is the correct way to put an else clause in a switch statement? For example, instead of:
switch (input) {
case (1):
printf("yes!");
break
case (0):
printf("no!");
break;
default:
printf("invalid!");
}
To do something along the lines of (if possible):
switch (input) {
case (1):
printf("yes!");
case (0):
printf("no!");
else:
printf("invalid!");
}
I'm simply asking if there is a short-cut to not have to add a break after every case statement to act as-if it were the else part of an if statement.
The correct way is using default. Also ,you don't have to use break for non-default cases, only if you don't want execution to fall into the next case.

Is there a way to change local variables partway through switch case without exiting the switch statement?

I'm dealing with a rather large enumeration, which can conceptually be divided as representing four different categories. Currently I'm using this enumeration in a switch case statement in order to map values into four separate arrays (in line with the four different categories).
What I'm curious about is if it is possible to change a locally defined variable after arbitrary cases in the switch case statement. This would allow for the ability to break the switch statement into these four different sections, and value assignments that would occur for each case -- if equivalent -- can occur at these sections.
A simplified example what I'm going for is as follows:
Setup
enum incidental_indexes {
arr1_0, arr1_2, arr2_0, arr1_1, arr2_1
} indexes;
struct foobar{
int arr1[3];
int arr2[2];
}
enum indexes unknown_index = ???; // In my code there are two separate indexes being mapped
// from one another, so for the sake of example imagine that
// this index is unknown
enum indexes curr_index = arr1_1; //Value here does not matter
struct foobar my_struc;
int * curr_arr;
int mapped_index;
Brute force approach
switch(unknown_index){
case(arr1_0):
curr_arr = my_struc.arr_1; //First category array
curr_index = arr1_0;
break;
case(arr1_1):
curr_arr = my_struc.arr_1; //First category array, again
curr_index = arr1_1;
break;
case(arr1_2):
curr_arr = my_struc.arr_1; //First category array, again, again
curr_index = arr1_2;
break;
case(arr2_0):
curr_index = arr2_0;
curr_arr = my_struc.arr_2; //Second category array
break;
case(arr2_1):
curr_index = arr2_1;
curr_arr = my_struc.arr_2; //....
break;
}
Ideal Approach
switch(unknown_index){
default: //Notice no break.
curr_arr = my_struc.arr_1; //First category array
case(arr1_0):
curr_index = arr1_0;
break;
case(arr1_1):
curr_index = arr1_1;
break;
case(arr1_2):
curr_index = arr1_2;
break;
default: //Something like a second default, however disallowed
curr_arr = my_struc.arr_2; //Second category array
case(arr2_0):
curr_index = arr2_0;
break;
case(arr2_1):
curr_index = arr2_1;
break;
}
The functional benefits are obviously nill, however I'm curious if this functionality even exists in C, or if there is perhaps a better method for executing this.
Thanks!
Switch statements only perform a single branch, so you can't jump around inside of the switch like that. What you can do however is group certain cases together without a break in between:
switch(curr_index){
case arr1_0:
case arr1_1:
case arr1_2:
curr_arr = my_struc.arr_1;
break;
case arr2_0:
case arr2_1:
curr_arr = my_struc.arr_2;
break;
}
EDIT:
For the index assignment part, you could do a second switch like this:
switch(unknown_index){
case arr1_0:
curr_index = arr1_0;
break;
case arr1_1:
curr_index = arr1_1;
break;
case arr1_2:
curr_index = arr1_2;
break;
case arr2_0:
curr_index = arr2_0;
break;
case arr2_1:
curr_index = arr2_1;
break;
}
But since you're always assigning whatever the value of unknown_index is, the above is the same as this:
curr_index = unknown_index;
One, no.
Two, just use ifs and elses. As the saying goes, when you have a hammer, everything looks like a nail. switch is a really weird "hammer" to try applying to everything.
Three, um, I guess you could use goto everywhere, but we decided this was a bad idea and creates horribly messes of code in the 80s or something.
Within a switch you have access to all the locally defined variables. I'm not quite sure I understand your question... it seems like what you're trying to do is best accomplished by 2 switches:
switch(unknown_index){
case(arr1_0):
case(arr1_1):
case(arr1_2):
curr_arr = my_struc.arr_1; //First category array, again, again
break;
case(arr2_0):
case(arr2_1):
curr_arr = my_struc.arr_2; //....
break;
}
switch(unknown_index){
case(arr1_0):
curr_index = arr1_0;
break;
case(arr1_1):
curr_index = arr1_1;
break;
case(arr1_2):
curr_index = arr1_2;
break;
case(arr2_0):
curr_index = arr2_0;
break;
case(arr2_1):
curr_index = arr2_1;
break;
}

How to break outer loops from inner structures that respond break (loops/switch)

How to I break an outer loop from within an nested structure that responds to the break statement in Swift?
For example:
while someCondition {
if someOtherCondition {
switch (someValue) {
case 0: // do something
case 1: // exit loop
case 2...5: // do something else
default: break
}
} else {
someCondition = false
}
}
The break will only get me out of the switch, and in Swift, it has to be used as empty cases are not allowed. How can I entirely exit the loop from within the switch?
Swift allows for labeled statements. Using a labeled statement, you can specify which which control structure you want to break from no matter how deeply you nest your loops (although, generally, less nesting is better from a readability standpoint). This also works for continue.
Example:
outerLoop: while someCondition {
if someOtherCondition {
switch (someValue) {
case 0: // do something
case 1: break outerLoop // exit loop
case 2...5: // do something else
default: break
}
} else {
someCondition = false
}
}
Label the loop as outerLoop and whenever needed user break Label: i.e. break outerLoop in our case.
outerLoop: for indexValue in 0..<arr.count-1 {
if arr[indexValue] > arr[indexValue+1] {
break outerLoop
}
}

How to re-use a variable without getting error C2371 (Redefinition), for var with different types?

In VBA I simply would use a variant-Type for this, but how can I reduce this somewhat repetitive code to get to a better switch case block?
switch(command){
case CMD1:
RESPONSE1 rsp1;
memcpy(&rsp1,pPkt,sizeof(rsp1));
break;
case CMD2:
RESPONSE2 rsp2;
memcpy(&rsp2,pPkt,sizeof(rsp2));
break;
case CMD3:
RESPONSE3 rsp3;
memcpy(&rsp3,pPkt,sizeof(rsp3));
break;
case CMD4:
RESPONSE4 rsp4;
memcpy(&rsp4,pPkt,sizeof(rsp4));
case CMD5:
RESPONSE5 rsp5;
memcpy(&rsp5,pPkt,sizeof(rsp5));
default:
break;
}
My goal would be to eliminate those 5 response variables and use only one - however, I need the 5 different types because of the memcpy.
I am aware, that there is something like cast, but I think this is more problematic, because these RESPONSE# are structs of different size - wouldn't I have to reallocate memory for that?
Edit:
Thanks to mux, I found, that there is already a union for that in my code (adapting something from someone else)!
typedef union
{
RESPONSE1 rsp1;
RESPONSE2 rsp2;
RESPONSE3 rsp3;
RESPONSE4 rsp4;
RESPONSE5 rsp5;
}
RESPONSE_UNION;
And this is what I am using now:
RESPONSE_UNION ru;
switch(command){
case CMD1:
memcpy(&ru.rsp1,pPkt,sizeof(ru.rsp1));
break;
case CMD2:
memcpy(&ru.rsp2,pPkt,sizeof(ru.rsp2));
break;
...
Really a great help!
You could use a union and you might also want to define an enum for the response type:
typedef enum {
RESPONSE_1,
RESPONSE_2,
RESPONSE_3,
RESPONSE_4
} ResponseType;
typedef struct {
ResponseType type;
union {
RESPONSE1 rsp1;
RESPONSE2 rsp2;
RESPONSE3 rsp3;
RESPONSE4 rsp4;
};
} Response;
In your code you use it like this:
Response r;
switch (command) {
case CMD1:
r.type = RESPONSE_1;
memcpy(&r.rsp1, pPkt, sizeof(r.resp1));
break;
case CMD2:
...
}

Resources