当前位置:   article > 正文

C++工具:C++日志模板--提供调试日志和文件日志_c++ 日志模块

c++ 日志模块
  1. //!
  2. //! C++工具:C++日志模板--提供调试日志和文件日志
  3. //!
  4. //! == 日志模板简介 ==
  5. //! 日志打印是C++程序调试的关键一环,可惜C++并没有提供标准库日志,
  6. //! 本文将提供一个简单轻便的调试日志,使用方式更接近C++风格
  7. //! 日志模板包含控制台调试日志,写入文件日志两种常见日志,
  8. //! 通常调试日志不会跟随程序发行,发行时采用文件日志
  9. //! 该日志在Linux环境下适用,但基本采用C++标准,
  10. //! 如需要在Windows下使用需微调代码
  11. //! == 日志模板简介 ==
  12. //!
  13. //!
  14. //! == 调试日志 ==
  15. //! 调试日志:提供日志开关宏,控制整体日志的打印输出
  16. //! 提供日志级别,可屏蔽低级日志
  17. //! 提供日志级别模板,可自定义日志级别
  18. //! 提供颜色打印开关,控制不同级别高亮打印
  19. //! 提供标准容器打印模板,快速打印容器内容
  20. //!
  21. //! 文件日志:提供日志级别,可屏蔽低级日志
  22. //! 提供日志级别模板,可自定义日志级别
  23. //! 提供文件限制最大长度,文件数量循环复写模式
  24. //! 提供无限文件数量追加写入模式
  25. //! == 调试日志 ==
  26. //!
  27. //! 结束语:
  28. //! 从性能测试结果来看,调试日志的颜色打印与常规打印性能无差距,
  29. //! 调试日志的时间消耗是cout/paintf打印时间的一倍,
  30. //! 时间消耗主要由重载符<<产生,为便捷性牺牲速度
  31. //! 文件日志写入文件的性能比cout/paintf打印到屏幕更快,
  32. //! 文件日志不错的性能与便捷性,可以在简单项目中快速使用
  33. //!
  34. #define VLOG_COLOR //需要在Tvlog.h文件之前使用
  35. //#define VLOG_CLOSE //需要在Tvlog.h文件之前使用
  36. #include "../include/Tvlog.h"
  37. #include <vector>
  38. #include <list>
  39. #include <chrono>
  40. #include <iostream>
  41. using std::string;
  42. using std::vector;
  43. using std::list;
  44. using std::to_string;
  45. using namespace std::chrono;
  46. //!
  47. //! 说明:主要用于计算函数运行的时间,测试函数性能
  48. //! steady_clock时间:精确到纳秒的均速时间
  49. //!
  50. //! 例子:
  51. //! {
  52. //! ctimel tm;
  53. //! func();
  54. //! }//到这里析构退出并打印时间
  55. //!
  56. //! 原理:构建对象时开始计时,析构时打印时间
  57. //!
  58. class ctimel
  59. {
  60. public:
  61. ctimel() { _begin = steady_clock::now(); }
  62. ~ctimel() { show(); }
  63. inline string to_str()
  64. {
  65. //顺序 [纳秒|微秒|毫秒|秒]
  66. auto loss = steady_clock::now() - _begin;
  67. string str =
  68. "[nan: " + std::to_string(loss.count()) +
  69. "|mic: " + std::to_string(duration_cast<microseconds>(loss).count()) +
  70. "|mil: " + std::to_string(duration_cast<milliseconds>(loss).count()) +
  71. "|sec: " + std::to_string(duration_cast<seconds>(loss).count()) +
  72. "]\n";
  73. return str;
  74. }
  75. inline void show_str(const string str) { std::cout<<str<<std::endl; }
  76. inline void show() { show_str(to_str()); }
  77. inline void update() { _begin = steady_clock::now(); }
  78. protected:
  79. time_point<steady_clock,nanoseconds> _begin;
  80. };
  81. void test_1()
  82. {
  83. Tvlogs::get()->set_level(vlevel4::e_info); //设置最低显示日志级别
  84. //普通打印
  85. vloge("== 普通打印 ==");
  86. vlogi("e_info level");
  87. vlogd("this template log");
  88. vlogd("10+20 ret: " << 10+20);
  89. vlogw("PI: "<<3.14);
  90. vloge("2^4 calculate: "<<2*2<<" * "<<2*2<<" = "<<4*4);
  91. vloge("2^4 calculate:" $(2*2) $(2*2) "=" $(4*4));
  92. //快速打印结果
  93. vloge("== 快速打印 ==");
  94. int count = 0;
  95. for(int i=0;i<=100;i++) count += i;
  96. string str = "hello world";
  97. int ret = 10*60;
  98. vlogd($(str) $(ret) $(count));
  99. //容器快速打印
  100. vector<string> vec;
  101. list<string> ls;
  102. for(int i=0;i<10;i++)
  103. {
  104. vec.push_back("vec:"+to_string(i));
  105. ls.push_back("ls:"+to_string(i));
  106. }
  107. vloge("== 容器打印--模板 ==");
  108. {
  109. vector<int> vec;
  110. for(int i=0;i<25;i++)
  111. {
  112. vec.push_back(i);
  113. }
  114. vlogc(vec);
  115. vlogc(vec,5);
  116. vlogc(vec,5,"][");
  117. vlogc(vec.begin(),vec.end(),5);
  118. vlogc(vec.begin(),vec.end(),5,".");
  119. }
  120. int ifor = 3;
  121. #if 1
  122. {
  123. ctimel c;
  124. for(int i=0;i<ifor;i++)
  125. {
  126. vlogd($(i) "hellow world");
  127. }
  128. string s1 = c.to_str();
  129. int value=100;
  130. string s = "hellow world";
  131. for(int i=0;i<ifor;i++)
  132. {
  133. vlogd($(i) $(value) $(s));
  134. }
  135. string s2 = c.to_str();
  136. }
  137. #endif
  138. #if 1
  139. {
  140. ctimel c;
  141. for(int i=0;i<ifor;i++)
  142. {
  143. std::cout<<i<<": hellow world"<<std::endl;
  144. }
  145. string s1 = c.to_str();
  146. int value=100;
  147. string s = "hellow world";
  148. for(int i=0;i<ifor;i++)
  149. {
  150. std::cout<<i<<": value:"<<value<<" | s:"<<s<<std::endl;
  151. }
  152. string s2 = c.to_str();
  153. }
  154. #endif
  155. #if 1
  156. {
  157. ctimel c;
  158. for(int i=0;i<ifor;i++)
  159. {
  160. printf("%d: hellow world\n",i);
  161. }
  162. string s1 = c.to_str();
  163. int value=100;
  164. const char *s = "hellow world";
  165. for(int i=0;i<ifor;i++)
  166. {
  167. printf("%d: value: %d| s: %s\n",i,value,s);
  168. }
  169. string s2 = c.to_str();
  170. }
  171. #endif
  172. }
  173. void test_2()
  174. {
  175. Tflogs::get()->init("Tflog.log",false); //设置日志文件和追加模式
  176. Tflogs::get()->set_level(vlevel4::e_debug); //设置最低显示日志级别
  177. Tflogs::get()->set_limit(5); //设置日志数量(启动循环覆盖)--不设置则默认无限制
  178. Tflogs::get()->set_length(1024*1024*10); //设置最大日志长度(10M)--不设置默认64M
  179. //普通打印
  180. floge("== 普通打印 ==");
  181. flogi("e_info level");
  182. flogd("this template log");
  183. flogd("10+20 ret: " << 10+20);
  184. flogw("PI: "<<3.14);
  185. floge("2^4 calculate: "<<2*2<<" * "<<2*2<<" = "<<4*4);
  186. floge("2^4 calculate:" $(2*2) $(2*2) "=" $(4*4));
  187. //快速打印结果
  188. floge("== 快速打印 ==");
  189. int count = 0;
  190. for(int i=0;i<=100;i++) count += i;
  191. string str = "hello world";
  192. int ret = 10*60;
  193. flogd($(str) $(ret) $(count));
  194. int ifor = 3;
  195. #if 1
  196. {
  197. ctimel c;
  198. for(int i=0;i<ifor;i++)
  199. {
  200. flogw($(i) "hellow world");
  201. }
  202. string s1 = c.to_str();
  203. int value=100;
  204. string s = "hellow world";
  205. for(int i=0;i<ifor;i++)
  206. {
  207. flogw($(i) $(value) $(s));
  208. }
  209. string s2 = c.to_str();
  210. }
  211. #endif
  212. }
  213. int main()
  214. {
  215. printf("== begin ==\n");
  216. test_1();
  217. test_2();
  218. printf("== end ==\n");
  219. return 0;
  220. }
  221. /*
  222. * 测试结果:各个版本的运行时间
  223. *
  224. //flog:
  225. [nan: 3999236206|mic: 3999236|mil: 3999|sec: 3]
  226. [nan: 3981404537|mic: 3981404|mil: 3981|sec: 3]
  227. [nan: 3943364553|mic: 3943364|mil: 3943|sec: 3]
  228. //vlog-color:
  229. [nan: 9553316241|mic: 9553316|mil: 9553|sec: 9]
  230. [nan: 9509730052|mic: 9509730|mil: 9509|sec: 9]
  231. [nan: 9444099080|mic: 9444099|mil: 9444|sec: 9]
  232. //vlog:
  233. [nan: 9377207274|mic: 9377207|mil: 9377|sec: 9]
  234. [nan: 9237833979|mic: 9237833|mil: 9237|sec: 9]
  235. [nan: 9389804775|mic: 9389804|mil: 9389|sec: 9]
  236. //cout:
  237. [nan: 5033779586|mic: 5033779|mil: 5033|sec: 5]
  238. [nan: 5081468378|mic: 5081468|mil: 5081|sec: 5]
  239. [nan: 5098394323|mic: 5098394|mil: 5098|sec: 5]
  240. //print:
  241. [nan: 4815928537|mic: 4815928|mil: 4815|sec: 4]
  242. [nan: 4650109190|mic: 4650109|mil: 4650|sec: 4]
  243. [nan: 4881491074|mic: 4881491|mil: 4881|sec: 4]
  244. *
  245. * 测试结果:各个版本的打印格式
  246. *
  247. //flog:
  248. [2023-06-07 22:30:44] [War] <<<< [i: 0] hellow world [../cpp_tools/main_Tvlog.cpp:<227>]
  249. [2023-06-07 22:30:44] [War] <<<< [i: 1] hellow world [../cpp_tools/main_Tvlog.cpp:<227>]
  250. [2023-06-07 22:30:44] [War] <<<< [i: 2] hellow world [../cpp_tools/main_Tvlog.cpp:<227>]
  251. [2023-06-07 22:30:44] [War] <<<< [i: 0] [value: 100] [s: hellow world] [../cpp_tools/main_Tvlog.cpp:<234>]
  252. [2023-06-07 22:30:44] [War] <<<< [i: 1] [value: 100] [s: hellow world] [../cpp_tools/main_Tvlog.cpp:<234>]
  253. [2023-06-07 22:30:44] [War] <<<< [i: 2] [value: 100] [s: hellow world] [../cpp_tools/main_Tvlog.cpp:<234>]
  254. //vlog:
  255. [Deb][../cpp_tools/main_Tvlog.cpp:<146>] <<<< [i: 0] hellow world
  256. [Deb][../cpp_tools/main_Tvlog.cpp:<146>] <<<< [i: 1] hellow world
  257. [Deb][../cpp_tools/main_Tvlog.cpp:<146>] <<<< [i: 2] hellow world
  258. [Deb][../cpp_tools/main_Tvlog.cpp:<153>] <<<< [i: 0] [value: 100] [s: hellow world]
  259. [Deb][../cpp_tools/main_Tvlog.cpp:<153>] <<<< [i: 1] [value: 100] [s: hellow world]
  260. [Deb][../cpp_tools/main_Tvlog.cpp:<153>] <<<< [i: 2] [value: 100] [s: hellow world]
  261. //cout:
  262. 0: hellow world
  263. 1: hellow world
  264. 2: hellow world
  265. 0: value:100 | s:hellow world
  266. 1: value:100 | s:hellow world
  267. 2: value:100 | s:hellow world
  268. //print:
  269. 0: hellow world
  270. 1: hellow world
  271. 2: hellow world
  272. 0: value: 100| s: hellow world
  273. 1: value: 100| s: hellow world
  274. 2: value: 100| s: hellow world
  275. *
  276. * 测试结果:test_1函数的打印结果
  277. *
  278. == begin ==
  279. [Err][../cpp_tools/main_Tvlog.cpp:<95>] <<<< == 普通打印 ==
  280. [Inf][../cpp_tools/main_Tvlog.cpp:<96>] <<<< e_info level
  281. [Deb][../cpp_tools/main_Tvlog.cpp:<97>] <<<< this template log
  282. [Deb][../cpp_tools/main_Tvlog.cpp:<98>] <<<< 10+20 ret: 30
  283. [War][../cpp_tools/main_Tvlog.cpp:<99>] <<<< PI: 3.14
  284. [Err][../cpp_tools/main_Tvlog.cpp:<100>] <<<< 2^4 calculate: 4 * 4 = 16
  285. [Err][../cpp_tools/main_Tvlog.cpp:<101>] <<<< 2^4 calculate:[2*2: 4] [2*2: 4] =[4*4: 16]
  286. [Err][../cpp_tools/main_Tvlog.cpp:<104>] <<<< == 快速打印 ==
  287. [Deb][../cpp_tools/main_Tvlog.cpp:<109>] <<<< [str: hello world] [ret: 600] [count: 5050]
  288. [Err][../cpp_tools/main_Tvlog.cpp:<125>] <<<< == 容器打印--模板 ==
  289. | [../cpp_tools/main_Tvlog.cpp:<132>]
  290. | size: 25
  291. | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  292. | [../cpp_tools/main_Tvlog.cpp:<133>]
  293. | size: 25
  294. | 0 1 2 3 4
  295. | 5 6 7 8 9
  296. | 10 11 12 13 14
  297. | 15 16 17 18 19
  298. | 20 21 22 23 24
  299. | [../cpp_tools/main_Tvlog.cpp:<134>]
  300. | size: 25
  301. | 0][1][2][3][4][
  302. | 5][6][7][8][9][
  303. | 10][11][12][13][14][
  304. | 15][16][17][18][19][
  305. | 20][21][22][23][24][
  306. | [../cpp_tools/main_Tvlog.cpp:<135>]
  307. | size: 25
  308. | 0 1 2 3 4
  309. | 5 6 7 8 9
  310. | 10 11 12 13 14
  311. | 15 16 17 18 19
  312. | 20 21 22 23 24
  313. | [../cpp_tools/main_Tvlog.cpp:<136>]
  314. | size: 25
  315. | 0.1.2.3.4.
  316. | 5.6.7.8.9.
  317. | 10.11.12.13.14.
  318. | 15.16.17.18.19.
  319. | 20.21.22.23.24.
  320. == end ==
  321. *
  322. * 测试结果:test_2函数的打印结果
  323. *
  324. [2023-06-07 22:34:36] [Err] <<<< == 普通打印 == [../cpp_tools/main_Tvlog.cpp:<204>]
  325. [2023-06-07 22:34:36] [Deb] <<<< this template log [../cpp_tools/main_Tvlog.cpp:<206>]
  326. [2023-06-07 22:34:36] [Deb] <<<< 10+20 ret: 30 [../cpp_tools/main_Tvlog.cpp:<207>]
  327. [2023-06-07 22:34:36] [War] <<<< PI: 3.14 [../cpp_tools/main_Tvlog.cpp:<208>]
  328. [2023-06-07 22:34:36] [Err] <<<< 2^4 calculate: 4 * 4 = 16 [../cpp_tools/main_Tvlog.cpp:<209>]
  329. [2023-06-07 22:34:36] [Err] <<<< 2^4 calculate:[2*2: 4] [2*2: 4] =[4*4: 16] [../cpp_tools/main_Tvlog.cpp:<210>]
  330. [2023-06-07 22:34:36] [Err] <<<< == 快速打印 == [../cpp_tools/main_Tvlog.cpp:<213>]
  331. [2023-06-07 22:34:36] [Deb] <<<< [str: hello world] [ret: 600] [count: 5050] [../cpp_tools/main_Tvlog.cpp:<218>]
  332. */
  1. //!
  2. //! Tvlog.h
  3. //!
  4. #ifndef TVLOG_H
  5. #define TVLOG_H
  6. #include <iostream>
  7. #include <fstream>
  8. #include <mutex>
  9. //== 单例模板 ==
  10. template<class T>
  11. class Tsingle_d
  12. {
  13. public:
  14. static T* get()
  15. {
  16. if(_obj == nullptr)
  17. {
  18. _mut.lock();
  19. if(_obj == nullptr) { _obj = new T; }
  20. _mut.unlock();
  21. }
  22. return _obj;
  23. }
  24. void clean()
  25. {
  26. _mut.lock();
  27. delete _obj; _obj = nullptr;
  28. _mut.unlock();
  29. }
  30. private:
  31. static T *_obj;
  32. static std::mutex _mut;
  33. friend T;
  34. Tsingle_d() = default;
  35. ~Tsingle_d() = default;
  36. Tsingle_d(const Tsingle_d &) = delete ;
  37. };
  38. template<class T> T *Tsingle_d<T>::_obj = nullptr;
  39. template<class T> std::mutex Tsingle_d<T>::_mut;
  40. //== 单例模板 ==
  41. //== 等级 ==
  42. namespace level4
  43. { enum level{ e_error,e_warning,e_debug,e_info }; }
  44. namespace level8
  45. { enum level{ e_off,e_fatal,e_error,e_warning,e_debug,e_trace,e_all }; }
  46. //== 等级 ==
  47. //== 调试日志模板 ==
  48. //提供等级自定义模板参数
  49. template<class Tlevel>
  50. class Tvlog
  51. {
  52. public:
  53. inline void set_level(Tlevel el){ _level = el; } //设置等级
  54. inline Tvlog& operator<<(Tlevel el)
  55. { if(el <= _level) _ok = true; else _ok = false; return *this; };
  56. inline Tvlog& operator<<(std::ostream& (*end)(std::ostream&))
  57. { if(_ok) std::cout<<end; return *this; };
  58. template<class T>
  59. inline Tvlog& operator<<(const T &log)
  60. { if(_ok) std::cout<<log; return *this; };
  61. private:
  62. bool _ok = false; //判断等级是否符合
  63. Tlevel _level; //最低显示的等级
  64. };
  65. //== 调试日志模板 ==
  66. //== 文件日志模板 ==
  67. //提供等级自定义模板参数
  68. template<class Tlevel>
  69. class Tflog
  70. {
  71. public:
  72. inline bool init(const std::string &file = "Tflog.log",bool app = true) //初始化日志
  73. {
  74. _file = file;
  75. if(app) _mode = std::ios::app; else _mode = std::ios::out;
  76. if(_fs.is_open() == false) _fs.open(_file,_mode);
  77. return _fs.is_open();
  78. }
  79. static std::string date_time() //获取秒精度的日期时间
  80. {
  81. time_t t; time(&t); char buf[64] = {0};
  82. strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S",localtime(&t));
  83. return std::string(buf);
  84. }
  85. inline void set_limit(int max) { _limit_max = max; } //设置数量限制
  86. inline void set_level(Tlevel el) { _level = el; } //设置等级
  87. inline void set_length(size_t len) { _len_max = len;} //设置文件长度
  88. inline void close_log() { _fs.close(); } //关闭日志
  89. inline Tflog& operator<<(Tlevel el)
  90. { if(el <= _level) _ok = true; else _ok = false; return *this; };
  91. inline Tflog& operator<<(std::ostream& (*end)(std::ostream&))
  92. { if(_ok &&_fs.is_open()){ _fs<<end; update_file(); } return *this; };
  93. template<class T>
  94. inline Tflog& operator<<(const T &log)
  95. { if(_ok &&_fs.is_open()) _fs<<log; return *this; };
  96. private:
  97. bool _ok = false; //判断等级是否符合
  98. int _limit_max = 0; //日志文件限制数量
  99. int _limit_now = 1; //当前写入日志
  100. Tlevel _level; //最低显示的等级
  101. std::fstream _fs; //文件对象
  102. std::string _file; //文件名
  103. size_t _len_max = (1 << 26); //最大长度--64M
  104. std::ios_base::openmode _mode; //文件打开模式
  105. void update_file() //超出最大文件限制后更新文件名
  106. {
  107. if(_len_max < (size_t)_fs.tellg())
  108. {
  109. if(_limit_max == 0) write_unlimited();
  110. else write_limit();
  111. }
  112. }
  113. void write_unlimited() //无限制日志
  114. {
  115. _fs.close();
  116. for(int i=1;;i++)
  117. {
  118. std::string new_file = std::to_string(i)+"_"+_file;
  119. if(exist_file(new_file) == false)
  120. { rename(_file.c_str(),new_file.c_str()); break; }
  121. }
  122. _fs.open(_file,_mode);
  123. }
  124. void write_limit() //限制日志数量
  125. {
  126. _fs.close();
  127. {
  128. std::string new_file = std::to_string(_limit_now)+"_"+_file;
  129. rename(_file.c_str(),new_file.c_str());
  130. _limit_now++;
  131. if(_limit_now > _limit_max) _limit_now = 1;
  132. }
  133. _fs.open(_file,_mode);
  134. }
  135. static bool exist_file(const std::string &filename) //判断文件是否存在
  136. { std::ifstream f(filename); return f.is_open(); }
  137. };
  138. //== 文件日志模板 ==
  139. typedef level4::level vlevel4;
  140. typedef Tsingle_d<Tflog<vlevel4>> Tflogs;
  141. typedef Tsingle_d<Tvlog<vlevel4>> Tvlogs;
  142. //颜色打印--注释掉则无颜色
  143. //#define VLOG_COLOR
  144. //调试打印--开启则关闭调试打印
  145. //#define VLOG_CLOSE
  146. //== 功能宏 ==
  147. //快速打印变量值
  148. //参数:打印的值
  149. #define $(value) "["#value": "<<value<<"] "
  150. //== 功能宏 ==
  151. //== 打印工厂宏 ==
  152. #define VMAKE_LOG(txt,type,...) \
  153. *Tsvlog::get()<<type \
  154. <<txt "["<<__FILE__<<":<"<<__LINE__<<">] <<<< " \
  155. <<__VA_ARGS__<<std::endl \
  156. #define VMAKE_LOG_COL(txt,type,...) \
  157. *Tvlogs::get()<<type \
  158. <<txt "["<<__FILE__<<":<"<<__LINE__<<">] <<<< " \
  159. <<__VA_ARGS__<<"\033[0m"<<std::endl \
  160. #define FMAKE_LOG(txt,type,...) \
  161. *Tflogs::get()<<type \
  162. <<"["<<Tflogs::get()->date_time()<<"] " \
  163. <<txt " <<<< "<<__VA_ARGS__ \
  164. <<" ["<<__FILE__<<":<"<<__LINE__<<">]"<<std::endl \
  165. //== 打印工厂宏 ==
  166. //== 调试日志宏 ==
  167. #ifndef VLOG_CLOSE
  168. #ifndef VLOG_COLOR
  169. #define vlogi(...) VMAKE_LOG("[Inf]",vlevel4::e_info,__VA_ARGS__)
  170. #define vlogd(...) VMAKE_LOG("[Deb]",vlevel4::e_debug,__VA_ARGS__)
  171. #define vlogw(...) VMAKE_LOG("[War]",vlevel4::e_warning,__VA_ARGS__)
  172. #define vloge(...) VMAKE_LOG("[Err]",vlevel4::e_error,__VA_ARGS__)
  173. #else //== 颜色打印分界 ==
  174. #define vlogi(...) VMAKE_LOG_COL("[Inf]",vlevel4::e_info,__VA_ARGS__)
  175. #define vlogd(...) VMAKE_LOG_COL("\033[32m[Deb]",vlevel4::e_debug,__VA_ARGS__)
  176. #define vlogw(...) VMAKE_LOG_COL("\033[33m[War]",vlevel4::e_warning,__VA_ARGS__)
  177. #define vloge(...) VMAKE_LOG_COL("\033[31m[Err]",vlevel4::e_error,__VA_ARGS__)
  178. #endif
  179. #else
  180. #define vlogi(...)
  181. #define vlogd(...)
  182. #define vlogw(...)
  183. #define vloge(...)
  184. #endif
  185. //== 调试日志宏 ==
  186. //== 文件日志宏 ==
  187. #define flogi(...) FMAKE_LOG("[Inf]",vlevel4::e_info,__VA_ARGS__)
  188. #define flogd(...) FMAKE_LOG("[Deb]",vlevel4::e_debug,__VA_ARGS__)
  189. #define flogw(...) FMAKE_LOG("[War]",vlevel4::e_warning,__VA_ARGS__)
  190. #define floge(...) FMAKE_LOG("[Err]",vlevel4::e_error,__VA_ARGS__)
  191. //== 文件日志宏 ==
  192. //===== 容器打印 =====
  193. //参数:容器
  194. template<class T>
  195. void print_con(const T& con)
  196. {
  197. std::cout<<"| size: "<<con.size()<<std::endl<<"| ";
  198. for(const auto &a:con)
  199. {
  200. std::cout<<a<<" ";
  201. }
  202. std::cout<<std::endl;
  203. }
  204. //参数:容器,换行长度
  205. template<class T>
  206. void print_con(const T& con,int len)
  207. {
  208. int count = 0;
  209. std::cout<<"| size: "<<con.size()<<std::endl<<"| ";
  210. for(const auto &a:con)
  211. {
  212. if(count >= len) { count = 0; std::cout<<std::endl<<"| "; }
  213. count++;
  214. std::cout<<a<<" ";
  215. }
  216. std::cout<<std::endl;
  217. }
  218. //参数:容器,换行长度,分割符
  219. template<class T>
  220. void print_con(const T& con,int len,const std::string &flg)
  221. {
  222. int count = 0;
  223. std::cout<<"| size: "<<con.size()<<std::endl<<"| ";
  224. for(const auto &a:con)
  225. {
  226. if(count >= len) { count = 0; std::cout<<std::endl<<"| "; }
  227. count++;
  228. std::cout<<a<<flg;
  229. }
  230. std::cout<<std::endl;
  231. }
  232. //参数:开始迭代器,结束迭代器,长度
  233. template<class Tit>
  234. void print_con(Tit begin,Tit end,int len)
  235. {
  236. int count = 0;
  237. std::cout<<"| size: "<<end - begin<<std::endl<<"| ";
  238. for(auto it=begin;it!=end;it++)
  239. {
  240. if(count >= len) { count = 0; std::cout<<std::endl<<"| "; }
  241. count++;
  242. std::cout<<*it<<" ";
  243. }
  244. std::cout<<std::endl;
  245. }
  246. //参数:开始迭代器,结束迭代器,长度,分割符号
  247. template<class Tit>
  248. void print_con(Tit begin,Tit end,int len,const std::string &flg)
  249. {
  250. int count = 0;
  251. std::cout<<"| size: "<<end - begin<<std::endl<<"| ";
  252. for(auto it=begin;it!=end;it++)
  253. {
  254. if(count >= len) { count = 0; std::cout<<std::endl<<"| "; }
  255. count++;
  256. std::cout<<*it<<flg;
  257. }
  258. std::cout<<std::endl;
  259. }
  260. #ifndef VLOG_CLOSE
  261. //参数:$v的容器打印,$v的参数
  262. #define vlogc(...) \
  263. std::cout<<"| ["<<__FILE__<<":<"<<__LINE__<<">]"<<std::endl; \
  264. print_con(__VA_ARGS__);
  265. #else
  266. #define vlogc(...)
  267. #endif
  268. //== 容器打印格式 ==
  269. #endif // TVLOG_H

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/262020
推荐阅读
相关标签
  

闽ICP备14008679号