当前位置: 首页 > wzjs >正文

推广下载app拿佣金seo外包如何

推广下载app拿佣金,seo外包如何,wordpress完整中文免费主题下载,网站开发郑州C项目 —— 基于多设计模式下的同步&异步日志系统(2)(工厂模式) 基类实现滚动文件文件名问题 工厂模式一些扩展点struct tm 成员列表关键注意事项使用示例1. 获取当前时间并打印2. 与 strftime 配合使用3. 构造自定义时间 常见…

C++项目 —— 基于多设计模式下的同步&异步日志系统(2)(工厂模式)

  • 基类实现
  • 滚动文件
    • 文件名问题
  • 工厂模式
  • 一些扩展点
      • `struct tm` 成员列表
      • 关键注意事项
      • 使用示例
        • 1. 获取当前时间并打印
        • 2. 与 `strftime` 配合使用
        • 3. 构造自定义时间
      • 常见问题
      • 可视化记忆表

我们在之前把日志消息的主体已经组织好了,而且我们创建的适当的类控制日志格式,并且按照我们的格式组织日志消息。如果还没有看过的小伙伴可以点击这里:

https://blog.csdn.net/qq_67693066/article/details/147162921?sharetype=blogdetail&sharerId=147162921&sharerefer=PC&sharesource=qq_67693066&spm=1011.2480.3001.8118

我们这次的任务是要完成日志器中的一个小功能实现:日志输出的方向,我们日志输出的方向有:控制台固定文件滚动文件。这个模块的实现还会涉及到工厂模式的使用

基类实现

首先设计思想还是比较清晰的,设计一个基类,派生出三个不同的方向,我们先实现两个方向比较简单的:

namespace logs
{//基类实现class BaseSink{public:using ptr = std::shared_ptr<BaseSink>; BaseSink(){}virtual ~BaseSink() {}virtual void log(const char *data, size_t len) = 0; //要继承实现的接口};class StdoutSink : public BaseSink{public://将日志消息写到标准输出void log(const char *data, size_t len){std::cout.write(data, len);}};class FixFileSink : public BaseSink {public:FixFileSink(const std::string& pathname):_pathname(pathname){//1.创建文件所在路径logs::utils::File::createDiretory(logs::utils::File::path(_pathname));//2.创建文件并打开_ofs.open(_pathname,std::ios::binary | std::ios::app);assert(_ofs.is_open());}//将日志消息写到固定文件中void log(const char *data, size_t len){_ofs.write(data,len);assert(_ofs.good());}private:std::string _pathname; //创建文件时的文件路径std::ofstream _ofs; //流式文件操作};
}

我们也可以顺便测试一下:

#include"utils.hpp"
#include"level.hpp"
#include"message.hpp"
#include"fometter.hpp"
#include "sink.hpp"int main()
{// std::cout << logs::utils::File::path("./abc/def");// logs::utils::File::createDiretory("./abc/def");//std::cout <<logs::Loglevel::toString(logs::Loglevel::value::DEBUG);logs::logMsg msg(logs::Loglevel::value::DEBUG,"main.cc",53,"root","格式化功能测试....");logs::Formetter fmt("abc[%d{%H:%M:%S}][%c]%T%m%n");std::string str = fmt.format(msg);//标准输入测试size_t len = str.size();logs:: StdoutSink st;st.log(str.c_str(),len);//文件测试logs::FixFileSink fx("../test/test.txt");fx.log(str.c_str(),len);
}

滚动文件

滚动文件意思是,如果这个文件日志已经被写满了,会自动换到一个新的文件写日志,写满了的话又继续换。

文件名问题

