程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++字符串格式化庫:CPPFormatLibrary,c語言

C++字符串格式化庫:CPPFormatLibrary,c語言

編輯:C++入門知識

C++字符串格式化庫:CPPFormatLibrary,c語言


      這個是很久之前寫的,去年總結了一下,將其單獨提取出來,作為一個開源庫放到了GitHub上,然而CPPFormat之類的名字都已經被搶注了,結果只好注冊了一個這麼蛋疼的名字:CPPFormatLibrary,以下簡稱FL。

      首先介紹一下這是個什麼東西。我們知道,在C++當中要進行格式化字符串,通常采用的是C庫函數sprintf或者C++的stringstream,然而兩者都有自己的問題,比如C庫函數的類型安全問題,sprintf當參數不足,或者參數類型與格式化字符不符是都會發生錯誤,導致崩潰;而stringstream的效率又明顯不行。除此之外,我麼還知道boost庫有format可以用,然而它效率不高。另外還有國外的大神寫過fastformat庫,地址:http://fastformat.sourceforge.net/ 。它的問題在於過於龐大,集成不方便,會引入太多你並不需要的東西;同時,它也並未將性能發揮到極限。我寫這個FL庫最初的靈感也來自於fastformat,也特別感謝它。

      FL與fastformat一樣,都致力於解決前面所描述的C++字符串格式化的各種問題,最終采用的方案是.net方案,關於.net的格式化字符串,可以看這篇文章:http://www.cnblogs.com/zyh-nhy/archive/2007/10/11/921240.html  與fastformat想比,FL移除了一些並沒有什麼用的功能,並進行了功能增強,比如fastformat並不支持{0,5}這樣的更細的描述,而FL支持。當然fastformat與FL都沒有完全覆蓋.net的format,也就是說並不完全等同於.net的格式化,部分功能並未得到支持。

      下面是FL中的測試代碼,這個代碼展示了最基本的格式化功能:

 1 // Test
 2 #include "Format.hpp"
 3 
 4 #include "Format/ProgressTimer.hpp"
 5 
 6 #define TEST_PERFORMANCE_IN_TOOLS 0
 7 
 8 using namespace FormatLibrary;
 9 
10 #include <iostream>
11 #include <vector>
12 using namespace std;
13 
14 void TestProfile()
15 {
16     const int TEST_COUNT = 100000;
17 
18     {
19         Profile::ProgressTimer Timer("FL");
20 
21         for (int i = 0; i < TEST_COUNT; ++i)
22         {
23             string str;
24             StandardLibrary::FormatTo(str, "{0}--#--{1,8}--#--{2}", 100, -40.2f, " String ");
25             StandardLibrary::FormatTo(str, "{0}--#--{1,8}--#--{1}", 100, -40.2f);
26             StandardLibrary::FormatTo(str, "{0}--#--{1,8}--#--{3}", 100, -40.2f, std::string("xxx"));
27         }
28     }
29 
30 #if !FL_COMPILER_MSVC
31 #define sprintf_s sprintf
32 #endif
33 
34 #if !TEST_PERFORMANCE_IN_TOOLS
35     {
36         Profile::ProgressTimer Timer("CL");
37 
38         for (int i = 0; i < TEST_COUNT; ++i)
39         {
40             string str;
41             char szBuf[64];
42             sprintf_s(szBuf, "%d--#--%8.2f--#--%s", 100, -40.2f, " String ");
43             str = szBuf;
44             sprintf_s(szBuf, "%d--#--%8.2f--#--%f", 100, -40.2f, 0.0f);
45             str = szBuf;
46             sprintf_s(szBuf, "%d--#--%8.2f--#--%%f", 100, -40.2f);
47             str = szBuf;
48         }
49     }
50 #endif
51 }
52 
53 #if FL_PLATFORM_HAS_CPP11 && (FL_COMPILER_MSVC||FL_PLATFORM_MACOS)
54 #include <thread>
55 
56 void TestProfileMultiThread()
57 {
58     std::thread t0( TestProfile );
59     std::thread t1( TestProfile );
60     std::thread t2( TestProfile );
61 
62     t0.join();
63     t1.join();
64     t2.join();
65 }
66 #endif
67 
68 int main()
69 {
70     StandardLibrary::STLGlobalPatternStorageA Storage;
71     Utility::TAutoString<char> TestStr;
72 
73     const char* pszTest = "{0},xxxd{1:d2}={2,3:d2} !! {{}} {0,-5:d8}";
74     Storage.LookupPatterns(pszTest, strlen(pszTest));
75 
76     std::string str;
77     StandardLibrary::FormatTo(str, "test{0}", 10);
78 
79     StandardLibrary::FormatTo(str, "{0}", char('c'), short(2));
80 
81 #if FL_COMPILER_MSVC
82     StandardLibrary::FormatTo(str, "0x{0:x}", 100, DWORD(100));
83 #endif
84 
85     std::wstring wstr;
86     StandardLibrary::FormatTo(wstr, L"Test{1}, {2:f4}, {0}, {0,4}", L" X ", 20, -10.005f);
87 
88     cout << str << endl;
89     wcout << wstr << endl;
90 
91     TestProfile();
92     
93 #if FL_PLATFORM_HAS_CPP11 && (FL_COMPILER_MSVC||FL_PLATFORM_MACOS)
94     TestProfileMultiThread();
95 #endif
96 
97     return 0;
98 }

