使用C++实现一个简单的日志功能

日志对于一些大一些的项目来说,可以在项目运行出现问题时更好的帮助
项目的维护人员快速的定位到问题出现的地方并且知道出现问题的原因,
并且日志也可以帮助程序员很好的进行项目的Debug,那么今天我就来实
现一个C++编写的一个简单的日志功能。

1. 简单功能的实现

我的第一步就是先写出一个大致的框架,能用就行:
在这里插入图片描述
现在我们要让它输出消息,对于日志来说,一个日志一定要有日志的等级,日志的时间,日志的内容,前两点比较容易,日志的等级可以使用枚举来表示,而日志的时间也很容易,对于日志的内容来说可以实现的更加多元化一点,这一点可以由用户输出自己想输出的内容,所以这里使用了可变参数列表:
在这里插入图片描述
有人看到这个会不会很熟悉,C标准库中的printf好像参数就长这样:
在这里插入图片描述
我就是想用这样的方式,来让用户输入自己想输出的格式,然后附带对应参数输出,由于输出的参数的个数和类型都不确定,所以我们使用可变参数来实现用户的传参。有人就问了,那这个可变参数中的参数怎么拿到呢?难道我们就这样给printf传过去吗?
在这里插入图片描述
显然是不行的,所以这里就有必要介绍如何获取到可变参数了。

可变参数

C语言针对可变参数做了几个宏,以便于用户能够获取到可变参数里的参数:
在这里插入图片描述
其中关于携带可变参数的函数,该函数的可变参数前必须有一个明确类型的参数:
在这里插入图片描述
原因就是,在调用函数之后,函数开始运行前要进行压栈,以及函数参数的加载,而函数参数的加载从右往左的,也就是说,可变参数前的参数是为了能够方便定位到可变参数的位置。
对于获取可变参数中的参数,我们首先需要一个va_list类型的变量(其实就是一个指针):
然后使用va_start对该变量进行初始化,这个宏的第一个参数就是arg,第二个参数就是可变参数前面的参数,通过va_arg根据顺序和参数类型拿到参数(这个顺序和类型都是用户已知的),最后使用va_end对arg进行销毁(其实就是置空):
在这里插入图片描述
在这里插入图片描述

而对于实现到日志上的可变参数,反正我们对这些参数是能够打印出来就行了,所以这里再介绍一批接口:
在这里插入图片描述
可以看到C标准库种有专门的针对va_list变量的打印措施,所以对于上面的代码我们也可以这么写:
在这里插入图片描述
在这里插入图片描述
有了上面的准备工作我们就可以继续编写日志代码了:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
但是我们发现我们无法识别到任务的等级是什么,只是一个数字,并且我们的时间是一个时间戳,不方便进行观察,所以这里再次做出优化:
关于时间这里再次介绍一个接口:
在这里插入图片描述
在这里插入图片描述
这个接口可以将时间戳转化成一个对应年月日时分秒的结构体:
在这里插入图片描述
在这里插入图片描述
这样这个日志打印出来就比较直观了。
这样的日志是打印在屏幕上,但是大多数情况日志是存储在文件中的,所以我们的日志要支持自定义式的让用户来决定日志打印到哪里,而打印到文件中,可能是一个文件,也可能是根据日志等级来分开打印,所以我们的日志打印又要支持多文件打印,也要支持单个文件的打印,所以我们的Log类中要添加两个字段:打印格式,目标文件:
那么现在我们又要对日志输出函数进行更深层次的封装了:
在这里插入图片描述

在这里插入图片描述

那么关于向文件中写日志,要为文件定制一个名字,这里采用. + 日志等级为后缀,如果是向一个文件中打印的话,后缀就是.all:
在这里插入图片描述

在这里插入图片描述
现在我们就可以以三种方式输出日志了:
在这里插入图片描述

屏幕:
在这里插入图片描述
单个文件:
在这里插入图片描述
多个文件:
在这里插入图片描述

2. 优化

