前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >原 状态机 搜索字符串中的特定占位符

原 状态机 搜索字符串中的特定占位符

作者头像
魂祭心
发布2018-05-17 16:09:58
3.3K0
发布2018-05-17 16:09:58
举报
文章被收录于专栏:魂祭心魂祭心

问题: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)的分解应当如下图:

代码: 状态机定义:

代码语言:javascript
复制
  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
    }

定义状态机种的状态及状态之间的转换关系

代码语言:javascript
复制
            //保存状态变化时的值及对应的状态
            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);

测试:

代码语言:javascript
复制
             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);
                });
            }

测试结果:

代码语言:javascript
复制
测试字符串 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
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档