Windows Visual Studio 2013 Release下的輸出:

0x64
Test20, -10.0050,  X ,  X
0x64
Test20, -10.0050,  X ,  X
1920 FLElapse:0.0762746
1920 CLElapse:0.269722
1636 FLElapse:0.0756153
7732 FLElapse:0.0766446
7956 FLElapse:0.0762051
7956 CLElapse:0.285714
1636 CLElapse:0.288648
7732 CLElapse:0.289193

Mac Xcode Release:

99
Test20, -10.0050,  X ,  X 
18446744073709551615 FLElapse:0.0901681
18446744073709551615 CLElapse:0.19329
18446744073709551615 FLElapse:0.147378
18446744073709551615 FLElapse:0.150375
18446744073709551615 FLElapse:0.153342
18446744073709551615 CLElapse:0.303508
18446744073709551615 CLElapse:0.308418
18446744073709551615 CLElapse:0.307407

     這只是一個簡單的測試,結果並不能覆蓋所有情況,然而可以明確的是,FL在提供了:編譯期類型安全檢查,不定參數,多線程支持,可重入,可亂序等功能的前提下,並不會比C庫函數sprintf慢。因此可以認為在使用C++的情況下,始終應該使用FL代替傳統的各種格式化字符串的方式以獲取更好更安全的代碼。

     FL被設計成Header Only的庫,這樣用起來就更方便了,只需要簡單的包含Format.hpp頭文件即可獲取到所有的功能。同時針對C++ 11做了專門的優化,使得在支持C++ 11的編譯器上可以取得更快的運行速度,這是其它庫無法比擬的。

     如果你使用的是STL的字符串string或者wstring,那麼FL已經內置了對應的支持,所有的適配器都已經默認提供。假如你不是使用的STL,比如UnrealEngine中使用的FString,那麼你也可以非常容易的集成FL到自己的項目中。UnrealEngine的FString在集成了FL之後,會多出一個靜態的FormatTo函數和一個Format成員函數,它們可以用於使用.net風格產生一個字符串或者直接格式化自己。在項目中也可以找到UnrealEngine的集成代碼,非常簡單。

     FL已經成功使用Visual Studio,XCode和Codeblocks with gcc進行編譯,並支持windows,macos,linux,ios等平台。已經成功用於多個項目。

     項目地址:https://github.com/sczybt/CPPFormatLibrary

     使用git Clone地址:https://github.com/sczybt/CPPFormatLibrary.git

     你也可以直接Download zip

     另外,一個代碼庫不可能沒有bug,如果你發現了問題,可以將測試用例發給我,我會修復之。歡迎大家來使用。

     接下來我會針對這個庫提供更多的說明和指導文檔。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved