Introduction to table-Driven Methods

Source: Internet
Author: User

The use of function pointers is actually very flexible. It has a lot of technical applications, and the application in the table-driven method is very typical. Here I will introduce it in detail.
What is a table-driven method?
A table is a very useful data structure to be discussed in almost all data structure textbooks. The table-driven method is used for a specific purpose and will be discussed below.
Programmers often talk about the "table-driven" method, but the textbook never mentions the "table-driven" method.A table-driven method allows you to search for information in a table without using many logical statements (if or case.In fact, any information can be selected through tables. In simple cases, logical statements are often simpler and more direct. However, with the complexity of the logical chain, tables become more and more attractive. Through the example below, we can know what the so-called Table-driven method is.
Suppose you need a function that can return the day of every month (for the sake of simplicity, skip the year). A stupid method is a large if statement:

int iGetMonthDays(int iMonth)
{
int iDays;
if(1 == iMonth) {iDays = 31;}
else if(2 == iMonth) {iDays = 28;}
else if(3 == iMonth) {iDays = 31;}
else if(4 == iMonth) {iDays = 30;}
else if(5 == iMonth) {iDays = 31;}
else if(6 == iMonth) {iDays = 30;}
else if(7 == iMonth) {iDays = 31;}
else if(8 == iMonth) {iDays = 31;}
else if(9 == iMonth) {iDays = 30;}
else if(10 == iMonth) {iDays = 31;}
else if(11 == iMonth) {iDays = 30;}
else if(12 == iMonth) {iDays = 31;}
return iDays;
}

Example
It can be seen that the code is so redundant that the table-driven method can be used to solve this problem.

Static int aimonthdays [12] = {31,28, 31,30, 31,30, 31,31, 30,31, 30,31 };
/* We can first define a static array, which is used to save the number of days of a year and 12 months */
Int igetmonthdays (INT Imonth)
{
Return aimonthdays [(Imonth-1)];
}


Example
I don't need to talk about it. You can see that this table-driven method is not strong enough to replace this kind of logic line, but it is amazing to have a lot of code in the branch.

Function:

Application of function pointers in table-Driven Methods
When using the table-driven method, you must note what you will store in the table. In some cases, the Table query result is data. In this case, you can store the data in the table. In other cases, the result of table search is an action. In this case, you can store the code that describes this action in the table. In some languages, you can also store the call of the subroutine that implements this action in the table, that is, the pointer of the function is saved in the table. When this is found, let the program use this function pointer to call the corresponding program code. This is the application of the function pointer in the table-driven method.
As a matter of fact, I have already mentioned many table-driven methods. Now I want to apply the function pointer. Many people should have thought of what it will look like. It is actually quite simple, the following two pseudo-code examples can fully reflect that the application of function pointers in the table-driven method will make the code more refined.
We often encounter this problem when writing a program. When writing a main function of a task, we sometimes have to wait for different event notifications and process different branches, first, we have the macro definition of event bit and the declaration of corresponding processing functions.

#define TASK_EVENT_BIT00   (1 << 0)
#define TASK_EVENT_BIT01 (1 << 1)
#define TASK_EVENT_BIT02 (1 << 2)
#define TASK_EVENT_BIT03 (1 << 3)
#define TASK_EVENT_BIT04 (1 << 4)
#define TASK_EVENT_BIT05 (1 << 5)
#define TASK_EVENT_BIT06 (1 << 6)
#define TASK_EVENT_BIT07 (1 << 7)
#define TASK_EVENT_BIT08 (1 << 8)
#define TASK_EVENT_BIT09 (1 << 9)

void vDoWithEvent00();
void vDoWithEvent01();
void vDoWithEvent02();
void vDoWithEvent03();
void vDoWithEvent04();
void vDoWithEvent05();
void vDoWithEvent06();
void vDoWithEvent07();
void vDoWithEvent08();
void vDoWithEvent09();

The first thing we come up with is:

unsigned long ulEventBit;
for(;;)
{
xos_waitFlag(&ulEventBit);
if(ulEventBit & TASK_EVENT_BIT00)
{
vDoWithEvent00();
}
if(ulEventBit & TASK_EVENT_BIT01)
{
vDoWithEvent01();
}
if(ulEventBit & TASK_EVENT_BIT02)
{
vDoWithEvent02();
}
if(ulEventBit & TASK_EVENT_BIT03)
{
vDoWithEvent03();
}
if(ulEventBit & TASK_EVENT_BIT04)
{
vDoWithEvent04();
}
if(ulEventBit & TASK_EVENT_BIT05)
{
vDoWithEvent05();
}
if(ulEventBit & TASK_EVENT_BIT06)
{
vDoWithEvent06();
}
if(ulEventBit & TASK_EVENT_BIT07)
{
vDoWithEvent07();
}
if(ulEventBit & TASK_EVENT_BIT08)
{
vDoWithEvent08();
}
if(ulEventBit & TASK_EVENT_BIT09)
{
vDoWithEvent09();
}
}

Example
It can be seen that the write process is too long.
Next let's take a look at the same piece of code using a function pointer and a table-driven method to write what it looks like.

Typedef struct {
Unsigned long uleventbit;
Void (* func) (void );
} Eventdowithtable_t;
/* Struct defining the relationship between eventbit and corresponding processing functions */

Static const eventdowithtable_t astdowithtable [] = {
{Task_event_bit00, vdowithevent00 },
{Task_event_bit01, vdowithevent01 },
{Task_event_bit02, vdowithevent02 },
{Task_event_bit03, vdowithevent03 },
{Task_event_bit04, vdowithevent04 },
{Task_event_bit05, vdowithevent05 },
{Task_event_bit06, vdowithevent06 },
{Task_event_bit07, vdowithevent07 },
{Task_event_bit08, vdowithevent08 },
{Task_event_bit09, vdowithevent09}
};
/* Create an eventbit table with corresponding processing functions */

Ulong uleventbit;
Int I;
For (;;)
{
Xos_waitflag (& uleventbit );
For (I = 0; I <sizeof (astdowithtable)/sizeof (astdowithtable [0]); I ++)
{
If (uleventbit & astdowithtable [I]. uleventbit )&&
(Astdowithtable [I]. func! = NULL ))
{
(* Astdowithtable [I]. func )();
/* Use the function pointer to call the corresponding processing function */
}
}
}

