Master the jump table before understanding the state machine

catalogue

Why write this

Program running results

Jump table body code

main function code

Complete code

Why write this

I was going to write an article about the state machine. The relevant theoretical knowledge has been almost written, but I haven't prepared much about the code. In the process of preparing the code, I saw a code file I practiced before, which is about the jump table, because the code I want to write is based on the jump table, not switch Case or if Else, I think I can write an article about jump table before the code of state machine is ready.

Maybe I haven't heard of jump table before. These two strange concepts (state machine and jump table) are also based on the existing C language concepts, such as for loop, such as pointer (function pointer), structure and structure array, and enumeration type.

Jump table is a structure array made of identifier and function pointer. By traversing the structure array, find the corresponding identifier, and call the corresponding function pointer to execute the corresponding function. The following function is to find the identifier and directly call the corresponding function pointer within a reasonable range.

Program running results

The example explained is to realize four simple operations, and the parameters involved can be passed in through the command line. This is the code I read in the official account, which rewrites the implementation of the main function.

main function definition of parameters that can be passed in from the command line

int main(int argc, char *argv[])

After compilation, enter: jumptable Exe # 23 x 5 = then press enter to get the corresponding calculation result

Jump table body code

/* Defines an operation as an enumeration type */
typedef enum
{
    OP_ADD = 0,         //Performing operations: adding
    OP_SUB,             //Performing actions: subtraction
    OP_MUL,             //Perform operations: multiply
    OP_DIV,             //Performing operations: Division
} OP_TYPE;

/* Function pointer with double input parameter and double output parameter */
typedef double (*OP_FUNC)(double, double);

typedef struct OP_STRUCT
{
    OP_TYPE opType;     //Operation type
    OP_FUNC opFun;      //Operation function
} OP_STRUCT;

/*Addition, subtraction, multiplication and division processing function*/
double ADD(double op1, double op2)
{
    return op1 + op2;
}
double SUB(double op1, double op2)
{
    return op1 - op2;
}
double MUL(double op1, double op2)
{
    return op1 * op2;
}
double DIV(double op1, double op2)
{
    return op1 / op2;
}

/* Function jump table */
static OP_STRUCT g_opStruct[] =
{
    {OP_ADD, ADD},
    {OP_SUB, SUB},
    {OP_MUL, MUL},
    {OP_DIV, DIV},
};

/* Maximum number of operations */
static int g_opNum = sizeof(g_opStruct) / sizeof(OP_STRUCT);

/**
 * calc
 * @brief   Four arithmetic functions
 * @param   op Parameter Description: operator corresponding value
 * @param   op1 Parameter Description: first operand
 * @param   op2 Parameter Description: second operand
 * @retval  double Return value Description: operation result
 */
double calc(int op, double op1, double op2)
{
    if (op >= g_opNum || op < 0)
    {
        printf("unknow operation \n");
        return 0;
    }

    /* Select the operation function directly according to the operation type */
    return g_opStruct[op].opFun(op1, op2);
}

main function code

The main thing is the judgment of command line parameters. The only function related to the self implemented function is double result = calc(op, op1, op2); The calc function uses the jump table.

int main(int argc, char *argv[])
{
    /* Check the number of parameters */
    if (argc != 5)
    {
        printf("please refer to: JumpTable.exe 2 x 3 = \n");
        return 0;
    }

    /* Gets the first parameter for the operation */
	double op1 = atof(argv[1]);
	
    /* Gets the second parameter for the operation */
	int op = -1;
	if(('+' == argv[2][0]) && ('\0' == argv[2][1]))
	{
		op = 0;
	}else if(('-' == argv[2][0]) && ('\0' == argv[2][1]))
	{
		op = 1;
	}else if(('x' == argv[2][0]) && ('\0' == argv[2][1]))
	{
		op = 2;
	}else if(('/' == argv[2][0]) && ('\0' == argv[2][1]))
	{
		op = 3;
	}

	if(op == -1)
	{
		printf("operator is not one of '+','-','x' and '/' \n");
		return 0;
	}
	
    /* Gets the third parameter for the operation */
    double op2 = atof(argv[3]);
    printf("op1:%.1f, op: %s, op2:%.1f \n", op1, argv[2], op2);

    /* Gets the fourth parameter, which is used to maintain the form */
    if(('?' == argv[4][0]) || ('=' == argv[4][0]) && ('\0' == argv[4][1]))
    {
        double result = calc(op, op1, op2);
        printf("result is: %.1f \n", result);
    }else
    {
        printf("Do you want to know the result? \n");
        printf("please refer to: JumpTable.exe 2 x 3 = \n");
    }

    return 0;
}

