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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

c#截取字符串后几位_基础库的字符串设计

發(fā)布時間:2025/3/19 C# 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c#截取字符串后几位_基础库的字符串设计 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

C++在字符串上表現(xiàn),一直以來很受人詬病,沒有一個庫的字符串類的表現(xiàn)能讓人滿意, std的string,mfc的CString,Qt的QString等等字符串類,都存在這樣那樣的問題,以至于字符串處理竟然成為C++的弱項,這也太不應(yīng)該了。

話說回來,C++對待字符串的態(tài)度也很奇葩,其他語言都將字符串當(dāng)做是內(nèi)建類,在編譯器層面來實現(xiàn),只有C++是通過庫的形式來提供字符串的抽象,也就是說,C++的語言層面上并沒有字符串類,而是提供制造字符串輪子的語言機制。這樣有兩個好處,一方面既然這些語言機制能實現(xiàn)字符串,說不定還能干點別的什么事情,授人以魚不如授人以漁;另一方面,更重要的是,字符串內(nèi)部的緩沖區(qū)涉及到動態(tài)內(nèi)存分配,一旦涉及到內(nèi)存資源管理,在C++下從來就不是簡單的事情,最明顯的一點,就是稍微處理方式不恰當(dāng),就勢必影響應(yīng)用層對字符串全方位的粒度控制,這就違背了C++的語言哲學(xué)了。

雖說字符串類的設(shè)計不容易,C++面世到現(xiàn)在,未曾出現(xiàn)過差強人意的相關(guān)庫即是明證。但也不至于困難到語言都面世幾十年了,還在字符串處理上灰頭土臉的地步。其實,只要牢牢把握以下幾點,還是有希望做出來好用的字符串庫的。

1、采用utf8編碼,這個就不解釋太多了,字符串不可能搞成支持多種字符編碼的模板類(不必要的麻煩太多),所以自然要選擇一種Unicode編碼,在空間性能、時間性能、跨平臺(大端小端)、api設(shè)計等這些因素,utf8的綜合表現(xiàn)最為杰出。要操作其他編碼的字符串時,都要求先臨時轉(zhuǎn)換為utf8編碼,操作完成后,再將結(jié)果轉(zhuǎn)回為原始編碼的字符串,效率上稍微存在損失,但是真的不打緊;

2、空間效率與時間效率上的最高要求,哪怕由此導(dǎo)致api使用上的丑陋,也在所不惜。只因字符串的應(yīng)用范圍太廣了,不能讓它成為影響性能的因素。std的string之所以存在那么多的成員函數(shù),還不是為了性能上的需要,其中大部分都只是函數(shù)重載,僅僅只是為了避免臨時string的誕生,標(biāo)準(zhǔn)庫string的這種應(yīng)對方式也太實誠了

3、使用上的方便性,不必遵從什么最小完整接口的戒條,只管往里面添加各種各樣的成員函數(shù),怎么方便就怎么來,當(dāng)然也不能無節(jié)制,QString就太過分了,啥都往里面塞。

有鑒于此,我們將string設(shè)計為兩個類,U8View和U8String,分別代表只讀字符串和字符緩沖區(qū)生命周期管理類,這類似于Java的String和StringBuilder,其實這也對應(yīng)著C++17的string_view和string,這個方案既簡單直觀又靈活高效,奇怪的是,C++社區(qū)竟然要到17才會有這樣的認(rèn)識,并且,就算這樣,std的字符串表現(xiàn)也還是垃圾。

U8View代表著一段連續(xù)字符的只讀內(nèi)存塊,單個的char也可以看成是長度為1的U8View,不要求字符緩沖以0結(jié)束,這一點很關(guān)鍵,標(biāo)準(zhǔn)庫的string就是在此放不開手腳,才導(dǎo)致那么蹩腳的設(shè)計。U8View很輕量級,它只有兩個字段,分別代表字符緩沖的起始地址以及長度,常量字符串,U8String,字符數(shù)組這些內(nèi)部有著連續(xù)字符緩沖的對象,全部都可以看成是U8View。U8View不得修改其緩沖區(qū)的任何內(nèi)容。

顯然,U8View有一個很好的特性,那就是U8View的任何一部分也都是U8View,因此,U8View提取子字符串的操作必然很輕量級,簡直不存在任何性能上的損失,一步到位就做好了,無須搞任何內(nèi)存分配的事情。所以,U8View自然就不必理會其緩沖區(qū)的生命周期,緩沖區(qū)的有效性由應(yīng)用層代碼來保證,U8View在其使用期間,都假設(shè)了字符緩沖的有效性。

