Replacing nested switches with the multi-dimensional array

replacing-nested-switches-with-multi-dimensional-array

A multi-dimensional array is very useful in C language. We can replace nested switch case with a multidimensional array using the pointer to function. Using this technique, a function that has a hundred lines of code reduced dramatically.

Previously I have worked on a POS (point of sale) application, in this application we have used a lot of nested switch case. The application has a main screen where all type of transactions (SALE, VOID REFUND … etc) display. In the application, we have categorized all transactions on the basis of screen state and every main screen state has a sub-screen state.

In this article, I am creating a pseudo program code to describe, how we can replace a nested switch case with a multi-dimensional array.

Suppose there is an application that has different transaction methods and the transaction method is identified by the different screen states. In below demo program transaction methods are identified by the MenuStates.

typedef enum {

    Menustate1 = 0,
    Menustate2,
    Menustate3,
    Menustate4

} MenuStates;

 

Further, every Menu state consists of other sub-states. Every Menu state should have a unique sub-state.

typedef enum {

    MenuSubState1 = 0,
    MenuSubState2,
    MenuSubState3,
    MenuSubState4,
    MenuSubState5,
    MenuSubState6,
    MenuSubState7,
    MenuSubState8,
    MenuSubState9,
    MenuSubState10

} MenuSubStates

 

Note: In this application important point is that we have nested switch statements and the number of substates is different for each menu states.

In the below example, I am creating a sample program to describe the working of the nested switch case.

#include <stdint.h>
#include <stdio.h>

//Menu state
typedef enum
{

    Menustate1 = 0,
    Menustate2,
    Menustate3,
    Menustate4,
    LastMenustate

} MenuStates;


//Substates
typedef enum
{

    MenuSubState1 = 0,
    MenuSubState2,
    MenuSubState3,
    MenuSubState4,
    MenuSubState5,
    MenuSubState6,
    MenuSubState7,
    MenuSubState8,
    MenuSubState9,
    MenuSubState10,
    LastMenuSubState

} MenuSubStates;


/*Prototype of Function which select transaction and processing
method on the basis of Menustate and substate */

void Transaction(MenuStates State, MenuSubStates SubState);

/*Prototype of Functions which are called from nested switch statement.*/
void SaleCreditTransaction(void);
void SaleDebitTransaction(void);
void SaleCashTransaction(void);
void RefferalCreditTransaction(void);
void VoidTransaction(void);
void RefundTransaction(void);
void SaleReprintReceipt(void);
void VoidReprintReceipt(void);
void RefundReprintReceipt(void);
void RefferalReprintReceipt(void);


void main(void)
{
    MenuStates  eMenuState; //Menu State
    MenuSubStates eMenuSubState; // Sub State

    //Trasaction type is selected by on the basis of menustate and substate
    for (eMenuState = Menustate1; eMenuState < LastMenustate; eMenuState ++)
    {
        for( eMenuSubState = MenuSubState1; eMenuSubState < LastMenuSubState; eMenuSubState++)
        {

            Transaction (eMenuState, eMenuSubState);
        }
    }
}


void Transaction(MenuStates State, MenuSubStates SubState)

{
    switch (State)
    {
    case Menustate1:
        switch (SubState)
        {
        case MenuSubState1:
            SaleCreditTransaction();
            break;

        case MenuSubState2:
            SaleDebitTransaction();
            break;
        case MenuSubState3:
            SaleCashTransaction();
            break;

        case MenuSubState5:
            SaleReprintReceipt();
            break;


        default:
            break;
        }
        break;

    case Menustate2:
        switch (SubState)
        {
        case MenuSubState6:
            RefferalCreditTransaction();
            break;
        case MenuSubState9:
            RefferalReprintReceipt();
            break;

        default:
            break;
        }
        break;

    case Menustate3:
    {
        switch (SubState)
        {
        case MenuSubState4:
            VoidTransaction();
            break;

        case MenuSubState8:
            VoidReprintReceipt();
            break;

        default:
            break;
        }
    }
    break;

    case Menustate4:
    {
        switch (SubState)
        {
        case MenuSubState7:
            RefundTransaction();
            break;

        case MenuSubState10:
            RefundReprintReceipt();
            break;
        default:
            break;
        }
    }

    default:
        break;
    }
}


void SaleCreditTransaction(void)
{
    printf("Sale Credit Transaction\n");
}

void SaleDebitTransaction(void)
{
    printf("Sale Debit Transaction\n");
}

void SaleCashTransaction(void)
{
    printf("Sale Cash Transaction\n");
}

void SaleReprintReceipt(void)
{
    printf("Sale Receipt Reprint\n");
}

void RefferalCreditTransaction(void)
{
    printf("Refferal Credit Transaction\n");
}

void RefferalReprintReceipt(void)
{
    printf("Refferal Receipt Reprint\n");
}

void VoidTransaction(void)
{
    printf("Void Transaction\n");
}