我们看到我们的代码大部分使用的都是C++中的string,但是使用的接口大多都是C语言的接口,导致输出字符串时,都得使用c_str()来转换,这个接口打起来可能有些麻烦,所以我们宏定义一下:
在这里插入图片描述
在这里插入图片描述
上面展示宏使用的这个snprintf中的内容优有点难看,这里也需要优化一下:
在这里插入图片描述

我们也可以利用仿函数来将我们日志接口的使用来变得更简单:
在这里插入图片描述

但是我们发现,可变参数并不能够在多个函数上进行传递,所以我们这里依旧利用va_list来实现传参:
在这里插入图片描述
这样我们在使用日志接口时就可以是这样:
在这里插入图片描述
并将LogMessage函数置为私有,我们也知道,日志功能在一个项目中输出的格式应该是一致的,所以日志对象应该是只有一个,所以:
在这里插入图片描述

至此我们的日志的使用起来就是这样:
在这里插入图片描述
而我们想要修改日志的输出格式只需要修改类内Conf的全局对象就可以:
在这里插入图片描述
至此,一个简单的日志功能就实现了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/772264.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习中常用计算距离的几种算法对比与python实现

前言 距离度量在许多机器学习算法中扮演着至关重要的角色,无论是监督学习还是无监督学习。选择适当的距离度量可以显著影响模型的性能。 在高维数据集中,欧几里得距离可能会受到所谓的“维度诅咒”的影响,因为随着维度的增加,数…

海外媒体软文发稿:谷歌关键词优化细分人群成功案例,突破海外市场!

海外媒体软文发稿:谷歌关键词优化细分人群成功案例,突破海外市场! 引言 在全球化的时代,海外市场对于企业的发展至关重要。而在海外市场中,互联网媒体的作用不可忽视。本篇教程将介绍如何通过谷歌关键词优化细分人群…

Spring设计模式-实战篇之单例模式

实现案例,饿汉式 Double-Check机制 synchronized锁 /*** 以饿汉式为例* 使用Double-Check保证线程安全*/ public class Singleton {// 使用volatile保证多线程同一属性的可见性和指令重排序private static volatile Singleton instance;public static Singleton …

Learn OpenGL 30 SSAO

SSAO 我们已经在前面的基础教程中简单介绍到了这部分内容:环境光照(Ambient Lighting)。环境光照是我们加入场景总体光照中的一个固定光照常量,它被用来模拟光的散射(Scattering)。在现实中,光线会以任意方向散射,它的强度是会一…

C++ STL - 优先级队列及其模拟实现

目录 0. 引言 1. priority_queue 介绍 1.1 构造函数 1.2 priority_queue 接口函数使用 1.3 仿函数 1.4 题目练习 2. priority_queue 模拟实现 2.1基本框架: 2.2 默认构造函数 2.3 基本函数 2.4 堆的向上以及向下调整 0. 引言 优先队列 (priority_queu…

【剑指offr--C/C++】JZ22 链表中倒数最后k个结点

一、题目 二、思路及代码 遍历链表并存入vector容器&#xff0c;通过下标取出对应位置元素或者返回空 /*** struct ListNode {* int val;* struct ListNode *next;* ListNode(int x) : val(x), next(nullptr) {}* };*/ #include <cstddef> #include <iterator> #…

【微服务】接口幂等性常用解决方案

一、前言 在微服务开发中&#xff0c;接口幂等性问题是一个常见却容易被忽视的问题&#xff0c;同时对于微服务架构设计来讲&#xff0c;好的幂等性设计方案可以让程序更好的应对一些高并发场景下的数据一致性问题。 二、幂等性介绍 2.1 什么是幂等性 通常我们说的幂等性&…

【Entity Framework】 EF三种开发模式

【Entity Framework】 EF三种开发模式 文章目录 【Entity Framework】 EF三种开发模式一、概述二、DataBase First2.1 DataBase First简介2.2 DataBase First应用步骤2.3 DataBase First总结 三、Model First3.1 Model First简介3.2 Model First实现步骤 四、Code First4.1 Cod…

全市场都忽视了!大摩:数据中心算力成本正在迅速下降

随着AI技术迈入普及与应用的新纪元&#xff0c;其算力需求蓬勃增长的同时&#xff0c;算力成本随技术进步呈现下降趋势。 摩根士丹利在3月24日的AI报告中指出&#xff0c;随着GPU技术的不断进步&#xff0c;例如英伟达从Hopper发展到Blackwell GPU架构&#xff0c;GAI的算力成…

ChatGPT 对 ELT的理解

本文主要内容来自 ChatGPT 4.0 到底什么是 ETL&#xff1f;在数据库内部&#xff0c;把数据从 ODS 层加工成 DWD&#xff0c;再加工成 DWS&#xff0c;这个过程和 ETL 的关系是什么&#xff1f;带着这些问题&#xff0c;我问了一下 ChatGPT&#xff0c;总结如下。 数据在两个数…

AWS EC2设置root登录

在使用亚马逊的服务器时&#xff0c;官方默认是使用密钥登录&#xff0c;跟国内的云服务器差别较大&#xff0c;本文记录下&#xff0c;如何开放AWS EC2的root登录。 一、通过网页版或者XShell登录服务器 这里略过 二、设置root账户密码 # 切换 root sudo -i # 设置或修改密…

静态住宅IP VS 动态住宅IP,怎么选择?

在进行海外 IP 代理时&#xff0c;了解动态住宅 IP 和静态住宅 IP 的区别以及如何选择合适的类型非常重要。本文将介绍精态住宅 IP 特点和&#xff0c;并提供选择建议&#xff0c;帮助您根据需求做出明智的决策。 静态住宅 IP 的特点 静态住宅 IP 是指 IP 地址在一段时间内保…

故障诊断 | 一文解决,CNN-BiLSTM卷积神经网络-双向长短期记忆神经网络组合模型的故障诊断(Matlab)

效果一览 文章概述 故障诊断 | 一文解决,CNN-BiLSTM卷积神经网络-双向长短期记忆神经网络组合模型的故障诊断(Matlab) 模型描述 CNN-BiLSTM卷积神经网络-双向长短期记忆神经网络组合模型是一种深度学习模型,结合了卷积神经网络(CNN)和双向长短期记忆网络(BiLSTM)的优点…

CBLUEbenchmark代码跑通

CBLUEbenchmark 跑通 github源地址 1.配置 数据下载 新建文件夹CLBUEDatasets,将数据放在该文件夹下模型下载到github源地址中选择一个模型来下载: 将下载好的模型放在一个专门放模型的文件夹下&#xff0c;我这里是bert 文件如下所示放置&#xff1a; 2.训练模型&#xff…

宁德时代与特斯拉合作;钟睒睒连续四次中国首富丨 RTE 开发者日报 Vol.171

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、…

全自动引流,每日500+粉丝的秘诀

在如今竞争激烈的市场环境下&#xff0c;如何有效地吸引和保持精准粉丝成为了每个企业主或网红必须面对的问题。然而&#xff0c;许多人可能误以为全自动引流就意味着无人参与&#xff0c;实际上&#xff0c;它更多的是借助一些自动化工具和策略来提升我们的工作效率。今天&…

阿尔吉侬的花束 (典bfs)

0326重写&#xff0c;一个小时终于成功了 #include<algorithm> #include<iostream> #include<cstring> #include<queue>using namespace std;int t; int r,c; char mp[210][210]; bool vis[210][210]; struct node{int x,y; }; int dx[] {1,-1,0,0};…

《量子计算:揭开未来科技新篇章》

随着科技的不断发展&#xff0c;量子计算作为一项颠覆性的技术逐渐走进人们的视野&#xff0c;引发了广泛的关注和探讨。本文将围绕量子计算的技术进展、技术原理、行业应用案例、未来趋势预测以及学习路线等方向&#xff0c;深入探讨这一领域的前沿动态和未来发展趋势。 量子…

springboot swagger 接口文档分组展示

例如将 controller 分成四类&#xff0c;分别放到四个包下&#xff1a; xxx.xxx.xxx.controller.manage xxx.xxx.xxx.controller.client xxx.xxx.xxx.controller.authority xxx.xxx.xxx.controller.common SwaggerConfig.java&#xff1a; import io.swagger.annotations.Api…