<?php
// 有限状态机的简单应用
// 解决问题:将字符串中多于一个的空格变为一个空格输出
$str = 'Memcached is simple yet powerful.'; //最初字符串
var_dump($str);
$state = 0; // 初始状态
$index = 0;
$len = strlen($str); // str length
$input = 0; // input
$result_str = '';
while($index < $len) {
$c = $str[$index++]; // 读入字符
$input = get_input_type($c); // 输入类型
// $input 输入类型:0 非空格字符, 1 空格
// $state 状态:0 初始状态, 1 遇到第一个空格, 2 遇到第二个以及更多空格
// 状态迁移
if($state === 0 && $input === 0) {
$state = 0;
$result_str .= $c; //采取相应的动作
} else
if($state === 0 && $input === 1) { // 遇到第一个空格, state = 1, 输出该空格
$state = 1;
$result_str .= $c;
} else
if($state === 1 && $input === 0) {
$state = 0;
$result_str .= $c;
} else
if($state === 1 && $input === 1) { // 遇到连续的第二个空格, state = 2, 该空格不再输出
$state = 2;
} else
if($state === 2 && $input === 0) {
$state = 0;
$result_str .= $c;
} else
if($state === 2 && $input === 1) { // 遇到连续的三个空格, 状态保持不变, 空格依然不输出
$state = 2;
}
}
// 获取输入类型
function get_input_type($c) {
if($c === ' ') {
return 1;
}
return 0;
}
var_dump($result_str);
将问题抽象化:
抽象出来两个二维数组:状态迁移表,执行动作表
二维数组的第一维是 $state 状态值, 第二维是 $input 输入类型
改进代码如下:
<?php
// 有限状态机的简单应用
// 解决问题:将字符串中多于一个的空格变为一个空格输出
$str = 'Memcached is simple yet powerful.';
var_dump($str);
// 将问题抽象
// int [state][input]
// 状态迁移表
$state_transition = array(
[0, 1],
[0, 2],
[0, 2],
);
// 动作表
$act_table = array(
['concat_str', 'concat_str'],
['concat_str', 'act_null'],
['concat_str', 'act_null'],
);
$state = 0; // init state
$input = 0; // input
$index = 0;
$len = strlen($str); // str length
$result_str = '';
$char = '';
while($index < $len) {
$char = $str[$index++]; // 读入字符
$input = get_input_type($char); // 输入类型
$callback = $act_table[$state][$input];
call_user_func($callback);
$state = $state_transition[$state][$input];
}
// 获取输入类型
function get_input_type($c) {
if($c === ' ') {
return 1;
}
return 0;
}
// 连接字符串
function concat_str() {
global $result_str;
global $char;
$result_str .= $char;
}
// 什么也不做
function act_null() {
return ;
}
var_dump($result_str);