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