一个简简单单的废物C++11日志输出封装

实现

#pragma once

#ifndef _LOG_CPP_HPP_
#define _LOG_CPP_HPP_

#include <iostream>
#include <string>
#include <deque>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <fstream>
#ifdef _MSC_VER
#include <ctime>
#include <memory>
#define LOG_FUNCTION __FUNCSIG__
#else
#define LOG_FUNCTION __PRETTY_FUNCTION__
#endif
// 日志输出等级
#ifndef LOG_CPP_LEVEL
#define LOG_CPP_LEVEL 100
#endif

// 默认日志输出等级,全部
#define LOG_CPP_DEBUG 1
#define LOG_CPP_INFO 10
#define LOG_CPP_ERROR 100

/**
* @brief Get the Current Time object
*
* @return std::string
*/
inline std::string getCurrentTime()
{
#ifndef _MSC_VER
	auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
	struct tm *ptm = localtime(&tt);
	char date[60] = { 0 };
	sprintf(date, "%d-%02d-%02d %02d:%02d:%02d",
		(int)ptm->tm_year + 1900, (int)ptm->tm_mon + 1, (int)ptm->tm_mday,
		(int)ptm->tm_hour, (int)ptm->tm_min, (int)ptm->tm_sec);
	return date;
#else
	struct tm newtime;
	char am_pm[] = "AM";
	__time64_t long_time;
	char date[60] = { 0 };
	errno_t err;

	// Get time as 64-bit integer.
	_time64(&long_time);
	// Convert to local time.
	err = _localtime64_s(&newtime, &long_time);
	sprintf_s(date, "%d-%02d-%02d %02d:%02d:%02d",
		(int)newtime.tm_year + 1900, (int)newtime.tm_mon + 1, (int)newtime.tm_mday,
		(int)newtime.tm_hour, (int)newtime.tm_min, (int)newtime.tm_sec);
	return date;
#endif
}

class SpaceFunction
{
public:
	SpaceFunction &operator<<(const std::string _t) { return *this; }
	SpaceFunction &operator<<(const int _t) { return *this; }
};

class LogCpp
{
private:
	/**
	* @brief 本对象的任务队列
	*
	*/
	std::deque<std::string> m_task;

	/**
	* @brief 写入线程条件变量
	*
	*/
	std::condition_variable m_cond;

	/**
	* @brief 写入线程执行锁
	*
	*/
	std::mutex m_mutex;

	/**
	* @brief 初始化
	*
	*/
	void ini()
	{
		m_thread = std::make_shared<std::thread>([this]()
		{
			while (true) {
				std::unique_lock<std::mutex> lock(m_mutex);
				if (this->m_task.empty() || this->m_logFile == nullptr) {
					m_cond.wait(lock);
				}
				this->m_logFile->write(m_task.front().c_str(), m_task.front().size());
				m_task.pop_front();
				std::this_thread::yield();
			} });
		m_thread->detach();
	}

public:
	/**
	* @brief 空白函数
	*
	* @param _t 需要忽略的参数
	* @return LogCpp& 自身引用
	*/
	SpaceFunction _spaceFunction;
	/**
	* @brief 日志文件指针
	*
	*/
	std::shared_ptr<std::ofstream> m_logFile = nullptr;
	/**
	* @brief 写文件线程指针
	*
	*/
	std::shared_ptr<std::thread> m_thread = nullptr;

public:
	/**
	* @brief Construct a new LogCpp object
	*
	*/
	LogCpp()
	{
		ini();
	}

	~LogCpp()
	{
		getGlobalLogCpp()->m_logFile->close();
	}

	/**
	* @brief Set the Global Path object
	*
	* @param filePath
	*/
	static void setGlobalPath(const std::string &filePath)
	{
		if (nullptr != getGlobalLogCpp()->m_logFile)
		{
			getGlobalLogCpp()->m_logFile->close();
			getGlobalLogCpp()->m_logFile = nullptr;
		}
		getGlobalLogCpp()->m_logFile = std::make_shared<std::ofstream>(filePath, std::ios::app);
	}

	/**
	* @brief 输出日志
	*
	* @param log 日志串
	* @return LogCpp 全局对象
	*/
	LogCpp &operator<<(const std::string &log)
	{
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
			m_task.emplace_back(log);
		}
		else
		{
			m_task.back().append(log);
		}
		m_cond.notify_one();
		return *this;
	}
	/**
	* @brief 输出日志
	*
	* @param num 数字
	* @return LogCpp 全局对象
	*/
	LogCpp &operator<<(int num)
	{
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
			m_task.emplace_back(std::to_string(num));
		}
		else
		{
			m_task.back().append(std::to_string(num));
		}
		m_cond.notify_one();
		return *this;
	}

	/**
	* @brief 新的一行
	*
	* @return LogCpp 对象本身
	*/
	LogCpp &addLine()
	{
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
			m_task.emplace_back("\n" + getCurrentTime());
		}
		else
		{
			m_task.back().append("\n" + getCurrentTime());
		}
		m_cond.notify_one();
		return *this;
	}

	/**
	* @brief 错误输出
	*
	* @return LogCpp& 自身引用
	*/
	LogCpp &err()
	{

#if LOG_CPP_LEVEL >= LOG_CPP_ERROR
#define LogErr (LogCpp::getGlobalLogCpp()->addLine().err() << __FILE__ << ":" << LOG_FUNCTION << ":" << __LINE__ << " ")
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
			m_task.emplace_back(" [ERROR] ");
		}
		else
		{
			m_task.back().append(" [ERROR] ");
		}
		m_cond.notify_one();
