C++實(shí)現(xiàn)高性能轉(zhuǎn)換大小寫算法示例
簡(jiǎn)述
最近工作中遇到一個(gè)需求,是需要將URL中的 query 參數(shù)的key全部轉(zhuǎn)換為小寫或者大寫,鍵值對(duì)的數(shù)量有點(diǎn)多,但全部都是英文字母,無(wú)需考慮非字母的情況。
實(shí)現(xiàn)比較快的做法是使用STL或C標(biāo)準(zhǔn)庫(kù)中的轉(zhuǎn)換接口,如下:
#include <string> #include <cctype> #include <algorithm> // 字符串中的大寫字符轉(zhuǎn)小寫 std::string strtolower(std::string s) { transform(s.begin(), s.end(), s.begin(), ::tolower); return s; } // 字符串中的小寫字符轉(zhuǎn)大寫 std::string strtoupper(std::string s) { transform(s.begin(), s.end(), s.begin(), ::toupper); return s; }
這個(gè)方法雖然很好,但是效率不是很高。
分析了一下ascii碼的碼值,發(fā)現(xiàn)大小寫字母的ascii碼之間是有規(guī)律的。
原理
英文字母的ASCII碼值表示如下
對(duì)比一下其二進(jìn)制形式
從對(duì)比的結(jié)果可以看出, 大寫字母與小寫字母的差別 僅是 一個(gè)比特位的不同 。
因?yàn)樗鼈兊倪@個(gè)規(guī)律,可以寫出下面的轉(zhuǎn)換函數(shù)(如果輸入不是字母,轉(zhuǎn)出的結(jié)果會(huì)有錯(cuò)誤)
可以查看數(shù)字 0-9 的ascii碼值,可以看出它們的第6位都是0,所以轉(zhuǎn)為小寫的算法不會(huì)影響數(shù)字的值。
轉(zhuǎn)小寫算法中受到影響的,只有ascii碼二進(jìn)制表示中第六位為0的部分。其中非字母部分如下表
#include <iostream> #include <string> #include <stdint.h> // 更優(yōu)化 std::string strtoupper(std::string s) { if(s.empty()){return s;} size_t len = s.size() + 1; size_t alignlen = len + 8 - (len % 8); s.resize(alignlen); size_t ec = alignlen / 8; uint64_t* p8 = (uint64_t*)s.data(); for(size_t i=0;i<ec;++i){ p8[i] &= 0xDFDFDFDFDFDFDFDF; } s.resize(len-1); return s; } // 未做進(jìn)一步優(yōu)化 std::string strtolower(std::string s) { size_t len = s.size(); size_t ec = len /8; uint64_t* p8 = (uint64_t*)s.data(); for(size_t i=0;i<ec;++i){ p8[i] |= 0x2020202020202020; } uint8_t* p1 = (uint8_t*)(p8 + ec); len %= 8; for(size_t i=0;i<len;++i){ p1[i] |= 0x20; } return s; }
性能測(cè)試
測(cè)試代碼如下:
int main() { //std::cout << "Hello, world!\n"; for(size_t i=0;i<1000000;++i){ std::string s = strtoupper("qwertyuiopasdfghjklzxcvbnm````````QWERTYUIOPASDFGHJKLZXCVBNM"); //std::cout<<s<<std::endl; s = strtolower("qwertyuiopasdfghjklzxcvbnm\t\t\t\t\t\t\t\tQWERTYUIOPASDFGHJKLZXCVBNM"); //std::cout<<s<<std::endl; } return 0; }
-- 編譯時(shí)候請(qǐng)勿優(yōu)化,否則可能被優(yōu)化掉! --
測(cè)試結(jié)果如下:
使用STL算法
STL算法部分主要由頭文件<algorithm>,<numeric>,<functional>組成。要使用 STL中的算法函數(shù)必須包含頭文件<algorithm>,對(duì)于數(shù)值算法須包含<numeric>,<functional>中則定義了一些模板類,用來(lái)聲明函數(shù)對(duì)象。
STL中算法大致分為四類:
1、非可變序列算法:指不直接修改其所操作的容器內(nèi)容的算法。
2、可變序列算法:指可以修改它們所操作的容器內(nèi)容的算法。
3、排序算法:包括對(duì)序列進(jìn)行排序和合并的算法、搜索算法以及有序序列上的集合操作。
4、數(shù)值算法:對(duì)容器內(nèi)容進(jìn)行數(shù)值計(jì)算。
結(jié)果如下
time ./teststl ./teststl 7.88s user 0.03s system 100% cpu 7.904 total
自寫代碼測(cè)試結(jié)果如下
time ./test ./test 0.93s user 0.00s system 99% cpu 0.928 total
可以看到,其性能有差異。(應(yīng)用場(chǎng)景有限)
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
C++實(shí)現(xiàn)并優(yōu)化異常系統(tǒng)
異常處理是C++的一項(xiàng)語(yǔ)言機(jī)制,用于在程序中處理異常事件,下面這篇文章主要給大家介紹了關(guān)于C++中異常的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08C++實(shí)現(xiàn)學(xué)生選課系統(tǒng)的思路與詳細(xì)過(guò)程
C語(yǔ)言是在國(guó)內(nèi)外廣泛使用的一種計(jì)算機(jī)語(yǔ)言,下面這篇文章主要給大家介紹了關(guān)于C++實(shí)現(xiàn)學(xué)生選課系統(tǒng)的思路與詳細(xì)過(guò)程,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01復(fù)數(shù)乘法中的結(jié)構(gòu)體賦值實(shí)現(xiàn)代碼
復(fù)數(shù)乘法中的結(jié)構(gòu)體賦值實(shí)現(xiàn)代碼。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-10-10用C語(yǔ)言實(shí)現(xiàn)鏈?zhǔn)綏=榻B
大家好,本篇文章主要講的是用C語(yǔ)言實(shí)現(xiàn)鏈?zhǔn)綏=榻B,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12C語(yǔ)言之把數(shù)組名作函數(shù)參數(shù)的四種情況說(shuō)明
這篇文章主要介紹了C語(yǔ)言之把數(shù)組名作函數(shù)參數(shù)的四種情況說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07C++詳細(xì)講解繼承與虛繼承實(shí)現(xiàn)
這篇文章主要介紹了Java中的繼承詳情,繼承是面向?qū)ο笕筇卣髦?,可以使得子類具有父類的屬性和方法,還可以在子類中重新定義,以及追加屬性和方法,下文介紹需要的朋友可以參考下2022-04-04FFRPC應(yīng)用 Client/Server使用及原理解析
這篇文章主要介紹了FFRPC應(yīng)用 Client/Server使用及原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08