日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

趣味编程:从字符串中提取信息(参考答案 - 上)

發布時間:2025/3/21 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 趣味编程:从字符串中提取信息(参考答案 - 上) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這次“趣味編程”的目的是解析字符串,從一個指定模式的字符串中提取信息。對于目前這個問題,解決方案有很多種,例如直接拆分,使用正則表達式,或是如現在本文這般按照順序解析。總結果上來說,這些做法都是可取的,不過現在我打算舉出的做法是我認為最為“典型”也最有“學習”和“展現”價值的解決方案:基于狀態機的順序字符解析。也歡迎您對此其他的做法進行深入分析。

您可能需要重新閱讀上一篇文章來回憶字符串解析的具體規則,起始歸納起來,它只有以下三點:

  • 一個text由一至多個token group組成;一個token group由一至多個token組成。
  • token group的token之間使用單條橫線“-”進行分割;text的token group之間使用兩條橫線“--”進行分割。
  • token可以使用單引號包裹,單引號包裹內的橫線作為普通字符處理,單引號包裹內使用兩個單引號表示單個單引號。
  • 至于最終結果,便是將一個text字符串,拆分成一個token group列表:

    static List<List<string>> Parse(string text) { ... }

    在這里,我們使用List<string>來表示一個token group(即token列表)。自然,表現方式可以有所不同。例如您的Parse方法如果返回“列表的數組”、“數組的列表”或是“數組的數組”都是沒有任何問題的。

    下面的做法基于winter-cn在上一篇文章后面的回復,再加以簡單的修改和注釋后得到的結果。這個做法的思路和我在“出題”時已經準備的“參考答案”不謀而合,但是winter-cn的實現要比我的更為簡單、因此我的代碼就不拿出來獻丑了,我們現在一起來欣賞高手的勞動成果。

    winter-cn的做法,是將“解析”工作拆分為5種狀態,每種狀態對應一種解析邏輯,而每種解析邏輯除了處理當前字符(改變一些公共狀態)以外,還會返回處理下一個字符所使用的“解析邏輯”——這就是狀態的遷移。winter-cn原有的做法是使用Func<char, object>來表示解析邏輯的類型,這樣在每次得到新狀態之后,還需要將其轉化為Func<char, object>。不過為了更清晰地表達這樣一種邏輯,我們也可以定義一個返回自身類型的“遞歸”的委托類型:

    delegate StateParser StateParser(char ch);

    在現在的實現中,我們把它解析過程分解為5個狀態,分別對應不同“時刻”下的解析邏輯:

    static List<List<string>> Parse(string text) {StateParser p1 = null; // 用于解析token的起始字符StateParser p2 = null; // 用于解析作為分隔符的“-”的下一個字符StateParser p3 = null; // 用于解析token中或結尾的單引號的下一個字符StateParser p4 = null; // 用于解析單引號外的token字符StateParser p5 = null; // 用于解析單引號內的token字符var currentToken = new StringBuilder(); // 用于構建當前的token(即收集字符)var currentTokenGroup = new List<string>(); // 用于構建當前的token group(即收集token)var result = new List<List<string>>(); // 用于保存結果(即收集token group)...return result; }

    p1至p5便是所謂的“狀態”,也就是“解析邏輯”,它們都會操作currentToken,currentTokenGroup和result三個數據,并返回下一個狀態。狀態的劃分并非只有一種,不同的狀態劃分方式會形成不同的邏輯。我們接下來便要根據這樣的劃分方式,為每個狀態指定實現了。在實現的過程中,我們需要時刻遵守“當前”狀態的邏輯細節,以及其他狀態的職責,這樣實現狀態的遷移似乎也并不是一件困難的事情。

    首先是p1,它的作用是解析token的第一個字符:

    // 解析token的起始字符 p1 = ch => {if (ch == '-'){// 如果token中需要包含單引號或“-”,// 那么這個token在表示的時候一定需要用一對單引號包裹起來throw new ArgumentException();}if (ch == '\''){// 如果起始字符是單引號,// 則開始解析單引號內的token字符return p5;}else{// 如果是普通字符,則作為當前token的字符,// 并開始解析單引號外的token字符currentToken.Append(ch);return p4;}};

    接著是p2:它的作用是解析分隔符“-”(不包括單引號包裹內的“-”)后的下一個字符:

    // 解析作為分隔符的“-”的下一個字符 p2 = ch => {if (ch == '-'){// 如果當前字符為“-”,說明一個token group結束了(因為前一個字符也是“-”),// 則將當前的token group加入結果集,并且準備新的token groupresult.Add(currentTokenGroup);currentTokenGroup = new List<string>();return p1;}else if (ch == '\''){// 如果當前字符為單引號,則說明新的token以單引號包裹// 則開始解析單引號內的token字符return p5;}else{// 如果是普通字符,則算作當前token的字符,// 并繼續解析單引號外的token字符currentToken.Append(ch);return p4;} };

    接著是p3:解析token內部或結尾的單引號的下一個字符:

    // 解析token內部或結尾的單引號的下一個字符 p3 = ch => {if (ch == '\''){// 如果當前字符為單引號,則說明連續兩個單引號,// 所以表明token中出現了“單個”單引號,并且當前token一定包裹在單引號內,// 因此繼續解析單引號內的token字符currentToken.Append('\'');return p5;}else if (ch == '-'){// 如果當前字符為一個分隔符,則說明上一個token已經結束了// 于是將當前token加入當前token group,準備新的token,// 并解析分隔符后的下一個字符currentTokenGroup.Add(currentToken.ToString());currentToken = new StringBuilder();return p2;}else{// 單引號后面只可能是另一個單引號或者一個分隔符,// 否則說明輸入錯誤,則拋出異常throw new ArgumentException();} };

    最后則是p4和p5,分別用于處理普通的token以及被單引號包裹的token字符:

    // 用于解析單引號外的token字符, // 即一個沒有特殊字符(分隔符或單引號)的token p4 = ch => {if (ch == '\''){// 如果token中出現了單引號,則拋出異常throw new ArgumentException();}if (ch == '-'){// 如果出現了分隔符,則表明當前token結束了,// 于是將當前token加入當前token group,準備新的token,// 并解析分隔符的下一個字符currentTokenGroup.Add(currentToken.ToString());currentToken = new StringBuilder();return p2;}else{// 對于其他字符,則當作token中的普通字符處理// 繼續解析單引號外的token字符currentToken.Append(ch);return p4;} };// 用于解析單引號內的token字符 p5 = ch => {if (ch == '\''){// 對于被單引號包裹的token內的第一個單引號,// 需要解析其下一個字符,才能得到其真實含義return p3;}else{// 對于普通字符,則添加到當前token內currentToken.Append(ch);return p5;} };

    這些狀態中的邏輯都有一個特點,它們都會通過C#編譯器形成的閉包來操作“外部”狀態——不過這個“外部”是指這些匿名函數的外部,但是它們統統屬于Parse方法本身!這意味著,雖然我們的狀態并非“純函數”,但是Parse方法是沒有任何副作用(Side Effect,即除了返回值外不會影響其他外部狀態,以及相同的返回值永遠相同的結果)。這個特點確保了Parse方法可以被任意多個線程同時調用。winter-cn的做法巧妙地使用了C#編譯器的特性,簡化了Parse方法的實現。

    在定義完5種狀態之后,我們便要從p1開始依次處理字符串中的每個字符,并且隨著狀態的遷移改變處理每個字符的邏輯。當然,最后的“收尾”工作也是必不可少的:

    static List<List<string>> Parse(string text) {...text.Aggregate(p1, (sp, ch) => sp(ch));currentTokenGroup.Add(currentToken.ToString());result.Add(currentTokenGroup);return result; }

    可以看出,這種做法的優勢之一是完全的“順序處理”,只遍歷一次。如果您使用字符串的分割或者正則表達式進行解析的話,一般總是會有“回溯”,以及拆分出更多的字符串。因此,根據推測,這個做法從性能上來講應該也有一定優勢,不過還是需要真實的性能比較才能得出確切的結果。本文全部代碼已經存放在http://gist.github.com/214427中,您可以復制、執行,調試等等。

    這次的“趣味編程”是到目前為止最為熱鬧的一次,在上一篇文章的回復里您還可以發現許多朋友給出的大量解決方案,不過由于時間精力有限,我無法一一瀏覽了。此外,由于winter-cn已經給出了與我思路接近但實現更好的做法,后來我又用F#實現了另外一個思路不同的版本,您會發現F#有一些語言特性似乎非常適合進行字符串解析工作,它對于我們編寫C#代碼也有一定的借鑒意義。

    from:?http://blog.zhaojie.me/2009/10/code-for-fun-tokenizer-answer-1.html

    總結

    以上是生活随笔為你收集整理的趣味编程:从字符串中提取信息(参考答案 - 上)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 精品国产av色一区二区深夜久久 | 成人欧美视频在线观看 | 影音先锋男人天堂 | 日韩免费久久 | 99自拍视频在线观看 | 国产一区二区波多野结衣 | 午夜视频在线观看一区 | 久操视频免费看 | 国产又粗又猛又爽又黄的视频小说 | 天天操天天做 | 日本少妇做爰全过程毛片 | 奇米在线777| 黄色性视频网站 | 永久免费看黄 | 欧美成人国产 | 三级电影网址 | 91精品综合久久久久久 | 日本一级黄色大片 | 人妻互换免费中文字幕 | 91视频国产精品 | 午夜伊人网 | 1区2区3区视频 | 欧美日韩国产精品成人 | 黄色片在线视频 | mm131在线| 少妇真实被内射视频三四区 | 国产欧美一区二区三区在线看 | 精品麻豆一区二区 | 性色av蜜臀av色欲av | 免费看国产一级片 | 日本视频黄色 | 欧美一级xxx | av新天堂| 成人欧美一区二区三区小说 | 免费激情| 精品国产第一页 | 狠狠a| 影音先锋黄色资源 | 亚洲最色网站 | 国产精品成人电影在线观看 | www.天天干| 国产麻豆精品在线观看 | 日韩成人在线视频 | 亚洲影院在线 | 97伊人网 | 亚洲情趣 | 国产探花一区二区三区 | 亚洲狠狠丁香婷婷综合久久久 | 免费看污视频的网站 | 绯色av蜜臀vs少妇 | 国产成人自拍网 | 久久久久亚洲视频 | 老司机午夜福利视频 | 青春草在线视频免费观看 | 二区三区在线 | 少妇欧美激情一区二区三区 | 区一区二区三 | jizz国产| 非洲黄色大片 | 草色噜噜噜av在线观看香蕉 | 无码人妻精品一区二区三区9厂 | 午夜精品久久久久久久久久久久久蜜桃 | sm捆绑调教视频 | 女同性做受全过程动图 | 五月婷综合网 | 91在线观看免费高清完整版在线观看 | 色爱AV综合网国产精品 | 国产一区二区色 | 亚洲免费黄网 | 快色av| 久草久| av优选在线观看 | 天天干天天综合 | 亚洲成人tv | av猫咪| 黄色av导航| 蜜桃视频污 | 少妇一边呻吟一边说使劲视频 | 国产精品久久久久久久久久小说 | 影音资源av| 一起操在线 | xxxxxhd亚洲人hd | 亚洲h视频在线观看 | 禁漫天堂免费网站 | 日本一级淫片免费放 | 欧美一区二区人人喊爽 | 亚洲第一av| 亚洲欧美一区二区三区在线观看 | 美女福利视频导航 | 护士的小嫩嫩好紧好爽 | 精品国产系列 | 黄页网站在线播放 | 三级在线网址 | 性插插视频| 欧美一区二区三区在线视频 | 双性人bbww欧美双性 | 在线观看网站 | 国内福利视频 | 在线不卡一区二区 |