void VoidReprintReceipt(void)
{
    printf("Void Receipt Reprint\n");
}

void RefundTransaction(void)
{
    printf("Refund Transaction\n");
}

void RefundReprintReceipt(void)
{
    printf("Refund Receipt Reprint\n");
}

nested switch c++

In the above program nested switch case statement execute on the basis of Menustate and substate value. Nested switch cases increase the length of the program. Sometimes it is hard to modify the nested switch case due to their length.

 

If you want to learn more about the c language, here 10 Free days (up to 200 minutes) C video course for you.

Your free trial is waiting

 

Steps to replace nested switch cases with a multidimensional array of pointer to function:
  • First, need to create an array of pointer to function. In my case, only one nested switch so here I am creating a 2D array of pointer to function.
  • Assign the address of function at the proper index of the array.
  • Put the NULL or dummy function at the empty index of the array.
  • Always check the boundary of the array before calling the function.
  • We need to check NULL before calling the function either we will get the segmentation fault.
#include <stdint.h>
#include <stdio.h>

//Menu state
typedef enum
{

    Menustate1 = 0,
    Menustate2,
    Menustate3,
    Menustate4,
    LastMenustate

} MenuStates;


//Substates
typedef enum
{

    MenuSubState1 = 0,
    MenuSubState2,
    MenuSubState3,
    MenuSubState4,
    MenuSubState5,
    MenuSubState6,
    MenuSubState7,
    MenuSubState8,
    MenuSubState9,
    MenuSubState10,
    LastMenuSubState

} MenuSubStates;


/*Prototype of Function which select transaction and processing
method on the basis of Menustate and substate */

void Transaction(MenuStates State, MenuSubStates SubState);

/*Prototype of Functions which are called from nested switch statement.*/
void SaleCreditTransaction(void);
void SaleDebitTransaction(void);
void SaleCashTransaction(void);
void RefferalCreditTransaction(void);
void VoidTransaction(void);
void RefundTransaction(void);
void SaleReprintReceipt(void);
void VoidReprintReceipt(void);
void RefundReprintReceipt(void);
void RefferalReprintReceipt(void);




//Ceate typedef of pointer to function 2D array
typedef void (* const apfTransactionTable[LastMenustate][LastMenuSubState])(void);


void Transaction(MenuStates State,  MenuSubStates SubState)
{
    static apfTransactionTable pfTransaction =
    {
        {SaleCreditTransaction, SaleDebitTransaction, SaleCashTransaction,NULL, SaleReprintReceipt,NULL,NULL,NULL,NULL,NULL},
        {NULL, NULL, NULL, NULL, NULL,RefferalCreditTransaction,NULL,NULL,RefferalReprintReceipt,NULL},
        {NULL, NULL, NULL, VoidTransaction, NULL,NULL,NULL,VoidReprintReceipt,NULL,NULL},
        {NULL, NULL, NULL, NULL, NULL,NULL,NULL,NULL,RefundTransaction,RefundReprintReceipt},

    };

    if(pfTransaction[State][SubState] != NULL) //Check NULL pointer
    {
        (*pfTransaction[State][SubState])();
    }
}


void main(void)
{
    MenuStates  eMenuState;
    MenuSubStates eMenuSubState;

    for (eMenuState = Menustate1; eMenuState < LastMenustate; eMenuState ++)
    {
        for( eMenuSubState = MenuSubState1; eMenuSubState < LastMenuSubState; eMenuSubState++)
        {
            Transaction(eMenuState, eMenuSubState);

        }
    }
}




void SaleCreditTransaction(void)
{
    printf("Sale Credit Transaction\n");
}
void SaleDebitTransaction(void)
{
    printf(" Sale Debit Transaction\n");
}
void SaleCashTransaction(void)
{
    printf("Sale Cash Transaction\n");
}

void SaleReprintReceipt(void)
{
    printf("Sale Receipt Reprint\n");
}

void RefferalCreditTransaction(void)
{
    printf("Refferal Credit Transaction\n");
}


void RefferalReprintReceipt(void)
{
    printf("Refferal Receipt Reprint\n");
}

void VoidTransaction(void)
{
    printf("Void Transaction\n");
}

void VoidReprintReceipt(void)
{
    printf("Void Receipt Reprint\n");
}


void RefundTransaction(void)
{
    printf("Refund Transaction\n");
}


void RefundReprintReceipt(void)
{
    printf("Refund Receipt Reprint\n");
}

 

nested switch

In the above program, a nested switch case replace by an array of pointer to function.
Sometimes this approach creates the issues and reduces the readability of the code.
So it totally depends on your requirement and design of the application that replacing the nested switch case with the multidimensional array is the benefit or not.

Recommended Articles for you,



8 comments

  1. Excellent work. It is brilliantly explained and can be modified to serve multipurpose projects. Again, great work…

Leave a Reply

Your email address will not be published. Required fields are marked *