bool IsValidUtf8Text(const char* str, size_t len);struct U8View {typedef const char* const_pointer;const_pointer mStr;size_t mLength;U8View(const_pointer str, size_t len) :mStr(str), mLength(len){assert(IsValidUtf8Text(str, len));}U8View(const_pointer start, const_pointer last);U8View(const_pointer str);template<size_t _Size> U8View(const char(&str)[_Size]);bool empty()const { return mLength == 0; }char operator[](size_t index)const;//... };

U8View里面有大量的成員函數(shù),大致可分為這6類,所有的成員函數(shù)幾乎為const屬性。

1、 構(gòu)造函數(shù),通過各種常量字符指針來初始化U8View,各個函數(shù)體內(nèi)部要assert字符串utf8的有效性。

2、 查找函數(shù),Find,RFind(查找字符,查找子字符串,正向查找,反向查找),FindOneOf查找字符串參數(shù)里面的任何一個unicode字符;

3、 比較函數(shù),CompareTo大小寫方式比較,CompareTo忽略大小寫比較,StartsWith, EndsWith,各種比較操作符的重載函數(shù),empty可空判斷

4、 截取子字符串,不管時間空間,都是O(1),零懲罰。這里又分為3類,a)直接通過字節(jié)數(shù)來截取,Sub,Left,Right,Trim,TrimLeft,TrimRight,關(guān)鍵的一點是返回時候,都要assert其utf8字符串的完整性;b)以Unicode的codepoint數(shù)目來截取子字符串,SubPoints,LeftPoints等;c)以Unicde的glyph數(shù)目來截取。

5、 迭代器,正常的begin、end函數(shù), Points返回一對訪問codepoint的迭代器,Glyphs返回迭代glyph的迭代器,正向迭代,反向迭代;返回各個位置上(比如字符串頭尾)的char值或者codepoint值

6、 生成U8String:Replace替換已有子字符串以生成新的U8String,U8View的加號操作符重載,Concat多個U8View等。

至于U8View轉(zhuǎn)換為各類數(shù)字類型的轉(zhuǎn)換函數(shù),就不在這里出現(xiàn)了,另有更好的安排。有了U8View之后,基本上所有同步函數(shù)的字符串參數(shù),都可以為U8View的類型。其實,很多字符串運算的場合下,只要U8View就完全足夠,效率(時間空間)以及易用性,均能達(dá)到最優(yōu)。U8View其實為值類型,C++在抽象值類型時,不管是性能還是api使用形式,每一項的表現(xiàn)都很杰出,其他任何猿語都很難再超過大C++了。

由于U8View已經(jīng)剝離出來很多常見的字符串操作,U8String的設(shè)計就很簡單了,只需老老實實本本分分管理字符緩沖的生命周期就好了,也就是實現(xiàn)析構(gòu)函數(shù),復(fù)制移動構(gòu)造函數(shù),賦值操作符重載,這沒什么好說的,只是要注意到U8String內(nèi)部的字符緩沖,必須以0結(jié)束。U8String的成員函數(shù)無非就是替換,追加,修改,交換等。其中很重要的一個成員函數(shù)View,用以返回U8View對象,之后就能以只讀形式操作U8String的字符緩沖。這里要強調(diào)的一點就是,除了移動構(gòu)造和移動賦值函數(shù),所有其他成員函數(shù)的字符串參數(shù)類型都是U8View類型,因此我們就無須為了效率,要對每一個操作都重載那么多成員函數(shù),何其簡潔。

不知道大家發(fā)現(xiàn)沒有,U8View和U8String這兩個類型互相依賴,你中有我,我中有你,相依為命。這種相互糾纏的設(shè)計方案,一般情況下避之唯恐不及,但是在字符串這里必須這樣搞,用起來才方便。但是,編譯器可不喜歡這種設(shè)計,這可怎么辦?只好讓U8View成為U8String的內(nèi)部類,并將其命名為TextView。然后再在外面將U8String的TextView typedef為U8View,代碼如下。

struct U8String {struct TextView {char* mStr; size_t mLength;//...};MemoryAllocator* mAlloc;size_t mCapacity;char* mStr; //故意保持跟TextView一樣的內(nèi)存布局size_t mLength;//... }; typedef U8String::TextView U8View;

字符串的故事就這樣結(jié)束了嗎?不,這才剛剛開始,U8String U8View必須配套格式化,字符串解析,字符串流的輸入輸出,正則表達(dá)式(運行時以及編譯時)等功能之后,才真正好用起來,然后就可以發(fā)現(xiàn),C++其實還是很擅長于處理字符串的。但是,在此之前,我們必須先解決幾個基礎(chǔ)問題,那就是反射、Trait(非侵入式的接口)、allocator、甚至stl各個容器的重新設(shè)計。

總結(jié)

以上是生活随笔為你收集整理的c#截取字符串后几位_基础库的字符串设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。