2. Get The Number of Days in a Month
if (month == 1) days = 31;
else if (month == 2) days = 28;
else if (month == 3) days = 31;
else if (month == 4) days = 30;
else if (month == 5) days = 31;
else if (month == 6) days = 30;
Method 1: 12 comparisons
switch(month) {
case 1: days = 31; break;
case 2: days = 28; break;
case 3: days = 31; break;
case 4: days = 30; break;
case 5: days = 31; break;
case 6: days = 30; break;
case 7: days = 31; break;
Method 3: 6 comparisons
if (month == 1) days = 31;
if (month == 2) days = 28;
if (month == 3) days = 31;
if (month == 4) days = 30;
if (month == 5) days = 31;
if (month == 6) days = 30;
if (month == 7) days = 31;
Method 2: 6 comparisons
else if (month == 6) days = 30;
else if (month == 7) days = 31;
else if (month == 8) days = 31;
else if (month == 9) days = 30;
else if (month == 10) days = 31;
else if (month == 11) days = 30;
else if (month == 12) days = 31;
int DaysPerMonth[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
if ( (month >= 1) && (month <=12) ) {
days = DaysPerMonth[month];
}
Table-Driven Method: 2 comparison
case 7: days = 31; break;
case 8: days = 31; break;
case 9: days = 30; break;
case 10: days = 31; break;
case 11: days = 30; break;
case 12: days = 31; break; }
if (month == 7) days = 31;
if (month == 8) days = 31;
if (month == 9) days = 30;
if (month == 10) days = 31;
if (month == 11) days = 30;
if (month == 12) days = 31;
3. Indirect Function Call
int (*funcptr)(int, int);
void main(void)
{
int func1(int a, int b)
{
return a+b;
int result;
funcptr = func1;
result = (*funcptr)(1,2);
funcptr = func2;
result = (*funcptr)(2,3);
}
}
int func2(int a, int b)
{
return a+b;
}
4. Table-Driven Method
with Indirect Function Call
switch(class) {
case 1:
Statements 001;
break;
case 2:
void func001(void) {
Statements 001;
}
void func002(void) {
Statements 002;
General Method:
Average 50 Comparisons
Table-Driven Method:
Always 0 comparisons
break;
case 2:
Statements 002;
break;
case 3:
Statements 003;
break;
……
……
case 100:
Statements 100;
break;
}
Statements 002;
}
……
void func100(void) {
Statements 100;
}
void (*func_tbl[ ])(void)={
func000, func001, func002,
……… , func099, func100 }
(*func_tbl[class])();
5. Table-Driven Method
with Indirect Function Call(Cont.)
switch(class) {
case 0x0057:
Statements 001;
break;
case 0x0811:
struct {
int id;
void (*funcptr)(void);
} class_tbl[] = {
{ 0x0057, func001 },
General Method:
Average 50 Comparisons
Table-Driven Method:
Average 50 Comparisons but flexible
break;
case 0x0811:
Statements 002;
break;
case 0x0C0C:
Statements 003;
break;
……
……
case 0xABAB:
Statements 100;
break;
}
} class_tbl[] = {
{ 0x0057, func001 },
{ 0x0811, func002 },
{ 0x0C0C, func003 },
……
{ 0xABAB, func100 },
{ 0x0000, NULL }};
for (int i=0; class_tbl[i].id != 0; i++) {
if ( class_tbl[i].id == class) {
(*class_tbl[i].funcptr)();
break;
}
}
6. Example 1:
Message Map in Window MFC Programs
switch(message) {
case WM_CREATE:
Statements 1;
break;
case WM_SIZE:
Statements 2;
struct {
UINT id;
LONG (*pfn)(HWND, UINT, WPARAM,
LPARAM);
} mesg_map[ ] = {
{ WM_CREATE, OnCREATE },
General Method: Table-Driven Method:
Statements 2;
break;
case WM_VSCROLL:
Statements 3;
break;
case WM_PAINT:
Statements 4;
break;
case WM_DESTROY:
Statements 5;
break;
}
{ WM_CREATE, OnCREATE },
{ WM_SIZE, OnSIZE },
{ WM_VSCROLL, OnVSCROLL },
{ WM_PAINT, OnPAINT },
{ WM_DESTROY, OnDESTROY },
{ 0 , NULL }};
for (int i=0; mesg_map[i].id != 0; i++) {
if ( mesg_map[i].id == message)
return ((*mesg_map[i].pfn)(hWnd,
message, wParam, lParam));
}
7. Example 2: Check Number Format
State Transition Diagram
430 2
digitStart
1 5 6
digit digit. E/e +/-
digit 、nullnull
digit
digit 、null digit 、null
Any input
E/e digit
State 0: The start (or Initial) state.
State 1,3,6: The accepting (or final) states.
State 7: The error state.
Examples: 123、123.456、 123E45、 12.34E-23、12e+12
7
Any other input...
8. Example 2: Check Number Format
How to Classify the Input Key ?
switch( buf[index] ) {
case ‘000’:
ctype = 0;
break;
case ‘0’:
case ‘1’:
case ‘2’:
…..
case ‘9’:
const unsigned char keymap[128] =
{
0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
// ! " # $ % & ' ( ) * + , - . /
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 4, 2, 5,
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
General Method: Table-Driven Method:
…..
case ‘9’:
ctype = 1;
break;
case ‘.’:
ctype = 2;
break;
case ‘E’:
case ‘e’:
ctype = 3;
break;
case ‘+‘:
case ‘-’:
ctype = 4;
break;
default:
ctype = 5;
break;
}
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5,
// @ A B C D E F G H I J K L M N O
5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
// P Q R S T U V W X Y Z [ ] ^ _
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
// ` a b c d e f g h i j k l m n o
5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
// p q r s t u v w x y z { | } ~
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
};
ctype = keymap[buf[index]];
11. Example 2: Check Number Format
Finite State Machine Real C Code
Char buf[128];
int index;
unsigned state, ctype;
void main(void)
{{
printf("Please input the string to check: ");
scanf("%s", buf);
index = 0; state = S00;
while (1) {
ctype = keymap[buf[index]];
(*state_tbl[state][ctype].operation)();
state = state_tbl[state][ctype].next_state;
++index;
}
}
12. C: Clear key
E: Error input key
N: Number keys
O: Operator keys
S: Signed key
Example 3: Simple Calculator
State Transition Diagram
1
E,N,
S,D,A
C Q
O
S: Signed key
D: Dot key
Q: eQual key
A: All other input keys
State 0: Input operand A state.
State 1: Input operand B state.
State 2: After input operand state.
State 3: After press equal key state.
30
2
C,E,N,
S,D,A
E,O,
S,A
E,Q,A
N,D
Q
C
O
Q
C,N,D
O,S
13. Example 3: Simple Calculator
How to Classify the Input Key ?
switch(key=getch()) {
case ‘c’:
case ‘C’:
class = 0;
break;
case ‘e’:
case ‘E’:
class = 1;
int key_tbl[128] = {
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
// ! “ # $ % & ‘ ( ) * + , - . /
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 7, 3, 5, 3,
General Method: Table-Driven Method:
class = 1;
break;
case ‘0’:
case ‘1’:
case ‘2’:
…..
case ‘9’:
class = 2;
break;
…..
…..
case ‘=‘:
class = 6;
break;
default:
class = 7;
break;
}
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, 6, 7, 7,
// @ A B C D E F G H I J K L M N O
7, 7, 7, 0, 7, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
// P Q R S T U V W X Y Z [ ] ^ _
7, 7, 7, 4, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 7,
// ` a b c d e f g h i j k l m n o
7, 7, 7, 0, 7, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
// p q r s t u v w x y z { | } ~
7, 7, 7, 4, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 };
class = key_tbl[key=getch()];
14. Example 3: Simple Calculator
State Transition Table
Input
State
C E N O S D Q A
0 0
cancel
0
erase
0
update
2
set_op
0
sign
0
dot
3
nop
0
nop0 cancel erase update set_op sign dot nop nop
1 0
cancel
1
erase
1
update
2
go_op
1
sign
1
dot
3
go
1
nop
2 0
cancel
2
nop
1
set_B
2
set_op
2
sign
1
dot_B
3
cp_go
2
nop
3 0
cancel
3
nop
0
set_A
2
set_op
2
sign
0
dot_A
3
nop
3
nop
15. FSM States:
State 0: Key Idle.
State 1: Key Pressed.
State 2: Key Pressed & Hold.
Example 4: KeyScan Algorithm
State Transition Diagram
State 2: Key Pressed & Hold.
State 3: Key Released.
FSM Actions:
Key Release w/o TimeOut
Key Pressed w/o TimeOut
Key Release w/ TimeOut
Key Pressed w/ TimeOut
17. Example 4: KeyScan Algorithm
State Transition Table Description
Key Scan State:
KEY_STATE_IDLE: Key without any action.
KEY_STATE_PRESS: Key has been pressed but maybe bouncing.
KEY_STATE_HOLD: Key is not bouncing and still on holding.
KEY_STATE_RELEASE: Key has been released and wait for timeout.
Key Scan Input: Key Scan Input:
ACT_xTMOT_RELEASE: Action release without timeout.
ACT_xTMOT_PRESS: Action press without timeout.
ACT_oTMOT_RELEASE: Action release with timeout.
ACT_oTMOT_PRESS: Action press with timeout.
Key Counter Value:
KEY_COUNT_IDLE: Counter value in state "KEY_STATE_IDLE".
KEY_COUNT_PRESS1: Counter value for 1st key press code to be sent.
KEY_COUNT_PRESS2: Counter value for 2nd key press code to be sent.
KEY_COUNT_PRESSn: Counter value for n>2 key press code to be sent.
KEY_COUNT_RELEASE: Counter value for key release code to be sent.
18. Example 4: KeyScan Algorithm
Sample Code Description
程式一開始註解中, 將 FSM Table 列出來: 此 FSM 中定義了四
個狀態, 與四種可能的輸入值,
而實際表現在程式中就是 2D Array
"fsm_kbd_tbl[KEY_STATE_MAX][ACT_INPUT_MAX]".
Table "key_ctrl_tbl[]" 是描述預期要掃描的按鍵定義 & 預期回傳
的鍵值.的鍵值.
主要函式 "kbd_key_scan( unsigned cur_key_scan )" 預期掛在 ISR
中, 將所有按鍵掃一次.
而以下MACRO定義三段Count時間長度, 單位為ISR被執行的次
數:
#define KEY_COUNT_PRESS1 2 // Tick Period for 1st Key Press
to be Validated
#define KEY_COUNT_PRESS2 15 // Tick Period for 2nd Key
Press to be Validated
#define KEY_COUNT_PRESSn 5 // Tick Period for 2:n Key Press
to be Validated
19. The Restriction of Finite State Machine
Finite State Machine: A machine without
memory to record the past input.
Finite State Machine CAN’T Handle…Finite State Machine CAN’T Handle…
The match of “(” and “)” in the expressions.
The match of “{” and “}” in C/C++ block.
The match of “begin” and “end” in PASCAL.
……...
We can handle above problems if we add a
stack to the FSM Push-Down Automata
20. Hierarchy of Languages(Automata):
Chomsky Hierarchy
Type 3: Regular (Right Linear) Language
Finite-State Automata
Type 2: Context-Free LanguageType 2: Context-Free Language
Push-Down Automata
Type 1: Context-Sensitive Language
Linear-Bounded Automata
Type 0: Contracting Context-Sensitive
Turing Machines