提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
近年来,蓝桥杯竞赛的题目设计逐渐向思维深度和创新性倾斜,传统“刷题式”备考的效果正在减弱。面对这一趋势,借鉴他人的解题思路和分析方法,往往能帮助参赛者更快抓住问题核心,实现事半功倍。
本次分享聚焦第12届蓝桥杯的这道典型题目,这些题目有一定难度。通过拆解题目背景、关键思路和优化技巧,希望能为读者提供一种可参考的思考范式。需说明的是,所有观点仅为个人经验总结,未必完全适用所有场景,欢迎交流指正。
(注:若需具体题目解析或进一步讨论,可随时补充细节。)
题目
配置Cubemx:
主要的配置如下:
串口配置:
打开串口中断:
题目难点
我认为本届题目的难点有2个
1、对于时间的处理,时间的是否合理,怎么计算时间
2、出库入库的存储及处理
代码实现
对于第一点
恰当地用c语言的库函数有时候可以很高效的解决问题和减少出问题的概论,在比赛短短的5小时来说,还是很关键的。
我首先介绍一个库函数
#include"time.h"
这个库函数里面有很多处理时间的封装好的函数。
本次工程用到了“time_t mktime(struct tm *timeptr);”
简单说就是计算当前时间距离1970-01-01的秒数;
times.tm_year = T.year + 2000-1900; // 2000+年偏移
times.tm_mon = T.mon - 1; // 月份从0开始
times.tm_mday = T.day;
times.tm_hour = T.hour;
times.tm_min = T.min;
times.tm_sec = T.sec;
now_car.sec_all = mktime(×); // 生成时间戳```
然后我写了很简单的一个判断年月日是否合理的代码
void mon_pd() {
// 月份校验(1-12)
if (T.mon < 1 || T.mon > 12) error = 1;
// 计算当月最大天数(考虑闰年)
int day_max = 31;
if (T.mon == 2) {
int is_leap = ((T.year % 4 == 0) && (T.year % 100 != 0)) || (T.year % 400 == 0);
day_max = is_leap ? 29 : 28;
} else if (T.mon == 4 || T.mon == 6 || T.mon == 9 || T.mon == 11) {
day_max = 30;
}
// 校验时间合法性
if (T.day > day_max || T.hour > 23 || T.min > 59 || T.sec > 59) error = 1;
}
用了两次三目运算符:
简单说就是前面为1的话,就选前面那个的值,否在就选后面的值
1、首先判断月份是否在1~12月
2、当是2月时,判断是否闰年,来确定2月的天数
3、计算其他月份的时间的天数
4、得到的此月份的最大天数
对于第二点
写两个函数,一个入库函数,一个出库函数
入库函数
void park_in() {
uint8_t id_yn = 0;//判断车牌有无,id yes or no
if (now_car.cv_yn != 0) {
// 检查车牌是否已存在
for (uint8_t i = 0; i < 8; i++) {
if (strcmp(all_car[i].id, now_car.id) == 0) {
id_yn = 1;
break;
}
}
// 分配空闲车位
if (!id_yn) {
for (uint8_t i = 0; i < 8; i++) {
if (all_car[i].cv_yn == 0) {
all_car[i] = now_car; // 复制车辆信息
if (now_car.cv_yn == 1) ct.cn_num++;
else if (now_car.cv_yn == 2) ct.vn_num++;
in_out_flag = 1; // 标记进场成功
break;
}
}
}
}
}
出库函数及时间和费用的计算
void park_out()
{
uint8_t id_yn=0; // 车辆存在标志:0=未找到,1=已找到
uint8_t place=0; // 存储找到车辆的位置索引(0-7)
uint32_t cha; // 存储停车时长差值(秒)
// 检查当前车辆状态是否有效(cv_yn=1 普通车,2=VIP车)
if (now_car.cv_yn != 0)
{
// 遍历停车场所有车位(共8个)
for (uint8_t i = 0; i < 8; i++)
{
// 比较当前车辆ID与车位中的车辆ID
if (strcmp(all_car[i].id, now_car.id) == 0)
{
id_yn=1; // 标记车辆已找到
place=i; // 记录车辆所在位置
break; // 找到后立即跳出循环
}
}
// 如果找到车辆
if(id_yn==1)
{
// 计算停车时长(当前时间戳 - 入场时间戳)[1](@ref)
cha = now_car.sec_all - all_car[place].sec_all; // 计算完整小时数(秒转小时)
all_car[place].hour_all = cha / 3600; // 处理不足1小时的部分(向上取整)
if(cha % 3600 != 0 && cha > 0) all_car[place].hour_all++; // 不足1小时按1小时计费
if(now_car.cv_yn == 1)
{
money = ct.cn_vlaue * all_car[place].hour_all; // 计算费用
ct.cn_num--; // 减少普通车计数
// 格式化账单信息:类型+车牌+时长+金额
sprintf(tx, "CNBR:%4s:%d:%0.2f\r\n",
all_car[place].id,
all_car[place].hour_all,
money);
// 通过串口发送账单(超时50ms)[6,7](@ref)
HAL_UART_Transmit(&huart1, (uint8_t*)tx, strlen(tx), 50);
}
else if(now_car.cv_yn == 2)
{
money = ct.vn_vlaue * all_car[place].hour_all; // 计算费用
ct.vn_num--; // 减少VIP车计数
// 格式化账单信息
sprintf(tx, "VNBR:%4s:%d:%0.2f\r\n",
all_car[place].id,
all_car[place].hour_all,
money);
// 通过串口发送账单
HAL_UART_Transmit(&huart1, (uint8_t*)tx, strlen(tx), 50);
}
// 释放车位
all_car[place].cv_yn = 0; // 清除车辆类型标记
all_car[place].hour_all = all_car[place].sec_all = 0; // 重置时长计数器
memset(&all_car[place].id, '\0', 5); // 清空车牌号(安全擦除)[2]
}
}
}
总结
把这两个难点解决了,其他的就很好解决啦。
此文仅代表个人愚见。
蓝桥杯12届完整工程链接