PHP定时任务框架taskPHP3.0的学习记录1(TaskPHP、执行任务类的实操代码实例)

TaskPHP是一个基于PHP的定时任务框架,它提供了一个简单、灵活且易于使用的解决方案,用于在PHP环境中执行定时任务。下面是对TaskPHP框架的简要介绍:

  1. 简单易用:TaskPHP的设计目标是让定时任务的创建和管理变得简单。通过简单的配置和编写任务代码,即可轻松实现定时任务的执行。
  2. 高性能:TaskPHP采用高效的任务调度算法,确保任务能够按照预定的时间准确执行。同时,它还支持并发执行多个任务,提高了任务的执行效率。
  3. 灵活配置:TaskPHP允许用户通过配置文件或代码来定义任务的执行时间、执行间隔、执行次数等参数。用户可以根据自己的需求灵活配置任务。
  4. 可扩展性:TaskPHP框架具有良好的扩展性,用户可以根据自己的需求添加自定义的任务类型或扩展功能。此外,它还支持与其他PHP框架或库进行集成,方便用户在现有项目中使用。
  5. 日志记录:TaskPHP提供了日志记录功能,可以记录任务的执行过程、执行结果以及错误信息等。这有助于用户监控任务的执行情况,及时发现问题并进行处理。
  6. 任务管理:框架提供了任务管理的功能,用户可以查看当前正在执行的任务、已完成的任务以及任务执行的历史记录。这有助于用户对任务进行监控和管理。

TaskPHP是一个功能强大、易于使用的PHP定时任务框架,适用于各种需要定时执行任务的场景。无论是简单的定时发送邮件、定时更新数据,还是复杂的定时爬虫、定时数据分析等任务,TaskPHP都能提供有效的解决方案。

关键环境感知任务记录

