问题:xz[[cenvENVzxcENV[ fffff ]dsbgENV[fecccccc]nqe W3]NBENV[]ZXC 这个字符串中总共有三个变量区,规定ENV[] 方括号中间包含的即是变量,那么使用的过程中需要找到这个变量在替换。
使用状态机首先需要定义系统的状态的个数及状态之间的转换过程及条件
本例中总共定义了6种状态 common char:普通字符串 env:变量内容 over:状态机终止(字符串超长) maybe:可能属于变量 maybeOver:后面紧跟着的可能是变量 envOver:变量终止。
状态直接的转换关系如图
那么示例字符串(xz[[cenvENVzxcENV[ fffff ]dsbgENV[fecccccc]nqe W3]NBENV[]ZXC)的分解应当如下图:
代码: 状态机定义:
public delegate Tuple<bool, T> HandleType<T>(IState<T> current, IState<T> previous, T originData, int currentIndex);
public interface IState<T>
{
string Name { get; set; }
string Value { get; set; }
//后一个状态u
IList<IState<T>> Nexts { get; set; }
//判断状态如何迁移
Func<IState<T>, T, int, IState<T>> Selector { get; set; }
}
public interface IContext<T> : IEnumerator<T>, IEnumerable<T>
{
/// <summary>
/// 初始值
/// </summary>
T OriginData { get; set; }
/// <summary>
/// 用于在状态机变化过程中自定义写处理方法
/// </summary>
IDictionary<Tuple<IState<T>, IState<T>>, HandleType<T>> Handles { get; set; }
/// <summary>
/// 当前状态
/// </summary>
IState<T> CurrentState { get; set; }
/// <summary>
/// 前件处理
/// </summary>
/// <param name="next"></param>
/// <returns></returns>
bool transition(IState<T> next);
}
public class State : IState<string>
{
/// <summary>
/// 状态类型
/// </summary>
public string Name { get; set; }
/// <summary>
/// 用于保存本次状态过程的值
/// </summary>
public string Value { get; set; }
IList<IState<string>> IState<string>.Nexts { get; set; }
public Func<IState<string>, string, int, IState<string>> Selector { get; set; }
}
/// <summary>
/// 定义的状态机
/// </summary>
public class Context<T> : IContext<T>
{
public Context()
{
Handles = new Dictionary<Tuple<IState<T>, IState<T>>, HandleType<T>>();
}
public T OriginData { get; set; }
private int originDataIndex { get; set; }
T currentData;
public IDictionary<Tuple<IState<T>, IState<T>>, HandleType<T>> Handles { get; set; }
public IState<T> CurrentState { get; set; }
T IEnumerator<T>.Current { get { return currentData; } }
object IEnumerator.Current { get { return currentData; } }
bool IContext<T>.transition(IState<T> next)
{
IContext<T> context = this as IContext<T>;
if (context.CurrentState == null || context.CurrentState.Nexts.Contains(next))
{
var key = Tuple.Create(context.CurrentState, next);
if (context.Handles.ContainsKey(key) && context.Handles[key] != null)
{
var result = context.Handles[key](context.CurrentState, next, OriginData, originDataIndex);
if (!result.Item1)
{
currentData = result.Item2;
return false;
}
else
{
currentData = result.Item2;
}
}
context.CurrentState = next;
return true;
}
return false;
}
bool IEnumerator.MoveNext()
{
IContext<T> context = this as IContext<T>;
IState<T> current = context.CurrentState;
if (current == null)
throw new Exception("必须设置初始状态");
if (context.CurrentState.Selector != null)
{
IState<T> next = context.CurrentState.Selector(context.CurrentState, OriginData, originDataIndex);
var success = context.transition(next);
originDataIndex++;
return success;
}
return false;
}
void IEnumerator.Reset()
{
originDataIndex = 0;
}
#region IDisposable Support
private bool disposedValue = false; // 要检测冗余调用
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)。
}
// TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
// TODO: 将大型字段设置为 null。
disposedValue = true;
}
}
void IDisposable.Dispose()
{
// 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
Dispose(true);
// TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
// GC.SuppressFinalize(this);
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return this;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this;
}
#endregion
}
定义状态机种的状态及状态之间的转换关系
//保存状态变化时的值及对应的状态
var dic = new List<Tuple<string, string>>();
//定义六种状态实例
IState<string> common = new State() { Name = "common char" };
IState<string> env = new State() { Name = "env" };
IState<string> over = new State() { Name = "over" };
IState<string> maybe = new State() { Name = "maybe" };
IState<string> maybeOver = new State() { Name = "maybeOver" };
IState<string> envOver = new State() { Name = "envOver" };
//初始化状态机
IContext<string> stringState = new Context<string> { CurrentState = common };
stringState.OriginData = "";
//附加处理
HandleType<string> attachResolve = (IState<string> previous, IState<string> current, string originData, int currentIndex) =>
{
current.Value += originData[currentIndex];
return new Tuple<bool, string>(true, current.Value);
};
//覆盖处理
HandleType<string> setResolve = (IState<string> previous, IState<string> current, string originData, int currentIndex) =>
{
current.Value = originData[currentIndex].ToString();
dic.Add(new Tuple<string, string>(previous.Name, previous.Value));
return new Tuple<bool, string>(true, current.Value);
};
//over 取前一个状态的值
HandleType<string> preResolve = (IState<string> previous, IState<string> current, string originData, int currentIndex) =>
{
dic.Add(new Tuple<string, string>(previous.Name, previous.Value));
return new Tuple<bool, string>(true, previous.Value);
};
//common char 状态转换 及不同转换条件下处理方法
common.Nexts = new List<IState<string>>() { common, over, maybe };
common.Selector = (state, originData, currentIndex) =>
{
if (currentIndex >= originData.Length)
{
return over;
}
var ch = originData[currentIndex];
if (ch == 'E')
{
return maybe;
}
return common;
};
stringState.Handles.Add(Tuple.Create(common, common), attachResolve);
stringState.Handles.Add(Tuple.Create(common, over), preResolve);
stringState.Handles.Add(Tuple.Create(common, maybe), setResolve);
//env 状态转换 及不同转换条件下处理方法
env.Nexts = new List<IState<string>>() { envOver, over, env };
env.Selector = (state, originData, currentIndex) =>
{
if (currentIndex >= originData.Length)
{
return over;
}
var ch = originData[currentIndex];
if (ch == ']') return envOver; else return env;
};
stringState.Handles.Add(Tuple.Create(env, envOver), setResolve);
stringState.Handles.Add(Tuple.Create(env, over), preResolve);
stringState.Handles.Add(Tuple.Create(env, env), attachResolve);
// maybe 状态转换 及不同转换条件下处理方法
maybe.Nexts = new List<IState<string>>() { maybe, common, env, over, maybeOver };
maybe.Selector = (state, originData, currentIndex) =>
{
if (currentIndex >= originData.Length)
{
return over;
}
var ch = originData[currentIndex];
if (state.Value == "E" && ch == 'N') return maybe;
if (state.Value == "EN" && ch == 'V') return maybe;
if (state.Value == "ENV" && ch == '[')
{
return maybeOver;
}
return common;
};
stringState.Handles.Add(Tuple.Create(maybe, maybe), attachResolve);
stringState.Handles.Add(Tuple.Create(maybe, common), setResolve);
stringState.Handles.Add(Tuple.Create(maybe, env), setResolve);
stringState.Handles.Add(Tuple.Create(maybe, over), preResolve);
stringState.Handles.Add(Tuple.Create(maybe, maybeOver), setResolve);
// maybeOver 状态转换 及不同转换条件下处理方法
maybeOver.Nexts = new List<IState<string>>() { env, envOver, over };
maybeOver.Selector = (state, originData, currentIndex) =>
{
var ch = originData[currentIndex];
if (currentIndex >= originData.Length)
{
return over;
}
if (ch == ']') return envOver;
return env;
};
stringState.Handles.Add(Tuple.Create(maybeOver, env), setResolve);
stringState.Handles.Add(Tuple.Create(maybeOver, over), preResolve);
// envOver 状态转换 及不同转换条件下处理方法
envOver.Nexts = new List<IState<string>>() { common, maybe, over };
envOver.Selector = (state, originData, currentIndex) =>
{
if (currentIndex >= originData.Length)
{
return over;
}
var ch = originData[currentIndex];
if (ch == 'E') return maybe;
return common;
};
stringState.Handles.Add(Tuple.Create(envOver, common), setResolve);
stringState.Handles.Add(Tuple.Create(envOver, maybe), setResolve);
stringState.Handles.Add(Tuple.Create(envOver, over), preResolve);
// over 状态转换 及不同转换条件下处理方法
over.Nexts = new List<IState<string>>() { };
stringState.Handles.Add(Tuple.Create(over, maybe), preResolve);
stringState.Handles.Add(Tuple.Create(over, common), preResolve);
stringState.Handles.Add(Tuple.Create(over, env), preResolve);
stringState.Handles.Add(Tuple.Create(over, envOver), preResolve);
stringState.Handles.Add(Tuple.Create(over, maybeOver), preResolve);
测试:
Console.WriteLine("测试字符串");
string input = "";
// "xz[[cenvENVzxcENV[ fffff ]dsbgENV[fecccccc]nqe W3]NBENV[]ZXC"
while (!string.IsNullOrEmpty(input = Console.ReadLine()))
{
stringState.OriginData = input;
foreach (var item in stringState)
{
Console.WriteLine("当前状态{0}---当前值{1}", stringState.CurrentState.Name, item);
}
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("抽取出的Symbol");
dic.ForEach(a =>
{
Console.WriteLine("字符串类型:" + a.Item1 + "-------------分解值:" + a.Item2);
});
}
测试结果:
测试字符串 xz[[cenvENVzxcENV[ fffff ]dsbgENV[fecccccc]nqe W3]NBENV[]ZXC
当前状态common char---当前值x
当前状态common char---当前值xz
当前状态common char---当前值xz[
当前状态common char---当前值xz[[
当前状态common char---当前值xz[[c
当前状态common char---当前值xz[[ce
当前状态common char---当前值xz[[cen
当前状态common char---当前值xz[[cenv
当前状态maybe---当前值E
当前状态maybe---当前值EN
当前状态maybe---当前值ENV
当前状态common char---当前值z
当前状态common char---当前值zx
当前状态common char---当前值zxc
当前状态maybe---当前值E
当前状态maybe---当前值EN
当前状态maybe---当前值ENV
当前状态maybeOver---当前值[
当前状态env---当前值
当前状态env---当前值
当前状态env---当前值
当前状态env---当前值
当前状态env---当前值
当前状态env---当前值
当前状态env---当前值 f
当前状态env---当前值 ff
当前状态env---当前值 fff
当前状态env---当前值 ffff
当前状态env---当前值 fffff
当前状态env---当前值 fffff
当前状态env---当前值 fffff
当前状态envOver---当前值]
当前状态common char---当前值d
当前状态common char---当前值ds
当前状态common char---当前值dsb
当前状态common char---当前值dsbg
当前状态maybe---当前值E
当前状态maybe---当前值EN
当前状态maybe---当前值ENV
当前状态maybeOver---当前值[
当前状态env---当前值f
当前状态env---当前值fe
当前状态env---当前值fec
当前状态env---当前值fecc
当前状态env---当前值feccc
当前状态env---当前值fecccc
当前状态env---当前值feccccc
当前状态env---当前值fecccccc
当前状态envOver---当前值]
当前状态common char---当前值n
当前状态common char---当前值nq
当前状态common char---当前值nqe
当前状态common char---当前值nqe
当前状态common char---当前值nqe
当前状态common char---当前值nqe W
当前状态common char---当前值nqe W3
当前状态common char---当前值nqe W3]
当前状态common char---当前值nqe W3]N
当前状态common char---当前值nqe W3]NB
当前状态maybe---当前值E
当前状态maybe---当前值EN
当前状态maybe---当前值ENV
当前状态maybeOver---当前值[
当前状态envOver---当前值[
当前状态common char---当前值Z
当前状态common char---当前值ZX
当前状态common char---当前值ZXC
当前状态over---当前值ZXC
抽取出的Symbol
字符串类型:common char-------------分解值:xz[[cenv
字符串类型:maybe-------------分解值:ENV
字符串类型:common char-------------分解值:zxc
字符串类型:maybe-------------分解值:ENV
字符串类型:maybeOver-------------分解值:[
字符串类型:env-------------分解值: fffff
字符串类型:envOver-------------分解值:]
字符串类型:common char-------------分解值:dsbg
字符串类型:maybe-------------分解值:ENV
字符串类型:maybeOver-------------分解值:[
字符串类型:env-------------分解值:fecccccc
字符串类型:envOver-------------分解值:]
字符串类型:common char-------------分解值:nqe W3]NB
字符串类型:maybe-------------分解值:ENV
字符串类型:envOver-------------分解值:]
字符串类型:common char-------------分解值:ZXC