#else
		// 舍弃流
#define LogErr (LogCpp::getGlobalLogCpp()->_spaceFunction)
#endif // LOG_CPP_LEVEL
		return *this;
	}

	/**
	* @brief 信息输出
	*
	* @return LogCpp& 自身引用
	*/
	LogCpp &info()
	{

#if LOG_CPP_LEVEL >= LOG_CPP_INFO
#define LogInfo (LogCpp::getGlobalLogCpp()->addLine().info() << __FILE__ << ":" << LOG_FUNCTION << ":" << __LINE__ << " ")
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
			m_task.emplace_back(" [INFO] ");
		}
		else
		{
			m_task.back().append(" [INFO] ");
		}
		m_cond.notify_one();
#else
		// 舍弃流
#define LogErr (LogCpp::getGlobalLogCpp()->_spaceFunction)
#endif // LOG_CPP_LEVEL
		return *this;
	}

	/**
	* @brief 调试输出
	*
	* @return LogCpp& 自身引用
	*/
	LogCpp &debug()
	{
#if LOG_CPP_LEVEL >= LOG_CPP_DEBUG
#define LogDebug (LogCpp::getGlobalLogCpp()->addLine().debug() << __FILE__ << ":" << LOG_FUNCTION << ":" << __LINE__ << " ")
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
			m_task.emplace_back(" [DEBUG] ");
		}
		else
		{
			m_task.back().append(" [DEBUG] ");
		}
		m_cond.notify_one();
#else
		// 舍弃流
#define LogErr (LogCpp::getGlobalLogCpp()->_spaceFunction)
#endif // LOG_CPP_LEVEL
		return *this;
	}

	/**
	* @brief 全局日志对象指针
	*
	*/
	static LogCpp *getGlobalLogCpp()
	{
		static LogCpp *g_logCpp = new LogCpp();
		return g_logCpp;
	}
};

#endif // !_LOG_CPP_HPP_


示例

#define LOG_CPP_LEVEL 10

#include "./logcpp.hpp"
#include <iostream>
#include <chrono>
#include <string>
#include <sstream>

int main() {
    LogCpp::setGlobalPath(".\\log.txt");
    while (true) {
        LogErr << "卧槽卧槽";
        LogInfo << "卧槽卧槽";
        LogDebug << "卧槽卧槽";
    }
    return 0;
}

地址

好的,以下是一个使用Canvas实现樱花飘落的页面,代码中有注释解释每个部分的作用: ```html <!DOCTYPE html> <html> <head> <title>樱花飘落页面</title> <style> body { margin: 0; padding: 0; background-color: #f9d2e9; } </style> </head> <body> <canvas id="canvas"></canvas> <script> // 获取canvas元素 var canvas = document.getElementById("canvas"); // 设置canvas大小为屏幕大小 canvas.width = window.innerWidth; canvas.height = window.innerHeight; // 获取画布上下文 var ctx = canvas.getContext("2d"); // 定义樱花花瓣数组 var sakuras = []; // 定义樱花花瓣类 function Sakura(x, y, r, vx, vy) { this.x = x; this.y = y; this.r = r; this.vx = vx; this.vy = vy; this.alpha = 1; this.color = "#FFC0CB"; } // 定义樱花花瓣渲染方法 Sakura.prototype.render = function() { ctx.beginPath(); ctx.globalAlpha = this.alpha; ctx.fillStyle = this.color; ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2); ctx.fill(); } // 定义樱花花瓣更新方法 Sakura.prototype.update = function() { // 计算新位置 this.x += this.vx; this.y += this.vy; // 计算新透明度 this.alpha -= 0.01; // 如果透明度小于等于0,就从数组中删除 if (this.alpha <= 0) { sakuras.splice(sakuras.indexOf(this), 1); } } // 定义樱花花瓣生成函数 function createSakura() { // 随机生成樱花花瓣的位置、大小和速度 var x = Math.random() * canvas.width; var y = -50; var r = Math.random() * 10 + 10; var vx = Math.random() * 2 - 1; var vy = Math.random() * 2 + 1; // 创建新的樱花花瓣对象并添加到数组中 var sakura = new Sakura(x, y, r, vx, vy); sakuras.push(sakura); } // 定义动画函数 function animate() { // 清空画布 ctx.clearRect(0, 0, canvas.width, canvas.height); // 每隔一段时间生成新的樱花花瓣 if (Math.random() > 0.9) { createSakura(); } // 遍历每个樱花花瓣,更新位置并渲染 for (var i = 0; i < sakuras.length; i++) { var sakura = sakuras[i]; sakura.update(); sakura.render(); } // 循环调用动画函数 requestAnimationFrame(animate); } // 启动动画函数 animate(); </script> </body> </html> ``` 这个页面使用Canvas实现了樱花花瓣的飘落效果,每隔一段时间会随机生成新的花瓣,并使用透明度和速度控制花瓣的位置和渲染。通过循环调用动画函数,使得花瓣会不断地飘落,营造出樱花飞舞的效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值