<?phpnamespace cron;use taskphp\Utils;require 'taskDb.php';class Service2
{/** 关键环境安全-定时任务* $service_id,定时任务服务路由ID* */public static function getTask($service_id){global $CONF, $serviceArr;$CONF = require '../conf/config.php';require '../conf/config.service.php';$serviceArr = getByServiceId($lock_service, $service_id);Utils::log('Task-ID: ' . $service_id);//数据信息$school_id = $serviceArr['school_id'];$school_type = $serviceArr['school_type'];$school_attribute = $serviceArr['school_attribute'];$school_short_name = $serviceArr['school_short_name'];$service_group = $serviceArr['service_group'];$service_protocol = $serviceArr['service_protocol'];$service_url = $serviceArr['service_url'];$url = $service_protocol . $service_url . '/service/page/sensor/simple.json';$dataPramas = ["group_id" => $service_group];$res = curlIotOnlyAPI($url, '1', '1000', $CONF['iot_token'], $dataPramas);//Utils::log('Task-content: ' . $res);$reArr = json_decode($res, true);if ($reArr && $reArr["data"] && $reArr["data"]["data"] && $reArr["data"]["data"][0]) {$keyData = $reArr["data"]["data"];$environment_area = $reArr["data"]["data"][0]['device'];//插入数据库;Utils::db()->table("environment")->ifInsert(array('task_code' => encodeId($school_id . '-' . $service_id),'service_id' => $service_id,'school_id' => $school_id,'school_type' => $school_type,'school_attribute' => $school_attribute,'school_short_name' => $school_short_name,'environment_area' => $environment_area,'environment_temperature' => getSDataByPropertyType($keyData, '温度'),'environment_temperature_state' => getStatusBySensorStatus($keyData, '温度'),'environment_humidity' => getSDataByPropertyType($keyData, '湿度'),'environment_humidity_state' => getStatusBySensorStatus($keyData, '湿度'),'environment_air' => getSDataByPropertyType($keyData, '空质'),'environment_air_state' => getStatusBySensorStatus($keyData, '空质'),'environment_time' => time()),array('service_id' => $service_id,'school_id' => $school_id,'school_type' => $school_type,'school_attribute' => $school_attribute,'school_short_name' => $school_short_name,'environment_area' => $environment_area,'environment_temperature' => getSDataByPropertyType($keyData, '温度'),'environment_temperature_state' => getStatusBySensorStatus($keyData, '温度'),'environment_humidity' => getSDataByPropertyType($keyData, '湿度'),'environment_humidity_state' => getStatusBySensorStatus($keyData, '湿度'),'environment_air' => getSDataByPropertyType($keyData, '空质'),'environment_air_state' => getStatusBySensorStatus($keyData, '空质'),'environment_time' => time()));//系统日志Utils::db()->table("task_log")->add(array("school_short_name" => $school_short_name,"task_name" => '关键环境安全',"task_status" => '服务路由ID(' . $service_id . ')API组ID(' . $service_group . ')-数据更新成功,STATUS:OK',"task_time" => time()));} else {//系统日志Utils::db()->table("task_log")->add(array("school_short_name" => $school_short_name,"task_name" => '关键环境安全',"task_status" => 'API组ID:' . $service_group . '接口出错,无法爬取数据,STATUS:Fail',"task_time" => time()));die();}//返回数据;return true;}
}

用电计量管理任务记录

<?phpnamespace cron;use taskphp\Utils;require 'taskDb.php';class Service3
{/** 用电计量管理-定时任务* $service_id,定时任务服务路由ID* */public static function getTask($service_id){global $CONF, $serviceArr;$CONF = require '../conf/config.php';require '../conf/config.service.php';$serviceArr = getByServiceId($lock_service, $service_id);Utils::log('Task-ID: ' . $service_id);//数据信息$school_id = $serviceArr['school_id'];$school_type = $serviceArr['school_type'];$school_attribute = $serviceArr['school_attribute'];$school_short_name = $serviceArr['school_short_name'];$service_group = $serviceArr['service_group'];$service_protocol = $serviceArr['service_protocol'];$service_url = $serviceArr['service_url'];$url = $service_protocol . $service_url . '/service/page/sensor/calc/data.json';$dataPramas = ["group_id" => $service_group, 'propertyTypeVal' => '电量'];$res = curlIotOnlyAPI($url, '1', '1000', $CONF['iot_token'], $dataPramas);//Utils::log('Task-content: ' . $res);$reArr = json_decode($res, true);if ($reArr && $reArr["data"] && $reArr["data"]["data"] && $reArr["data"]["data"][0]) {$powerData = $reArr["data"]["data"][0]["odata"];$MonthsArr = generatePastMonths(13);//月份$powerArr = [formatNumber($powerData['prev_0_month_val_diff']),formatNumber($powerData['prev_1_month_val_diff']),formatNumber($powerData['prev_2_month_val_diff']),formatNumber($powerData['prev_3_month_val_diff']),formatNumber($powerData['prev_4_month_val_diff']),formatNumber($powerData['prev_5_month_val_diff']),formatNumber($powerData['prev_6_month_val_diff']),formatNumber($powerData['prev_7_month_val_diff']),formatNumber($powerData['prev_8_month_val_diff']),formatNumber($powerData['prev_9_month_val_diff']),formatNumber($powerData['prev_10_month_val_diff']),formatNumber($powerData['prev_11_month_val_diff']),formatNumber($powerData['prev_12_month_val_diff'])];//对应月份的数据//插入数据库;/*  Utils::db()->table("electricity")->ifInsert(array('school_id' => $school_id,'school_type' => $school_type,'school_attribute' => $school_attribute,'school_short_name' => $school_short_name,'electricity_month' => $MonthsArr[0],'electricity_norm' => $powerArr[0],'electricity_time' => time()),array('school_type' => $school_type,'school_attribute' => $school_attribute,'school_short_name' => $school_short_name,'electricity_norm' => $powerArr[0],'electricity_time' => time()));*/for ($i = 0; $i < count($MonthsArr); $i++) {$row_sec = Utils::db()->table("electricity")->where(array('school_id' => $school_id, 'electricity_month' => $MonthsArr[$i]))->limit(1)->order("school_id DESC")->select();if (!$row_sec) {//插入数据Utils::db()->table("electricity")->add(array('school_id' => $school_id,'service_id' => $service_id,'school_type' => $school_type,'school_attribute' => $school_attribute,'school_short_name' => $school_short_name,'electricity_month' => $MonthsArr[$i],'electricity_norm' => $powerArr[$i],'electricity_time' => time()));} else {//更新数据Utils::db()->table("electricity")->where(array('school_id' => $school_id, 'electricity_month' => $MonthsArr[$i]))->update(array('service_id' => $service_id,'school_type' => $school_type,'school_attribute' => $school_attribute,'school_short_name' => $school_short_name,'electricity_norm' => $powerArr[$i],'electricity_time' => time()));}}//系统日志Utils::db()->table("task_log")->add(array("school_short_name" => $school_short_name,"task_name" => '用电计量管理',"task_status" => '服务路由ID(' . $service_id . ')API组ID(' . $service_group . ')-数据更新成功,STATUS:OK',"task_time" => time()));} else {//系统日志Utils::db()->table("task_log")->add(array("school_short_name" => $school_short_name,"task_name" => '用电计量管理',"task_status" => 'API组ID:' . $service_group . '接口出错,无法爬取数据,STATUS:Fail',"task_time" => time()));die();}//返回数据;return true;}
}

用水计量管理任务记录

<?phpnamespace cron;use taskphp\Utils;require 'taskDb.php';class Service4
{/** 用水计量管理-定时任务* $service_id,定时任务服务路由ID* */public static function getTask($service_id){global $CONF, $serviceArr;$CONF = require '../conf/config.php';require '../conf/config.service.php';$serviceArr = getByServiceId($lock_service, $service_id);Utils::log('Task-ID: ' . $service_id);//数据信息$school_id = $serviceArr['school_id'];$school_type = $serviceArr['school_type'];$school_attribute = $serviceArr['school_attribute'];$school_short_name = $serviceArr['school_short_name'];$service_group = $serviceArr['service_group'];$service_protocol = $serviceArr['service_protocol'];$service_url = $serviceArr['service_url'];$url = $service_protocol . $service_url . '/service/page/sensor/calc/data.json';$dataPramas = ["group_id" => $service_group, 'propertyTypeVal' => '总流量'];$res = curlIotOnlyAPI($url, '1', '1000', $CONF['iot_token'], $dataPramas);//Utils::log('Task-content: ' . $res);$reArr = json_decode($res, true);if ($reArr && $reArr["data"] && $reArr["data"]["data"] && $reArr["data"]["data"][0]) {$powerData = $reArr["data"]["data"][0]["odata"];$MonthsArr = generatePastMonths(13);//月份$powerArr = [formatNumber($powerData['prev_0_month_val_diff']),formatNumber($powerData['prev_1_month_val_diff']),formatNumber($powerData['prev_2_month_val_diff']),formatNumber($powerData['prev_3_month_val_diff']),formatNumber($powerData['prev_4_month_val_diff']),formatNumber($powerData['prev_5_month_val_diff']),formatNumber($powerData['prev_6_month_val_diff']),formatNumber($powerData['prev_7_month_val_diff']),formatNumber($powerData['prev_8_month_val_diff']),formatNumber($powerData['prev_9_month_val_diff']),formatNumber($powerData['prev_10_month_val_diff']),formatNumber($powerData['prev_11_month_val_diff']),formatNumber($powerData['prev_12_month_val_diff'])];//插入数据库;for ($i = 0; $i < count($MonthsArr); $i++) {$row_sec = Utils::db()->table("water")->where(array('school_id' => $school_id, 'water_month' => $MonthsArr[$i]))->limit(1)->order("school_id DESC")->select();if (!$row_sec) {//插入数据Utils::db()->table("water")->add(array('school_id' => $school_id,'service_id' => $service_id,'school_type' => $school_type,'school_attribute' => $school_attribute,'school_short_name' => $school_short_name,'water_month' => $MonthsArr[$i],'water_norm' => $powerArr[$i],'water_time' => time()));} else {//更新数据Utils::db()->table("water")->where(array('school_id' => $school_id, 'water_month' => $MonthsArr[$i]))->update(array('service_id' => $service_id,'school_type' => $school_type,'school_attribute' => $school_attribute,'school_short_name' => $school_short_name,'water_norm' => $powerArr[$i],'water_time' => time()));}}//系统日志Utils::db()->table("task_log")->add(array("school_short_name" => $school_short_name,"task_name" => '用水计量管理',"task_status" => '服务路由ID(' . $service_id . ')API组ID(' . $service_group . ')-数据更新成功,STATUS:OK',"task_time" => time()));} else {//系统日志Utils::db()->table("task_log")->add(array("school_short_name" => $school_short_name,"task_name" => '用水计量管理',"task_status" => 'API组ID:' . $service_group . '接口出错,无法爬取数据,STATUS:Fail',"task_time" => time()));die();}//返回数据;return true;}
}

记录日志

使用第三方爬中仅记录启动和结束任务日志

[2024-03-29 20:22:54.83456200][DEBUG]:distribute_listen daemon pid:383131 Start
[2024-03-29 20:22:55.83205600][DEBUG]:worker_listen daemon pid:383134 Start
[2024-03-29 20:22:56.83395000][DEBUG]:worker_listen daemon pid:383135 Start
[2024-03-29 20:22:57.83637100][DEBUG]:worker_listen daemon pid:383136 Start
[2024-03-29 20:22:58.83940500][DEBUG]:worker_listen daemon pid:383137 Start
[2024-03-29 20:22:59.83934000][DEBUG]:worker_listen daemon pid:383138 Start
[2024-03-29 20:23:00.84222100][DEBUG]:worker_listen daemon pid:383139 Start
[2024-03-29 20:23:01.84334700][DEBUG]:worker_listen daemon pid:383140 Start
[2024-03-29 20:23:02.84479600][DEBUG]:worker_listen daemon pid:383141 Start
[2024-03-29 20:30:01.04360000][DEBUG]:cron\Task14::run [--START--]
[2024-03-29 20:30:01.04501700][DEBUG]:Service-ID: 31
[2024-03-29 20:30:07.56411000][DEBUG]:cron\Task14::run [--END--][RunTime:6.520488s]
[2024-03-29 20:31:01.07364600][DEBUG]:cron\Task15::run [--START--]
[2024-03-29 20:31:01.07523800][DEBUG]:Service-ID: 30
[2024-03-29 20:31:01.85611800][DEBUG]:cron\Task15::run [--END--][RunTime:0.782444s]
[2024-03-29 20:32:01.12884500][DEBUG]:cron\Task6::run [--START--]
[2024-03-29 20:32:01.13076100][DEBUG]:Service-ID: 34
[2024-03-29 20:32:01.69706000][DEBUG]:cron\Task6::run [--END--][RunTime:0.568220s]

taskPHP自带Utils工具,会产生具体的日志记录

[2024-03-28 00:03:01.41235800][DEBUG]:cron\Task14::run [--START--]
[2024-03-28 00:03:01.41251000][DEBUG]:Task-ID: 31
[2024-03-28 00:03:07.83297000][DEBUG]:cron\Task14::run [--END--][RunTime:6.420764s]
[2024-03-28 00:05:00.89040200][DEBUG]:cron\Task10::run [--START--]
[2024-03-28 00:05:00.89097900][DEBUG]:Task-ID: 35
[2024-03-28 00:05:01.04386100][DEBUG]:cron\Task6::run [--START--]
[2024-03-28 00:05:01.04441500][DEBUG]:Task-ID: 34
[2024-03-28 00:05:01.42001300][DEBUG]:SQL:DESC po_environment[bind_value:null][RunTime:0.059952s]
[2024-03-28 00:05:01.49280500][DEBUG]:SQL:INSERT INTO `po_environment` SET `task_code`=:task_code,`service_id`=:service_id,`school_id`=:school_id,`school_type`=:school_type,`school_attribute`=:school_attribute,`school_short_name`=:school_short_name,`environment_area`=:environment_area,`environment_temperature`=:environment_temperature,`environment_temperature_state`=:environment_temperature_state,`environment_humidity`=:environment_humidity,`environment_humidity_state`=:environment_humidity_state,`environment_air`=:environment_air,`environment_air_state`=:environment_air_state,`environment_time`=:environment_time ON DUPLICATE KEY UPDATE `service_id`=:service_id_1,`school_id`=:school_id_2,`school_type`=:school_type_3,`school_attribute`=:school_attribute_4,`school_short_name`=:school_short_name_5,`environment_area`=:environment_area_6,`environment_temperature`=:environment_temperature_7,`environment_temperature_state`=:environment_temperature_state_8,`environment_humidity`=:environment_humidity_9,`environment_humidity_state`=:environment_humidity_state_10,`environment_air`=:environment_air_11,`environment_air_state`=:environment_air_state_12,`environment_time`=:environment_time_13[bind_value:null][RunTime:0.072542s]

@漏刻有时

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

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

相关文章

Learning To Count Everything

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;学习数一切东西1、研究背景2、提出方法3、模块详细3.1、多尺度特征提取模块3.2、密度预测模块 4、损失函数5、性能对比6、贡献 二…

城管智慧执法系统源码,基于微服务+java+springboot+vue开发

城管智慧执法系统源码&#xff0c;基于微服务javaspringbootvue开发 城管智慧执法系统源码有演示&#xff0c;自主研发&#xff0c;功能完善&#xff0c;正版授权&#xff0c;可商用上项目。 一套数字化的城管综合执法办案系统源码&#xff0c;提供了案件在线办理、当事人信用…

Platypus 一种集中式的央行数字货币方案

集中式的CBDC&#xff0c;混合使用账户模型和UTXO模型。 角色分类 中央银行&#xff1a;发行货币&#xff0c;交易验证&#xff0c;公开交易日志&#xff0c;防止双花。 不是完全受信任的&#xff0c;假定为会遵守监管要求&#xff0c;但可能会破坏交易隐私&#xff0c;即获…

正弦实时数据库(SinRTDB)的使用(9)-有损压缩

前文已经将正弦实时数据库的使用进行了介绍&#xff0c;需要了解的可以先看下面的博客&#xff1a; 正弦实时数据库(SinRTDB)的安装 正弦实时数据库(SinRTDB)的使用(1)-使用数据发生器写入数据 正弦实时数据库(SinRTDB)的使用(2)-接入OPC DA的数据 正弦实时数据库(SinRTDB)…

Kafka学习之:mac 上基础使用 python 来使用 kafka 的生产者和消费者进行数据处理

文章目录 前提python 环境配置Kafka 生产消费者模型生产者 producer检查当前存在的所有 topic / 是否自动创建 topic为什么 producer 要通过 key, value 来发布数据键&#xff08;Key&#xff09;值&#xff08;Value&#xff09; 消费者 consumerconsumer 得到的 message 有哪…

MES系统怎么解决车间生产调度难的问题?

MES系统三个层次 1、MES决定了生产什么&#xff0c;何时生产&#xff0c;也就是说它使公司保证按照订单规定日期交付准确的产品&#xff1b; 2、MES决定谁通过什么方式&#xff08;流程&#xff09;生产&#xff0c;即通过优化资源配置&#xff0c;最有效运用资源&#xff1b; …

关于SVG格式图片实现室内地图

SVG格式图片 可缩放矢量图形(Scalable Vector Graphics,SVG)基于 XML 标记语言,用于描述二维的矢量图形。 作为一个基于文本的开放网络标准,SVG 能够优雅而简洁地渲染不同大小的图形,并和 CSS、DOM、JavaScript 和 SMIL 等其他网络标准无缝衔接。本质上,SVG 相对于图像…

react学习总结(二)之案例分享

一.项目框架的搭建 1./src/pages下建不同的页面Header.jsx&#xff0c;About.jsx&#xff0c;Home.jsx&#xff0c; Message.jsx&#xff0c;News.jsx&#xff0c;Detail.jsx Header.jsx import React from react import { useNavigate } from react-router-domexport defau…

C++多线程:线程的创建、join、detach、joinable方法(二)

1、线程的开始与结束 程序运行起来&#xff0c;生成一个进程&#xff0c;该进程所持有的主线程开始自动运行&#xff0c;main主线程运行完所有的代码从main函数中返回表示整个进程运行完毕&#xff0c;标志着主线程和进程的死亡&#xff0c;等待操作系统回收资源&#xff0c;因…

nginx如何清理页面缓存

在 Nginx 中&#xff0c;清理页面缓存通常涉及配置缓存头以控制缓存行为&#xff0c;或者使用外部工具或机制来清除缓存。以下是一些建议来管理和清理 Nginx 的页面缓存&#xff1a; 配置缓存头&#xff1a; Nginx 本身不直接提供缓存机制&#xff0c;但可以通过配置 proxy_cac…

安全算法 - 国密算法

国密算法是中国自主研发的密码算法体系&#xff0c;包括对称加密算法、非对称加密算法和哈希算法。其中&#xff0c;国密算法采用SM4作为对称加密算法&#xff0c;SM2作为非对称加密算法&#xff0c;以及SM3作为哈希算法。国密算法在信息安全领域具有重要意义和广泛应用&#x…

Cocos Creator 常见问题记录

目录 问题1、精灵图九宫格&#xff0c;角度不拉伸 问题2、BlockInputEvents 防止透屏 问题1、精灵图九宫格&#xff0c;角度不拉伸 点击编辑&#xff0c;拖拽到可变区域 问题2、BlockInputEvents 防止透屏

【独立开发前线】Vol.26 【独立开发产品】吉光卡片-让你的文字变得酷炫起来

今天给大家分享一下 独立开发前线 社区成员张小吉 的作品 吉光卡片&#xff1b; 这是一款iOS的APP&#xff0c;下载&#xff1a;吉光卡片&#xff0c;主要功能是帮你制作酷炫的文字卡片&#xff0c;用精美的卡片让你的文字生动起来。 展示效果如下&#xff1a; 你可以用它制作…

【公示】2023年度青岛市级科技企业孵化器拟认定名单

根据《青岛市科技企业孵化器管理办法》&#xff08;青科规〔2023〕1号&#xff09;&#xff08;以下简称《管理办法》&#xff09;、《关于开展2023年度市级科技企业孵化器认定申报工作的通知》&#xff0c;经申报受理、区市推荐、形式审查、专家评审及现场核查等程序&#xff…

为何keil编译信息显示data使用量不是整数

在使用Keil软件进行嵌入式系统开发时&#xff0c;编译后显示的数据使用量&#xff08;Data Usage&#xff09;可能会以小数形式显示。这种情况通常是由以下几个原因造成的&#xff1a; 1.内存对齐&#xff1a;为了提高内存访问效率&#xff0c;编译器会对数据进行对齐处理。例…

【笔记】动⼿学深度学习(花书)|| Aston Zhang Mu Li Zachary C. LiptonAlexander J. Smola

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 前言 第一章 深度学习简介 第二章 P 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言本书…

BasicVSR++模型转JIT并用c++libtorch推理

BasicVSR模型转JIT并用clibtorch推理 文章目录 BasicVSR模型转JIT并用clibtorch推理安装BasicVSR 环境1.下载源码2. 新建一个conda环境3. 安装pytorch4. 安装 mim 和 mmcv-full5. 安装 mmedit6. 下载模型文件7. 测试一下能否正常运行 转换为JIT模型用c libtorch推理效果 安装Ba…

使用docker 安装oracle 11g 挂载数据目录并修改SID centos-7

建议&#xff1a;建议使用其它系统去装ubuntu或Rocky&#xff08;因为centos已经停止维护&#xff09; 1、安装docker 这里就不细写了&#xff0c;可以查看清华镜像源或者阿里镜像源 清华&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/help/docker-ce/ 阿里&#xff1a;ht…

2434. 使用机器人打印字典序最小的字符串

点击跳转题目 本题学到两点&#xff1a; 1.初始化数组&#xff0c;全部为0的简单写法。之前都是 int arr[26]; memset(arr,0,sizeof(arr));2.if条件中的&&部分左右顺序不能颠倒。颠倒报错&#xff0c;之前一直没重视。 思路&#xff1a; 遍历s&#xff0c;push当前字…

[c++]类和对象常见题目详解

本专栏内容为&#xff1a;C学习专栏&#xff0c;分为初阶和进阶两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握C。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&…