溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

C++如何實(shí)現(xiàn)高性能轉(zhuǎn)換大小寫(xiě)算法

發(fā)布時(shí)間:2021-04-14 11:17:17 來(lái)源:億速云 閱讀:362 作者:小新 欄目:編程語(yǔ)言

這篇文章給大家分享的是有關(guān)C++如何實(shí)現(xiàn)高性能轉(zhuǎn)換大小寫(xiě)算法的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

簡(jiǎn)述

最近工作中遇到一個(gè)需求,是需要將URL中的 query 參數(shù)的key全部轉(zhuǎn)換為小寫(xiě)或者大寫(xiě),鍵值對(duì)的數(shù)量有點(diǎn)多,但全部都是英文字母,無(wú)需考慮非字母的情況。

實(shí)現(xiàn)比較快的做法是使用STL或C標(biāo)準(zhǔn)庫(kù)中的轉(zhuǎn)換接口,如下:

#include <string> 
#include <cctype> 
#include <algorithm>
// 字符串中的大寫(xiě)字符轉(zhuǎn)小寫(xiě)
std::string strtolower(std::string s)
{
 transform(s.begin(), s.end(), s.begin(), ::tolower);
 return s;
}
// 字符串中的小寫(xiě)字符轉(zhuǎn)大寫(xiě)
std::string strtoupper(std::string s)
{
 transform(s.begin(), s.end(), s.begin(), ::toupper);
 return s;
}

這個(gè)方法雖然很好,但是效率不是很高。

分析了一下ascii碼的碼值,發(fā)現(xiàn)大小寫(xiě)字母的ascii碼之間是有規(guī)律的。

原理

英文字母的ASCII碼值表示如下

C++如何實(shí)現(xiàn)高性能轉(zhuǎn)換大小寫(xiě)算法

對(duì)比一下其二進(jìn)制形式

C++如何實(shí)現(xiàn)高性能轉(zhuǎn)換大小寫(xiě)算法

從對(duì)比的結(jié)果可以看出, 大寫(xiě)字母與小寫(xiě)字母的差別 僅是 一個(gè)比特位的不同 。

因?yàn)樗鼈兊倪@個(gè)規(guī)律,可以寫(xiě)出下面的轉(zhuǎn)換函數(shù)(如果輸入不是字母,轉(zhuǎn)出的結(jié)果會(huì)有錯(cuò)誤)

可以查看數(shù)字 0-9 的ascii碼值,可以看出它們的第6位都是0,所以轉(zhuǎn)為小寫(xiě)的算法不會(huì)影響數(shù)字的值。

轉(zhuǎn)小寫(xiě)算法中受到影響的,只有ascii碼二進(jìn)制表示中第六位為0的部分。其中非字母部分如下表

C++如何實(shí)現(xiàn)高性能轉(zhuǎn)換大小寫(xiě)算法

#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),用來(lái)聲明函數(shù)對(duì)象。

STL中算法大致分為四類(lèi):

       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

自寫(xiě)代碼測(cè)試結(jié)果如下

time ./test
./test 0.93s user 0.00s system 99% cpu 0.928 total

可以看到,其性能有差異。(應(yīng)用場(chǎng)景有限)

感謝各位的閱讀!關(guān)于“C++如何實(shí)現(xiàn)高性能轉(zhuǎn)換大小寫(xiě)算法”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI