zoukankan      html  css  js  c++  java
  • 老赵的《趣味编程:从字符串中提取信息》的一个解决方案

    足足3个月没有打开我的Visual Studio 2008,超过半年没有认认真真写过C# ,今天突然看到老赵提出了一个问题——趣味编程:从字符串中提取信息 ,勾起了我对大学时光的怀念,特写此文。

    老赵的问题简单的来说,就是从以下这段字符串:

    cpu-3.0g--color-red-green-black--price-5000-8000--weight-'3-'--keywords-'levi''s'

    解析得出需要的信息:

    new List
    {
        new string[] { "cpu", "3.0g" },
        new string[] { "color", "red", "green", "black" },
        new string[] { "price", "5000", "8000" },
        new string[] { "weight", "3-" },
        new string[] { "keywords", "levi's" },
    }

    看到这个问题一下子就让我想起了大学的《编译原理》的词法分析器,我十分怀疑老赵是不是在某本编译原理的书里面得到灵感的,呵呵呵呵。

    这是我们当时的课本:

    bb289e9f-7a4a-40d4-817c-c08c803c731c好难懂,认认真真学一周,竟然看不明白一章书,唉……,现在基本上都忘得差不多了……,下文有什么说得不恰当的地方欢迎大家指正。

    我的程序是基于状态机来做的,优点就是对输入仅作一次向前的扫描。

    缺点非常明显——难维护,相当难维护,用时髦一点的语言来说叫不够敏捷。

    还是言归正传吧,我用的是状态机的思路去解决这个问题。

    我将老赵所说的字符归为三类:

    1。平常字符,例如:A-Za-z0-9.,+等,简称Common、C

    2。分隔符,这里只有一个 - , 简称 Splitor、S

    3。块符,这里也只有一个 ' 简称 Block 、 B

    其实可以简单地认为,除了第二、第三种剩下的就是第一种了。

    构建一个状态跳转图,知识忘记得太多了,可能图不标准。

    image 突然,发现远看这个状态跳转图也挺有艺术感的啊,哈哈哈哈。

    我用哈希表存储这张图:

    //构建跳转表
    DictionaryJumpWorkTable=newDictionary();
    JumpTable.Add("0,Common",1);
    JumpTable.Add("0,Block",4);
    JumpTable.Add("0,Splitor",0);
    JumpTable.Add("1,Splitor",2);
    JumpTable.Add("1,Common",1);
    JumpTable.Add("2,Common",1);
    JumpTable.Add("2,Splitor",3);
    JumpTable.Add("2,Block",4);
    JumpTable.Add("3,Common",1);
    JumpTable.Add("3,Block",4);
    JumpTable.Add("4,Common",4);
    JumpTable.Add("4,Splitor",4);
    JumpTable.Add("4,Block",5);
    JumpTable.Add("5,Block",4);
    JumpTable.Add("5,Splitor",2);

    每一步跳转都会依据输入进行一定的处理,对应的表如下:

    Dictionary JumpWorkTable = new Dictionary();
    JumpWorkTable.Add("0,1", start);
    JumpWorkTable.Add("0,0", idle);
    JumpWorkTable.Add("1,1", inputCommonChar);
    JumpWorkTable.Add("1,2", endToken);
    JumpWorkTable.Add("2,1", startToken);
    JumpWorkTable.Add("2,3", endGroup);
    JumpWorkTable.Add("2,4", startToken);
    JumpWorkTable.Add("3,1", startToken);
    JumpWorkTable.Add("3,4", startToken);
    JumpWorkTable.Add("4,4", inputCommonChar);
    JumpWorkTable.Add("4,5", idle);
    JumpWorkTable.Add("5,4", inputCommonChar);
    JumpWorkTable.Add("5,2", endToken);

    根据这两张表做的动作就很简单了:

    /// 
    /// 从一个状态跳转到另一个状态
    /// 
    /// 现在所处的状态
    /// 输入的char
    /// 跳转到新的状态
    public int Jump(int nowPosition, char c)
    {
        if (((int)c) > 0)
        {
            string jump = nowPosition.ToString() + "," + JudgeChar(c);
            int nextPosition = JumpTable[jump];
            string work = nowPosition.ToString() + "," + nextPosition;
            JumpWorkTable[work](c);
            return nextPosition;
        }
        else
        {
            //不重要
        }
    }

    主程序调用也很简单了:

    InputSource source = new InputSource();
    FSM fsm = new FSM();
    int nowPosition = 0;
    
    while (source.HashToken())
    {
        char c = source.GetNextChar();
        nowPosition = fsm.Jump(nowPosition, c);
    }
    fsm.Jump(nowPosition, (char)0);

    可以说,整个程序的核心就是要弄明白上面的状态跳转图,以及每步跳转要做什么事情。虽然程序不长,但是基本上的脑力都是耗费在状态跳转图上面,如果状态跳转有少许差错就废了。

    源代码下载

  • 相关阅读:
    [WinJS] Promise 用法
    Python 统计代码行
    mac下Apache + MySql + PHP网站开发
    android中,获取网速的方法实现
    如何屏蔽掉两个activity切换时的动画效果
    dp与px的相互转化
    毫秒的格式化
    关于android中事件传递和分发的一些小理解
    汉字转拼音
    关于实现无限循环的做法
  • 原文地址:https://www.cnblogs.com/killkill/p/1582130.html
Copyright © 2011-2022 走看看