Example
It can be seen that this code style makes the code much more refined, and the flexibility of the program is greatly enhanced. If we want to add eventbit, we only need to modify the content in the table.
Summary
As described above, I believe you have some knowledge about how to use function pointers. However, we need to remind you that you must analyze the specific situation in every case, be careful when using function pointers because function pointers have a fatal disadvantage.
The fatal disadvantage of a function pointer is that you cannot check the types of parameters and return values. Because the function has been degraded to a pointer, the pointer does not carry such type information. If the type check is missing, serious errors may occur when the parameters or reverse return values are inconsistent. Some compilers do not help us find such fatal errors as function pointers. Therefore, many new programming languages do not support function pointers, but use other methods instead.
From the above example 3, we can see that
Int max (int x, int y) {return x> Y? X: Y ;}
Int min (int x, int y) {return x <Y? X: Y ;}
Int add (int x, int y) {return X + Y ;}

All three functions have two parameters, but the processing function is defined later

Int process (int x, int y, INT (* f )())
{
Return (* f) (x, y );
}
The third parameter is a pointer to a function. On the surface, it is a pointer to a function with no parameters and INT type is returned. However, process (a, B, max). Max has two parameters. This program can be compiled smoothly in C Language (but not in C ++ ), it can be seen that if the compiler does not check for errors and we accidentally write the errors, the consequences will be very serious, such as return (* f) (x, y ); accidentally writing return (* f) (x); it can be compiled normally in C language, but the running result must not be what we want.
Therefore, when using function pointers in C, be careful with the "type trap" and use function pointers. Only in this way can we benefit from function pointers.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.