Control table: Difference between revisions

Content deleted Content added
Spreadsheets: Edit for flow and clarity
C language: Simplify example
Line 210:
 
=== C language ===
ThisThe following example in [[C (programming language)|C]], uses two tables,arrays thethat firsttogether (CT1)form a table data structure. The {{code|ops}} array is a simple [[linear search]], one-dimensional lookuparray table{{endash}} for toobtaining obtain anthe index by matchingof the inputitem (x),that andmatches the secondinput, associated{{code table|op}}. (CT1p),The is{{code|handler_labels}} aarray table ofcontains addresses of labels to jump to. The loop tests each {{code |ops}} item against {{code |op}} and if they match, invokes {{code |goto}} for the label at the same index as the found {{code |ops}} item.
 
<syntaxhighlight lang="c" line style="font-size: 90%;">
static const char CT1ops[] = { "A", "S", "M", "D" }; /* permitted input values */
static const void *CT1phandler_labels[] = { &&Add, &&Subtract, &&Multiply, &&Divide, &&Default}; /* labels to goto & default*/
for (int i = 0; i < sizeof(CT1ops); i++) { /* loop thru ASCII values */
if (op == ops[i]) goto *handler_labels[i];
if (x==CT1[i]) goto *CT1p[i]; /* found --> appropriate label */
}
goto *CT1p[i+1]; /* not found --> default label */
</syntaxhighlight>
 
This canwould be made moreexecute efficientfaster if a 256 byte table is used to translate the raw ASCII valueinput (x{{code|op}}) directly to a dense sequentialan index valuewithout for use in directly locating the branch address from CT1p (i.e. "[[index mapping]]" with a byte-wide array)searching. It will thenwould execute in [[constant time]] for all possible values of x{{code |op}}. (If CT1pa {{code |handler_labels}} item contained the namesname of functionsa function instead of labelsa label, the jump could be replaced with a dynamic function call, eliminating the switch-like {{code|goto}} but decreasing runtime performance by the additional cost of function [[Housekeeping (computing)|housekeeping]]).
 
<syntaxhighlight lang="c" line style="font-size: 80%;">
static const void *CT1phandler_labels[] = {&&Default, &&Add, &&Subtract, &&Multiply, &&Divide};
static const char CT1xhandler_label_index_by_op[] = {
/* the 256 byte table, below, holds values (1,2,3,4), in corresponding ASCII positions (A,S,M,D), all others set to 0x00 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
static const char CT1x[]={
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'1, '\x00'0, '\x00'0, '\x00'4, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'3, '\x00'0, '\x00'0,
'\x00'0, '\x01'0, '\x00'0, '\x00'2, '\x04'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x03'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x02'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x03'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0,
'\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00'0, '\x00',0};
size_t i = handler_label_index_by_op(x);
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'};
goto *handler_labels[i];
/* the following code will execute in constant time, irrespective of the value of the input character (x) */
i = CT1x(x); /* extract the correct subroutine index from table CT1x using its ASCII value as an index initially */
goto *CT1p[i]; /* goto (Switch to) the label corresponding to the index (0=default, 1=Add, 2=Subtract,.) - see CT1p */
</syntaxhighlight>