c++之可變參數格式化字符串(c++11可變模板參數)


 

  本文將使用 泛型 實現可變參數。 涉及到的關見函數:  std::snprintf

1、一個例子

 函數聲明及定義

 1 // 泛型
 2 template <typename... Args> 
 3 std::string show_str(const char *pformat, Args... args)
 4 {
 5     // 計算字符串長度
 6     int len_str = std::snprintf(nullptr, 0, pformat, args...);
 7 
 8     if (0 >= len_str)
 9         return std::string("");
10 
11     len_str++;
12     char *pstr_out    = nullptr;
13     pstr_out        = new(std::nothrow) char[len_str];
14     // 申請失敗
15     if (NULL        == pstr_out || nullptr == pstr_out)
16         return std::string("");
17 
18     // 構造字符串
19     std::snprintf(pstr_out, len_str, pformat, args...);
20 
21     // 保存構造結果
22     std::string str(pstr_out);
23 
24     // 釋放空間
25     delete pstr_out;
26     pstr_out = nullptr;
27 
28     return str;
29 }

2、一個調用例子

1 std::cout << "str = " << show_str("1-%s, 2-%.2f, 3-%d", "ABC", 12.3456, 100).c_str() << "\n";

 

3、輸出結果

  演示環境為: VS2015 up3

 

4、完整代碼

 1 #include <iostream>
 2 
 3 // 泛型
 4 template <typename... Args> 
 5 std::string show_str(const char *pformat, Args... args)
 6 {
 7     // 計算字符串長度
 8     int len_str = std::snprintf(nullptr, 0, pformat, args...);
 9 
10     if (0 >= len_str)
11         return std::string("");
12 
13     len_str++;
14     char *pstr_out    = nullptr;
15     pstr_out        = new(std::nothrow) char[len_str];
16     // 申請失敗
17     if (NULL        == pstr_out || nullptr == pstr_out)
18         return std::string("");
19 
20     // 構造字符串
21     std::snprintf(pstr_out, len_str, pformat, args...);
22 
23     // 保存構造結果
24     std::string str(pstr_out);
25 
26     // 釋放空間
27     delete pstr_out;
28     pstr_out = nullptr;
29 
30     return str;
31 }
32 
33 // 入口函數
34 int main(int argc, char *argv[])
35 {
36     std::cout << "str = " << show_str("1-%s, 2-%.2f, 3-%d", "ABC", 12.3456, 100).c_str() << "\n";
37 
38     system("pause");
39     return 0;
40 }

 

5、總結

  A、 new 和 delete 需要配對使用

  B、可自定義日志輸出格式 和 構造c++格式化字符串。 更加方便輸出日志.

 

6、擴展 (c++11)

  A、可變參數模板函數

  C++11的新特性--可變模版參數是C++11新增的特性之一,它對參數進行了高度泛化,能表示0到任意個數

  一個例子,其定義如下

1 // 可變參數模板函數
2 template <typename ... Args>
3 void vp_func(Args ... args)
4 {
5     // 計算參數個數
6     int count_param = sizeof...(args);
7     std::cout << "參數個數=" << count_param << std::endl;
8 }

  其中,計算參數個數的方式:

int count_param = sizeof...(args);

  B、調用

 1 // 入口函數
 2 int main(int argc, char *argv[])
 3 {
 4     vp_func(1);
 5     vp_func("-=+", 1.23456f);
 6     vp_func(1, 2.2f, "ABC");
 7 
 8     system("pause");
 9     return 0;
10 }

  C、輸出結果:

  演示環境: VS2015 up3

  D、解包(包展開)

  有兩種方式

    1)、遞歸

    2)、非遞歸

  遞歸,好用,但是要考慮爆棧的情況,不推薦。這里就不介紹了。 

  下面介紹非遞歸的方式展開

    2.1)、定義展開函數

1 // 參數包展開
2 template<typename T>
3 void expand(const T t)
4 {
5     std::cout << t << std::endl;
6 }

  再調用展開函數

 1 // 可變參數模板函數
 2 template <typename ... Args>
 3 void vp_func(Args ... args)
 4 {
 5     // 計算參數個數
 6     // int count_param = sizeof...(args);
 7     // std::cout << "參數個數=" << count_param << std::endl;
 8 
 9     std::initializer_list<int>{(expand(args), 0)...};
10     // std::initializer_list<int>{([&] {std::cout << args << std::endl; }(), 0)...};
11 }

    2.2)、使用lambda 展開

 1 // 可變參數模板函數
 2 template <typename ... Args>
 3 void vp_func(Args ... args)
 4 {
 5     // 計算參數個數
 6     // int count_param = sizeof...(args);
 7     // std::cout << "參數個數=" << count_param << std::endl;
 8 
 9     // std::initializer_list<int>{(expand(args), 0)...};
10     std::initializer_list<int>{([&] {std::cout << args << std::endl; }(), 0)...};
11 }

  非lambda  完整展開代碼:

 1 // 參數包展開
 2 template<typename T>
 3 void expand(const T t)
 4 {
 5     std::cout << t << std::endl;
 6 }
 7 
 8 
 9 // 可變參數模板函數
10 template <typename ... Args>
11 void vp_func(Args ... args)
12 {
13     // 計算參數個數
14     // int count_param = sizeof...(args);
15     // std::cout << "參數個數=" << count_param << std::endl;
16 
17     std::initializer_list<int>{(expand(args), 0)...};
18     // std::initializer_list<int>{([&] {std::cout << args << std::endl; }(), 0)...};
19 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM