關(guān)于c++11與c風(fēng)格路徑拼接的速度對(duì)比
c++11的std庫(kù)中沒有提供路徑拼接的功能
比如我需要將 "d:\\temp\\robin" 和 "..\\config.ini" 路徑拼接,
這里用c++11的stingstream實(shí)現(xiàn)一個(gè)
string& replace_str(string& str, const string& to_replaced, const string& newchars) { ?? ?for (string::size_type pos(0); pos != string::npos; pos += newchars.length()) ?? ?{ ?? ??? ?pos = str.find(to_replaced, pos); ?? ??? ?if (pos != string::npos) ?? ??? ??? ?str.replace(pos, to_replaced.length(), newchars); ?? ??? ?else ?? ??? ??? ?break; ?? ?} ?? ?return ? str; } ? // windows std::string combinePath(const char *dir, const char* name) {?? ? ?? ?//printf("%s ?+ ?%s\n", dir, name); ?? ?if (dir == nullptr || name == nullptr) ?? ??? ?return ""; ?? ?string temp = dir; ?? ?replace_str(temp, "/", "\\"); ?? ?std::stringstream oss(temp); ?? ?std::deque<std::string> vecDir; ?? ?std::deque<std::string> vecName; ? ?? ?string part; ?? ?while (std::getline(oss, part, '\\')) ?? ?{ ?? ??? ?if (part.length() == 0) ?? ??? ??? ?continue; ?? ??? ?vecDir.emplace_back(part); ?? ?}? ? ?? ?temp = name; ?? ?replace_str(temp, "/", "\\"); ?? ?oss.clear(); ?? ?oss.str(temp); ?? ?while (std::getline(oss, part, '\\')) ?? ?{ ?? ??? ?if (part.length() == 0) ?? ??? ??? ?continue; ?? ??? ?vecName.emplace_back(part); ?? ?} ? ?? ?int index = 0; ?? ?while (index < vecName.size()) ?? ?{ ?? ??? ?if (vecName[0] == ".") ?? ??? ?{ ?? ??? ??? ?vecName.pop_front(); ?? ??? ?} ?? ??? ?//else if (vecName[0].find("..") != vecName[0].npos) ?? ??? ?else if (vecName[0] == "..") ?? ??? ?{ ?? ??? ??? ?vecName.pop_front(); ?? ??? ??? ?if (vecDir.size() > 1) ?? ??? ??? ??? ?vecDir.pop_back(); ?? ??? ?} ?? ??? ?else ?? ??? ?{ ?? ??? ??? ?vecDir.emplace_back(vecName[0]); ?? ??? ??? ?vecName.pop_front(); ?? ??? ?} ?? ?} ? ?? ?oss.clear(); ?? ?oss.str(""); ?? ?for (int i=0; i<vecDir.size(); i++) ?? ?{ ?? ??? ?oss << vecDir[i]; ?? ??? ?if (vecDir.size() == 1 || i < (vecDir.size() - 1)) ?? ??? ?{ ?? ??? ??? ?oss << "\\"; ?? ??? ?} ?? ?}? ?? ?return oss.str(); }
測(cè)試方法:
void test1() { ?? ?cout << combinePath("d:\\temp\\robin\\", "..\\demo\\config.ini") << endl; ?? ?cout << endl; ? ?? ?cout << combinePath("d:", "..\\demo\\config.ini") << endl; ?? ?cout << endl; ? ?? ?cout << combinePath("d:\\temp\\robin", "../demo/config.ini") << endl; ?? ?cout << endl; ? ?? ?cout << combinePath("d:\\temp\\robin", "./config.ini") << endl; ?? ?cout << endl; ? ?? ?cout << combinePath("d:\\temp\\robin", "config.ini") << endl; ?? ?cout << endl; ? ?? ?cout << combinePath("d:\\temp\\robin\\", "\\config.ini") << endl; ?? ?cout << endl; }
測(cè)試發(fā)現(xiàn),release使用O2優(yōu)化,能平均在2~4微秒左右,還是不夠快啊,
用c重新實(shí)現(xiàn)一遍
// 字符串范圍內(nèi),逆向查找 const char * ?strrfind(const char *begin, const char *end, const char c) { ?? ?const char * buf = end; ?? ?while (buf >= begin) ?? ?{ ?? ??? ?if (*buf == c) ?? ??? ??? ?return buf; ?? ??? ?buf--; ?? ?} ?? ?return nullptr; } size_t ?combinePathC(char ** buffer, const char * dir, const char *name) { ?? ?int n1 = strlen(dir); ?? ?int n2 = strlen(name); ?? ?size_t len = ?n1 + n2 + 2; ?? ?char *buf = new char[len]; ?? ?*buffer = buf; ? ?? ?memcpy(buf, dir, n1); ?? ?size_t len1 = n1; ? ?? ?// 末尾保證有一個(gè)"\" ?? ?if (buf[n1-1] == '\\') ?? ?{ ?? ??? ?len1 = n1; ?? ?} ?? ?else ?? ?{ ?? ??? ?buf[n1] = '\\'; ?? ??? ?len1 = n1+1;?? ??? ? ?? ?} ?? ?buf[len1] = '\0'; ? ?? ?// len1++示當(dāng)前拼接的長(zhǎng)度 ?? ?size_t index = 0; ?? ?char * rPart = (char *)name; ?? ?size_t len2 = n2; ?? ?while (index < n2) ? // 使用index向后滑動(dòng),直到末尾 ?? ?{ ?? ??? ?// 滑動(dòng)后當(dāng)前位置 ?? ??? ?rPart = (char *)name + index; ?? ??? ?char * tmp = (char *)strchr(rPart, '\\'); ?? ??? ?if (tmp == nullptr) ? // end here ?? ??? ?{ ?? ??? ??? ?// 拼接剩下的 ?? ??? ??? ?len2 = n2 - index; ?? ??? ??? ?memcpy(buf + len1, rPart, len2); ?? ??? ??? ?len1 += len2; ?? ??? ??? ?buf[len1] = '\0'; ?? ??? ??? ?len1++; ? ?? ??? ??? ?break; ?? ??? ?} ? ?? ??? ?// 當(dāng)前找到的長(zhǎng)度 ?? ??? ?len2 = tmp - rPart; ?? ??? ?if (len2 == 0) ? ? // 遇到 "\config.ini",去掉1個(gè)字符 ?? ??? ?{ ?? ??? ??? ?index += 1; ?? ??? ?} ?? ??? ?else if (len2 == 1 && rPart[0] == '.') ? // 遇到 ".\config.ini",去掉2個(gè)字符 ?? ??? ?{ ?? ??? ??? ?index += 2; ?? ??? ?} ?? ??? ?else if (len2 >= 2 && rPart[0] == '.') ?// 遇到 "..\config.ini", "..x\config.ini"去掉3個(gè)字符,末尾去掉一個(gè)目錄 ?? ??? ?{ ?? ??? ??? ?index += len2 + 1; ?? ??? ??? ?const char * back = strrfind(buf, buf + len1 - 2 , '\\'); ? // 從末尾的"\"前一個(gè)字符開始找 ?? ??? ??? ?if (back == nullptr) ?? ??? ??? ?{ ?? ??? ??? ??? ?// dir 當(dāng)前是這樣的情況,"d:\” ?? ??? ??? ?} ?? ??? ??? ?else if ((back - dir) == 2) ?// dir 當(dāng)前是這樣的情況,"d:\temp\” ?? ??? ??? ?{ ?? ??? ??? ??? ?len1 = 3; ?? ??? ??? ??? ?buf[3] = '\0'; ?? ??? ??? ?} ?? ??? ??? ?else ? ? ? ? ? ? ? ? ? ? ? ?// dir 當(dāng)前是這樣的情況,"d:\temp\test1\” ?? ??? ??? ?{ ?? ??? ??? ??? ?len1 = back - buf + 1; ?? ??? ??? ??? ?buf[len1] = '\0'; ?? ??? ??? ?} ?? ??? ?} ?? ??? ?else ? ?// ?遇到首字符不為點(diǎn) "x\config.ini", ? ?? ??? ?{ ?? ??? ??? ?index += len2 + 1; ?? ??? ??? ?memcpy(buf + len1, name + index, len2 + 1); ?? ??? ??? ?len1 += len2 + 1; ?? ??? ?} ?? ?}? ?? ?return len1; }
測(cè)試一下:
? ? char * buf = nullptr; ?? ?size_t len;? ?? ? ?? ?len = combinePathC(&buf, "d:\\temp\\robin\\", "config.ini"); ?? ?cout << buf << endl; ? ?? ?len = combinePathC(&buf, "d:\\temp\\robin", "config.ini"); ?? ?cout << buf << endl;*/ ? ?? ?len = combinePathC(&buf, "d:\\temp\\robin", ".\\config.ini"); ?? ?cout << buf << endl; ? ?? ?len = combinePathC(&buf, "d:\\temp\\robin", "..\\config.ini"); ?? ?cout << buf << endl; ? ?? ?len = combinePathC(&buf, "d:\\temp\\robin", "...\\config.ini"); ?? ?cout << buf << endl;
測(cè)試發(fā)現(xiàn),平均在0.2微秒左右;
打完收功! 以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
QT基于TCP實(shí)現(xiàn)文件傳輸系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了QT基于TCP實(shí)現(xiàn)文件傳輸系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08利用C++?OpenCV?實(shí)現(xiàn)從投影圖像恢復(fù)仿射特性
我們通過相機(jī)拍攝的圖片存在各種畸變,其中投影畸變使得原本平行的直線不再平行,就會(huì)產(chǎn)生照片中近大遠(yuǎn)小的效果。本文將具體介紹如何利用OPenCV實(shí)現(xiàn)從投影圖像恢復(fù)仿射特性,接下來跟著小編一起學(xué)習(xí)吧2021-11-11從匯編看c++中函數(shù)里面的static關(guān)鍵字的使用說明
c++中的static關(guān)鍵字使得函數(shù)里面的局部變量的存活期不在局限于函數(shù)里面,而是變?yōu)樵谡麄€(gè)程序生命期里面都有效2013-05-05C++實(shí)現(xiàn)ETW進(jìn)行進(jìn)程變動(dòng)監(jiān)控詳解
ETW提供了一種對(duì)用戶層應(yīng)用程序和內(nèi)核層驅(qū)動(dòng)創(chuàng)建的事件對(duì)象的跟蹤記錄機(jī)制。為開發(fā)者提供了一套快速、可靠、通用的一系列事件跟蹤特性。本文將利用ETW進(jìn)行進(jìn)程變動(dòng)監(jiān)控,需要的可以參考一下2022-07-07C++中4種管理數(shù)據(jù)內(nèi)存的方式總結(jié)
根據(jù)用于分配內(nèi)存的方法,C++中有3中管理數(shù)據(jù)內(nèi)存的方式:自動(dòng)存儲(chǔ)、靜態(tài)存儲(chǔ)和動(dòng)態(tài)存儲(chǔ)。在存在時(shí)間的長(zhǎng)短方面,以這三種方式分配的數(shù)據(jù)對(duì)象各不相同。下面簡(jiǎn)要介紹這三種類型2022-09-09C語(yǔ)言之函數(shù)返回值與參數(shù)傳遞案例教程
這篇文章主要介紹了C語(yǔ)言之函數(shù)返回值與參數(shù)傳遞案例教程,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語(yǔ)言數(shù)組越界引發(fā)的死循環(huán)問題解決
本文主要介紹了C語(yǔ)言數(shù)組越界引發(fā)的死循環(huán)問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08C++應(yīng)用Eigen庫(kù)對(duì)應(yīng)實(shí)現(xiàn)matlab中部分函數(shù)問題
這篇文章主要介紹了C++應(yīng)用Eigen庫(kù)對(duì)應(yīng)實(shí)現(xiàn)matlab中部分函數(shù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12