既然会不停的创建文件,我们就不得不考虑一个问题,文件名。文件名是不能重复的,那么有没有一种方式,能保证我们的文件名是绝对不会重复的呢?有的,时间戳,时间只要在流逝,时间戳就会变。我们可以让时间戳作为我们文件名的一部分,这样就可以保证文件绝对不会重复了。

    class RollFileSink : public BaseSink{public:private:std::string createNewFile(){//1.获取当前时间戳time_t time = logs::utils::Date::get_time();struct tm lt;localtime_r(&time,&lt);std::stringstream filename;filename << _basename;filename << lt.tm_year + 1900;filename << lt.tm_mon + 1;filename << lt.tm_mday;filename << lt.tm_hour;filename << lt.tm_min;filename << lt.tm_sec;filename << "-";filename << _name_count++;filename << ".log";return filename.str();}// 基础文件名 + 扩展文件名(以时间生成)组成一个实际的当前输出文件名size_t _name_count;std::string _basename; //基础文件名std::ofstream _ofs; //流式文件size_t _max_size; //最大文件大小size_t _cur_size: //当前文件大小};
   class RollFileSink : public BaseSink{public:RollFileSink(const std::string& basename,size_t max_size):_basename(basename),_name_count(0),_max_size(max_size),_cur_size(0){std::string pathname = createNewFile();//1、创建文件的所在路径logs::utils::File::createDiretory(logs::utils::File::path(pathname));// 2.创建并打开日志文件_ofs.open(pathname, std::ios::binary | std::ios::app);assert(_ofs.is_open());}// 将日志消息写到固定文件中void log(const char *data, size_t len){if(_cur_size > _max_size){_ofs.close();std::string pathname = createNewFile();//1、创建文件的所在路径logs::utils::File::createDiretory(logs::utils::File::path(pathname));// 2.创建并打开日志文件_ofs.open(pathname, std::ios::binary | std::ios::app);assert(_ofs.is_open());}_ofs.write(data, len);assert(_ofs.good());_cur_size += len;}private:std::string createNewFile(){//1.获取当前时间戳time_t time = logs::utils::Date::get_time();struct tm lt;localtime_r(&time,&lt);std::stringstream filename;filename << _basename;filename << lt.tm_year + 1900;filename << lt.tm_mon + 1;filename << lt.tm_mday;filename << lt.tm_hour;filename << lt.tm_min;filename << lt.tm_sec;filename << "-";filename << _name_count++;filename << ".log";return filename.str();}// 基础文件名 + 扩展文件名(以时间生成)组成一个实际的当前输出文件名size_t _name_count;std::string _basename; //基础文件名std::ofstream _ofs; //流式文件size_t _max_size; //最大文件大小size_t _cur_size; //当前文件大小};

我们可以测试一下:

    logs::RollFileSink roll("../test/mytest",1024);size_t cur = 0;while(cur < 1024 * 2){roll.log(str.c_str(),len);cur+=len;}

在这里插入图片描述

工厂模式

代码定义了一个名为 SinkFactory 的工厂类,用于创建日志输出器(Sink)的智能指针实例。它使用了现代 C++ 的模板和可变参数特性,是一个非常灵活通用的工厂实现:

    class SinkFactory{public:template<typename SinkType,typename... Args>static BaseSink::ptr create(Args && ...args){return std::make_shared<SinkType>(std::forward<Args>(args)...);}};
    auto st1 = logs::SinkFactory::create<logs::StdoutSink>();st1->log(str.c_str(),len);

这样我们不用用户直接接触接口,而是通过工厂,这样更具灵活性。

一些扩展点

struct tm 是 C/C++ 标准库中用于表示日历时间的结构体,定义在 <ctime> 头文件中。以下是其成员变量及详细说明:


struct tm 成员列表

成员类型说明取值范围注意事项
tm_secint0-61 (通常 0-59)允许闰秒
tm_minint分钟0-59
tm_hourint小时(24小时制)0-23
tm_mdayint月中的第几天(Day of month)1-31
tm_monint月份(从0开始)0-11 (0=1月)使用时需 +1
tm_yearint年份(从1900开始)0+=1900年使用时需 +1900
tm_wdayint星期几(从0开始,0=周日)0-6 (0=周日)
tm_ydayint年中的第几天(从0开始)0-365
tm_isdstint夏令时标志:
正数=启用
0=禁用
负数=信息不可用
-1, 0, 1

关键注意事项

  1. 特殊计数规则

    • 月份tm_mon 从 0 开始(0=1月,11=12月),显示时需要 +1
    • 年份tm_year 是 1900 年起的偏移量,真实年份 = tm_year + 1900
    • 星期tm_wday 中 0 表示周日
  2. 夏令时处理

    if (timeinfo.tm_isdst > 0) {std::cout << "夏令时生效";
    }
    
  3. 有效范围扩展

    • tm_sec 允许 60-61 以兼容闰秒
    • 其他字段超出范围时,mktime() 会自动标准化

使用示例

1. 获取当前时间并打印
#include <ctime>
#include <iostream>int main() {time_t now = time(nullptr);struct tm timeinfo;localtime_r(&now, &timeinfo);  // 线程安全版本std::cout << "当前时间: " << 1900 + timeinfo.tm_year << "-" << 1 + timeinfo.tm_mon << "-"<< timeinfo.tm_mday << " "<< timeinfo.tm_hour << ":"<< timeinfo.tm_min << ":"<< timeinfo.tm_sec;
}
2. 与 strftime 配合使用
char buf[64];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &timeinfo);
std::cout << "格式化时间: " << buf;
3. 构造自定义时间
struct tm custom_time = {0};
custom_time.tm_year = 2023 - 1900;  // 2023年
custom_time.tm_mon = 6 - 1;         // 6月
custom_time.tm_mday = 15;           // 15日
time_t t = mktime(&custom_time);    // 转换为time_t

常见问题

  1. 为什么年份从1900开始?
    历史原因,早期系统用2位数存储年份,1900为基准年。

  2. 如何获取时区信息?
    通过 tm_gmtofftm_zone(非标准扩展,需检查平台支持):

    #ifdef __linux__
    std::cout << "UTC偏移: " << timeinfo.tm_gmtoff / 3600 << "小时";
    #endif
    
  3. 线程安全注意

    • 优先使用 localtime_r()(POSIX)或 localtime_s()(Windows)
    • 避免使用非线程安全的 localtime()

可视化记忆表

struct tm {int tm_sec;    // 秒 [0,61]int tm_min;    // 分 [0,59]int tm_hour;   // 时 [0,23]int tm_mday;   // 日 [1,31]int tm_mon;    // 月 [0,11] ← 注意+1int tm_year;   // 年-1900  ← 注意+1900int tm_wday;   // 周几 [0,6] (0=周日)int tm_yday;   // 年内天数 [0,365]int tm_isdst;  // 夏令时标志
};

掌握这些成员的含义和特性,可以高效处理各种时间操作需求。

http://www.dtcms.com/wzjs/7132.html

相关文章:

  • 怎样让google收录网站不受国内限制的浏览器下载
  • 现在企业做网站用什么软件长沙网络推广营销
  • 免费设计logo的网站有哪些推广渠道有哪些方式
  • 开源php表单系统石家庄百度搜索引擎优化
  • wordpress火车头采集器上海百度首页优化
  • 免费的网站怎么做百度seo优
  • 太原网站建设工作室没经验可以做电商运营吗
  • 合肥公司网站开发百度广告官网
  • 怎么做倒计时网站网络营销有哪些功能
  • mac怎么升级wordpress谷歌自然排名优化
  • 企业网站推广推广阶段手机关键词点击排名软件
  • 用别人网站做app的危害app推广平台接单渠道
  • 网站建设是什么软件网站权重是怎么提升的
  • 建设部网站拆除资质微信群发软件
  • 专门做娱乐场所的设计网站百度搜索风云榜小说排行榜
  • 必应网站收录提交入口百度首页排名优化公司
  • 深圳专业做网站开发费用国内最好用免费建站系统
  • 高端企业网站建设方案百度官网认证多少钱
  • 自己开一个网站怎么赚钱快速将网站seo
  • 上海静安网站建设网络推广 公司 200个网站
  • 垫江网站建设费用天津网站排名提升多少钱
  • zbolg 去掉文章页带网站标题网络营销的方式有几种
  • 鞍山网站制作招聘网百度指数免费添加
  • 网站建设域名的购买怎样做网站卖自己的产品
  • 给企业做网站如何关闭2345网址导航
  • 例点估算网站开发项目工作量谷歌浏览器下载手机版安卓
  • 可做宣传的网站都有哪些app拉新项目推广代理
  • dede仿手机网站模板深圳全网推广托管
  • 西宁做网站的工作室谷歌排名优化入门教程
  • 怎么做企业销售网站邢台市seo服务