Complete code

#include <stdio.h>
#include <stdlib.h>

/* Defines an operation as an enumeration type */
typedef enum
{
    OP_ADD = 0,         //Execution: addition
    OP_SUB,             //Performing actions: subtraction
    OP_MUL,             //Perform operations: multiply
    OP_DIV,             //Performing actions: Division
} OP_TYPE;

/* Function pointer with double input parameter and double output parameter */
typedef double (*OP_FUNC)(double, double);

typedef struct OP_STRUCT
{
    OP_TYPE opType;     //Operation type
    OP_FUNC opFun;      //Operation function
} OP_STRUCT;

/*Addition, subtraction, multiplication and division processing function*/
double ADD(double op1, double op2)
{
    return op1 + op2;
}
double SUB(double op1, double op2)
{
    return op1 - op2;
}
double MUL(double op1, double op2)
{
    return op1 * op2;
}
double DIV(double op1, double op2)
{
    return op1 / op2;
}

/* Function jump table */
static OP_STRUCT g_opStruct[] =
{
    {OP_ADD, ADD},
    {OP_SUB, SUB},
    {OP_MUL, MUL},
    {OP_DIV, DIV},
};

/* Maximum number of operations */
static int g_opNum = sizeof(g_opStruct) / sizeof(OP_STRUCT);

/**
 * calc
 * @brief   Four arithmetic functions
 * @param   op Parameter Description: operator corresponding value
 * @param   op1 Parameter Description: first operand
 * @param   op2 Parameter Description: second operand
 * @retval  double Return value Description: operation result
 */
double calc(int op, double op1, double op2)
{
    if (op >= g_opNum || op < 0)
    {
        printf("unknow operation \n");
        return 0;
    }

    /* Select the operation function directly according to the operation type */
    return g_opStruct[op].opFun(op1, op2);
}

int main(int argc, char *argv[])
{
    /* Check the number of parameters */
    if (argc != 5)
    {
        printf("please refer to: JumpTable.exe 2 x 3 = \n");
        return 0;
    }

    /* Gets the first parameter for the operation */
	double op1 = atof(argv[1]);
	
    /* Gets the second parameter for the operation */
	int op = -1;
	if(('+' == argv[2][0]) && ('\0' == argv[2][1]))
	{
		op = 0;
	}else if(('-' == argv[2][0]) && ('\0' == argv[2][1]))
	{
		op = 1;
	}else if(('x' == argv[2][0]) && ('\0' == argv[2][1]))
	{
		op = 2;
	}else if(('/' == argv[2][0]) && ('\0' == argv[2][1]))
	{
		op = 3;
	}

	if(op == -1)
	{
		printf("operator is not one of '+','-','x' and '/' \n");
		return 0;
	}
	
    /* Gets the third parameter for the operation */
    double op2 = atof(argv[3]);
    printf("op1:%.1f, op: %s, op2:%.1f \n", op1, argv[2], op2);

    /* Gets the fourth parameter, which is used to maintain the form */
    if(('?' == argv[4][0]) || ('=' == argv[4][0]) && ('\0' == argv[4][1]))
    {
        double result = calc(op, op1, op2);
        printf("result is: %.1f \n", result);
    }else
    {
        printf("Do you want to know the result? \n");
        printf("please refer to: JumpTable.exe 2 x 3 = \n");
    }

    return 0;
}

 

 

Posted by sorenchr on Sat, 16 Apr 2022 22:49:46 +0930