[2-02-02].第59节:功能函数 - 函数基础

服务器端操作学习大纲


一、函数基础

需求场景

  • 在shell脚本的编写过程中,我们经常会遇到一些功能代码场景:多条命令组合在一起,实现一个特定的功能场景逻辑、一些命令在脚本内部的多个位置频繁出现。在这些场景的代码量往往不多,但是频繁使用的话,会导致脚本的整体逻辑脉络比较松散和框架散乱,所以我们需要一种脚本逻辑,不仅仅能够满足松散代码的功能目的,还能精简重复的代码。函数就是来满足这种场景的解决方案 – 而函数,也是所谓的面向对象编程的一种表现样式

什么是函数:

  • 所谓的函数,本质上就是一段能够满足特定功能的代码块。一旦定义好函数代码后,我们就可以在脚本的很多位置随意的使用。
    定义功能代码块的动作叫函数定义,使用函数代码的动作叫函数调用

函数的优势:

  • 代码模块化,调用方便,节省内存
  • 代码模块化,代码量少,排错简单
  • 代码模块化,可以改变代码的执行顺序

二、定义简单函数:

2.1.基本语法

  • 样式1:定义函数:
    function 函数名{		函数体				}	
  • 样式2:简约格式
函数名() {		函数体				
}

2.2.注意事项:

  • function 的作用和 () 的作用是一样的,都是定义一个函数
  • 函数的名称是自定义的,而且在脚本范围内必须唯一
  • 函数体内是普通的能够正常执行的命令,命令的执行流程符合顺序逻辑

2.3.函数调用:

  • 函数名
  • 注意:
    • 函数名出现在任何位置,就代表在该位置调用函数内代码块的执行
    • 函数名一般在函数定义后调用,否则的话会发生报错

2.4.简单实践:

实践1-标准函数的实践

  • 1.简单函数的定义与调用:
[root@localhost ~]# cat function_simple_test.sh
#!/bin/bash
# 定制一个函数,提示脚本的使用方式
function Usage {echo -e "\e[31m脚本的使用帮助信息: xxx\e[0m"
}# 定制脚本使用逻辑
if [ $# -eq 1 ]
thenecho "您输入的脚本参数是1个"
elseUsage
fi
脚本执行效果
[root@localhost ~]# /bin/bash function_simple_test.sh
脚本的使用帮助信息: xxx
[root@localhost ~]# /bin/bash function_simple_test.sh aa
您输入的脚本参数是1个
[root@localhost ~]# /bin/bash function_simple_test.sh aa bb
脚本的使用帮助信息: xxx

实践2-变种函数的实践

[root@localhost ~]# cat function_simple_test2.sh
#!/bin/bash
# 功能:简单函数的定义和调用# 定制一个函数,提示脚本的使用方式
Usage() {echo -e "\e[31m脚本的使用帮助信息: xxx\e[0m"
}# 定制脚本使用逻辑
if [ $# -eq 1 ]
thenecho "您输入的脚本参数是1个"
elseUsage
fi
脚本执行效果
[root@localhost ~]# /bin/bash function_simple_test2.sh
脚本的使用帮助信息: xxx
[root@localhost ~]# /bin/bash function_simple_test2.sh aa
您输入的脚本参数是1个
[root@localhost ~]# /bin/bash function_simple_test2.sh aa bb
脚本的使用帮助信息: xxx

实践3-函数的调用顺序和名称唯一实践

  • 功能:简单函数的定义和调用
[root@localhost ~]# cat function_simple_test3.sh
#!/bin/bash# 定制一个函数,提示脚本的使用方式
Usage() {echo -e "\e[31m脚本的使用帮助信息: xxx\e[0m"
}
echo "第一次调用效果: "
Usage# 定制同名的函数,提示脚本的使用方式
Usage() {echo -e "\e[31m脚本的使用帮助信息-------: xxx\e[0m"
}# 定制脚本使用逻辑
if [ $# -eq 1 ]
then# 调用一个后面才会生成的函数func
elseUsage
fi# 定制一个函数
func() {echo "您输入的脚本参数是1个"
}
  • 2.结果:
[root@localhost ~]# /bin/bash function_simple_test3.sh
第一次调用效果:
脚本的使用帮助信息: xxx
脚本的使用帮助信息-------: xxx
[root@localhost ~]# /bin/bash function_simple_test3.sh a
第一次调用效果:
脚本的使用帮助信息: xxx
function_simple_test3.sh:行18: func: 未找到命令
  • 3.总结:
    • 函数名称重复的话,会导致同名函数被覆盖
    • 函数在没有定义前调用的话,会导致异常报错

三、定义传参函数

3.1.简介

  • 简单的函数定义和调用的实践,我们只能实现固定内容的输出,不具有灵活性。其实函数作为shell脚本内部的小脚本也支持脚本传参的一系列能力

3.2.定义传参函数:

a.语法:

函数名() {		函数体	${变量名}			}

b.注意:

  • 注意:函数体内通过 ${变量名} 来实现函数体的功能通用性

3.3.调用传参函数:

a.语法:

	函数名 参数			

b.注意:

  • 函数在调用的时候,接收一些参数并传输到函数体内部

3.4.案例:

实践1-传参函数实践

  • 传参函数定义和调用
[root@localhost ~]# cat function_arg_input.sh
#!/bin/bash
# 功能:传参函数定义和调用# 定制数据运算的函数
add_func() {echo $(( $1 + $2 ))
}
sub_func() {echo $(( $1 - $2 ))
}
mul_func() {echo $(( $1 * $2 ))
}
div_func() {echo $(( $1 / $2 ))
}echo -n "4+3="; add_func 4 3
echo -n "4-3="; sub_func 4 3
echo -n "4*3="; mul_func 4 3
echo -n "4/3="; div_func 4 3
  • 2.脚本执行效果
[root@localhost ~]# /bin/bash function_arg_input.sh
4+3=7
4-3=1
4*3=12
4/3=1

3.5.脚本传参

a.简介

  • 传参函数定义和调用的实践,实现了函数层面的灵活性,但是它受到函数调用本身的参数限制。往往这些参数我们需要在脚本执行的时候传递进去,从而实现脚本功能的灵活性。

b.基本语法

  • 定义函数:
    函数名() {		函数体	${函数参数}			}
  • 调用函数:函数名 ${脚本参数}
  • 脚本执行:/bin/bash /path/to/scripts.sh arg

c.注意:

  • 由于脚本内部调用脚本参数和函数体内调用函数参数都遵循位置变量的使用,所以,一般情况下,我们会借助于临时变量的方式接收各自的参数,从而避免引起误会

d.实践1-脚本传参函数实践

查看脚本内容
[root@localhost ~]# cat function_arg_scripts.sh
#!/bin/bash
# 功能:脚本传参函数调用# 定制数据运算的函数
add_func() {echo $(( $1 + $2 ))
}
sub_func() {echo $(( $1 - $2 ))
}
mul_func() {echo $(( $1 * $2 ))
}
div_func() {echo $(( $1 / $2 ))
}[ $# -ne 2  ] && echo "必须传递两个数字参数" && exit
echo -n "$1+$2="; add_func $1 $2
echo -n "$1-$2="; sub_func $1 $2
echo -n "$1*$2="; mul_func $1 $2
echo -n "$1/$2="; div_func $1 $2注意:这种简单的脚本传参函数调用,导致大量的位置参数,容易引起混乱,需要改造
  • 2.脚本执行效果
[root@localhost ~]# /bin/bash function_arg_scripts.sh
必须传递两个数字参数
[root@localhost ~]# /bin/bash function_arg_scripts.sh 5 4
5+4=9
5-4=1
5*4=20
5/4=1

e.实践2-实践2-脚本传参函数进阶实践

查看脚本内容
[root@localhost ~]# cat function_arg_scripts2.sh
#!/bin/bash
# 功能:传参函数定义和调用# 接收脚本传参
arg1=$1
arg2=$2
# 定制数据运算的函数
add_func() {num1=$1num2=$2echo $(( ${num1} + ${num2} ))
}
sub_func() {num1=$1num2=$2echo $(( ${num1} - ${num2} ))
}
mul_func() {num1=$1num2=$2echo $(( ${num1} * ${num2} ))
}
div_func() {num1=$1num2=$2echo $(( ${num1} / ${num2} ))
}[ $# -ne 2  ] && echo "必须传递两个数字参数" && exit
echo -n "${arg1}+${arg2}="; add_func ${arg1} ${arg2}
echo -n "${arg1}-${arg2}="; sub_func ${arg1} ${arg2}
echo -n "${arg1}*${arg2}="; mul_func ${arg1} ${arg2}
echo -n "${arg1}/${arg2}="; div_func ${arg1} ${arg2}
脚本执行效果
[root@localhost ~]# /bin/bash function_arg_scripts2.sh
必须传递两个数字参数
[root@localhost ~]# /bin/bash function_arg_scripts2.sh 7 5
7+5=12
7-5=2
7*5=35
7/5=1

四、函数退出

4.1.简介

  • 我们可以将函数代码块,看成shell脚本内部的小型脚本,所以说函数代码块也会有执行状态返回值。对于函数来说,它通常支持两种种状态返回值的样式
  • 样式1-默认的退出状态:
    • 默认情况下,函数的退出状态是函数体内的最后一条命令的退出状态,可以通过 $? 来获取
  • 样式2-return定制状态返回值:
    • 在函数体内部,通过return定制状态返回值的内容

4.2.注意:

  • return的状态返回值必须尽快使用,否则会被其他return的值覆盖
  • return的状态返回值必须在 0-255,否则失效

4.3.简单实践:

实践1-默认退出状态

[root@localhost ~]# cat function_exit_status1.sh
#!/bin/bash
# 功能:函数默认状态返回值# 定制成功运行的函数
ok_func() {echo -e "\e[31m脚本的使用帮助信息: xxx\e[0m"
}
# 定制一个运行失败的函数
err_func() {666666
}
# 定制脚本使用逻辑
if [ $# -eq 1 ]
thenerr_funcecho "错误函数的执行状态返回值: " $?
elseok_funcecho "成功函数的执行状态返回值: " $?
fi
脚本执行效果
[root@localhost ~]# /bin/bash function_exit_status1.sh
脚本的使用帮助信息: xxx
成功函数的执行状态返回值:  0
[root@localhost ~]# /bin/bash function_exit_status1.sh aa
function_exit_status1.sh:行10: 666666: 未找到命令
错误函数的执行状态返回值:  127
[root@localhost ~]# lll; echo $?
bash: lll: 未找到命令
127
结果显示:对于异常的函数来说,默认的状态返回值有安全隐患

实践2-return定制函数的返回值实践

[root@localhost ~]# cat function_exit_status2.sh
#!/bin/bash
# 功能:return定制函数状态返回值# 定制成功运行的函数
ok_func() {echo -e "\e[31m脚本的使用帮助信息: xxx\e[0m"# 定制超范围的状态返回值return 666
}
# 定制一个运行失败的函数
err_func() {666666# 定制状态返回值return 222
}
# 定制脚本使用逻辑
if [ $# -eq 1 ]
thenerr_funcecho "错误函数的执行状态返回值: " $?
elseok_funcecho "成功函数的执行状态返回值: " $?
fi
脚本执行效果
[root@localhost ~]# /bin/bash function_exit_status2.sh
脚本的使用帮助信息: xxx
成功函数的执行状态返回值:  154
[root@localhost ~]# /bin/bash function_exit_status2.sh aa
function_exit_status2.sh:行12: 666666: 未找到命令
错误函数的执行状态返回值:  222
结果显示:return的状态返回值范围必须满足要求

五、综合案例

5.1.信息采集

  • 脚本实践-采集系统负载信息
[root@localhost ~]# cat function_systemctl_load.sh
#!/bin/bash
# 功能:采集系统负载信息
# 版本:v0.3# 定制资源类型
resource_type=(CPU MEM)# 定制cpu信息输出函数
cpu_info() {cpu_attribute=(1 5 15)cpu_load=($(uptime | tr -s " " | cut -d " " -f 11-13 | tr "," " "))echo -e "\e[31m\t系统CPU负载信息\e[0m"echo -e "\e[32m================================"for index in ${!cpu_attribute[@]}doecho "CPU ${cpu_attribute[$index]} min平均负载为: ${cpu_load[$index]}" doneecho -e "================================\e[0m"	
}
# 获取内存相关属性信息
mem_info() {free_attribute=(总量 使用 空闲)free_info=($(free -m | grep Mem | tr -s " " | cut -d " " -f 2-4))echo -e "\e[31m\t系统内存负载信息\e[0m"echo -e "\e[32m================================"for index in ${!free_attribute[@]}doecho "内存 ${free_attribute[$index]} 信息为: ${free_info[$index]} M" doneecho -e "================================\e[0m"
}# 服务的操作提示
echo -e "\e[31m---------------查看资源操作动作---------------1: CPU  2: MEM
-------------------------------------------"'\033[0m'
# 选择服务操作类型
while true
doread -p "> 请输入要查看的资源信息类型: " resource_idechocase ${resource_type[$resource_id-1]} in"CPU")cpu_info;;"MEM")mem_info;;*)echo -e "\e[31m\t请输入有效的信息类型\e[0m";;esac
done
  • 2.测试:
脚本使用效果
[root@localhost ~]# /bin/bash function_systemctl_load.sh
---------------查看资源操作动作---------------1: CPU  2: MEM
-------------------------------------------
> 请输入要查看的资源信息类型: 1系统CPU负载信息
================================
CPU 1 min平均负载为: 0.00
CPU 5 min平均负载为: 0.01
CPU 15 min平均负载为: 0.05
================================
> 请输入要查看的资源信息类型: 2系统内存负载信息
================================
内存 总量 信息为: 3770 M
内存 使用 信息为: 237 M
内存 空闲 信息为: 3290 M
================================
> 请输入要查看的资源信息类型: 3请输入有效的信息类型
> 请输入要查看的资源信息类型: ^C
[root@localhost ~]#

5.2.环境部署

a.需求

  • 定制kubernetes环境部署管理的功能脚本改造
    • 功能函数实现
    • 扩充while循环执行功能
    • 增加q退出环境功能

b.脚本内容

  • 查看脚本内容
[root@localhost ~]# cat function_kubernetes_manager.sh
#!/bin/bash
# 功能:定制kubernetes环境部署管理的功能
# 版本:v0.2# 定制数组变量
env_array=(base ha k8s_base master slave)# 监控平台的信息提示
menu(){echo -e "\e[31m     欢迎使用kubernetes部署平台"echo -e "\e[32m-----------请选择部署阶段-----------"echo -e " 1: 基础环境部署"echo -e " 2: 高可用环境部署"echo -e " 3: kubernetes基础环境部署"echo -e " 4: 主角色环境部署"echo -e " 5: 从角色环境部署"echo -e " q: 退出"echo -e "----------------------------------\033[0m"
}
# 定制基础环境
os_base_func(){echo -e "\e[31m开始基础环境部署..."echo "1 执行跨主机免密码操作"echo "2 执行时间同步操作"echo "3 执行内核配置操作"echo -e "4 执行容器私有仓库部署操作\e[0m"
}# 定制高可用环境
ha_func(){echo -e "\e[31高可用环境部署..."echo "1 执行高可用环境部署操作"echo -e "2 执行负载均衡环境部署操作\e[0m"
}# 定制k8s基础环境
k8s_base_func(){echo -e "\e[31mkubernetes基础环境部署..."echo "1 执行证书管理操作"echo "2 执行etcd环境部署操作"echo -e "3 执行集群证书配置操作\e[0m"
}# 定制主角色环境
master_func(){echo -e "\e[31m主角色环境部署..."echo "1 执行apiserver环境部署操作"echo "2 执行scheduler环境部署操作"echo "3 执行controller环境部署操作"echo "4 执行认证配置操作"echo "5 执行容器环境部署操作"echo "6 执行kubelet环境部署操作"echo -e "7 执行kube-proxy环境部署\e[0m"
}
# 定制从角色环境
slave_func(){echo -e "\e[31m主角色环境部署..."echo "1 执行容器环境部署操作"echo "2 执行kubelet环境部署操作"echo -e "3 执行kube-proxy环境部署\e[0m"
}
# 定制错误提示信息
usage_func(){echo -e "\e[31m请输入有效的功能场景标识\e[0m"
}# 脚本内容的判断
while true
do# 定制业务逻辑menuread -p "请输入功能标识: " env_idif [ ${env_id} == "q" ];thenexitelse# 执行配套业务逻辑case "${env_array[$env_id-1]}" in"base")os_base_func;;"ha")ha_func;;"k8s_base")k8s_base_func;;"master")master_func;;"slave")slave_func;;*)usage_func;;esacfi
done
  • 2.测试:
[root@localhost ~]# /bin/bash function_kubernetes_manager.sh欢迎使用kubernetes部署平台
-----------请选择部署阶段-----------1: 基础环境部署2: 高可用环境部署3: kubernetes基础环境部署4: 主角色环境部署5: 从角色环境部署q: 退出
----------------------------------
请输入功能标识: 6
请输入有效的功能场景标识欢迎使用kubernetes部署平台
-----------请选择部署阶段-----------1: 基础环境部署2: 高可用环境部署3: kubernetes基础环境部署4: 主角色环境部署5: 从角色环境部署q: 退出
----------------------------------
请输入功能标识: 5
主角色环境部署...
1 执行容器环境部署操作
2 执行kubelet环境部署操作
3 执行kube-proxy环境部署欢迎使用kubernetes部署平台
-----------请选择部署阶段-----------1: 基础环境部署2: 高可用环境部署3: kubernetes基础环境部署4: 主角色环境部署5: 从角色环境部署q: 退出
----------------------------------
请输入功能标识: q

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

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

相关文章

RA4M2开发涂鸦模块CBU(6)----RA4M2驱动涂鸦CBU模组

RA4M2开发涂鸦模块CBU.6--RA4M2驱动涂鸦CBU模组 概述视频教学样品申请参考程序硬件准备接口生成UARTUART属性配置R_SCI_UART_Open()函数原型回调函数user_uart_callback0 ()变量定义按键回调更新按键状态DP-LED 同步长按进入配网涂鸦协议解析主循环任务调度 概述 本方案基于瑞…

MiniMax-M1: Scaling Test-TimeCompute Efficiently with I Lightning Attention

我们推出了MiniMax-M1,这是全球首个开源权重、大规模混合注意力推理模型。MiniMax-M1采用了混合专家系统(Mixture-of-Experts,简称MoE)架构,并结合了闪电注意力机制。该模型是在我们之前的MiniMax-Text-01模型&#xf…

Appium+python自动化(二十六) -Toast提示

在日常使用App过程中,经常会看到App界面有一些弹窗提示(如下图所示)这些提示元素出现后等待3秒左右就会自动消失,那么我们该如何获取这些元素文字内容呢? Toast简介 Android中的Toast是一种简易的消息提示框。 当视图…

【信号与系统三】离散时间傅里叶变换

上一讲我们讲述了连续时间傅里叶变换,这一讲同理来个离散时间傅里叶变换。 和上讲模块类似 5.1离散时间傅里叶变换 这一式子就是离散时间傅里叶变换对 5.2周期信号的傅里叶变换 同理,由于之前第一讲讲到: 可以推出: 举个例子&am…

Python应用石头剪刀布练习初解

大家好!作为 Python 初学者,寻找一个既简单又有趣的项目来练习编程技能是至关重要的。今天,我将向大家介绍一个经典的编程练习——石头剪刀布游戏,它可以帮助你掌握 Python 的基本概念,如条件语句、随机数生成和用户输入处理等。 …

私有规则库:企业合规与安全的终极防线

2.1 为什么企业需要私有规则库?——合规与安全的最后防线 真实案例:2023年某跨境电商因员工泄露内部检测规则,导致黑产绕过风控系统,损失1200万+ 企业规则库的三大刚需: 行业合规: 金融行业需符合《个人金融信息保护技术规范》 医疗行业需满足HIPAA患者数据脱敏要求 业…

长尾关键词优化SEO核心策略

内容概要 本文旨在系统解析长尾关键词在搜索引擎优化中的核心地位,为读者提供从理论到实践的全面指南。文章首先探讨长尾关键词的基础作用,帮助理解其在提升网站流量质量中的价值。接着,深入介绍精准定位低搜索量、高转化率关键词的策略&…

腾讯云事件总线:构建毫秒级响应的下一代事件驱动架构

摘要 事件总线(EventBridge)作为云原生架构的核心枢纽,其性能与可靠性直接影响企业系统弹性。腾讯云事件总线基于TGW云网关底层能力重构,实现单节点吞吐量提升125%、故障恢复时间降至4秒级(行业平均>30秒&#xff0…

PyTorch 中mm和bmm函数的使用详解

torch.mm 是 PyTorch 中用于 二维矩阵乘法(matrix-matrix multiplication) 的函数,等价于数学中的 A B 矩阵乘积。 一、函数定义 torch.mm(input, mat2) → Tensor执行的是两个 2D Tensor(矩阵)的标准矩阵乘法。 in…

Qt 解析复杂对象构成

Qt 解析复杂对象构成 dumpStructure 如 QComboBox / QCalendarWidget / QSpinBox … void Widget::Widget(QWidget* parent){auto c new QCalendarWidget(this);dumpStructure(c,4); }void Widget::dumpStructure(const QObject *obj, int spaces) {qDebug() << QString…

山姆·奥特曼:从YC到OpenAI,硅谷创新之星的崛起

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 山姆奥特曼&#xff1a;从YC到OpenAI&#xff0c;硅谷创新之星的崛起 在人工智能革命…

PHP语法基础篇(五):流程控制

任何 PHP 脚本都是由一系列语句构成的。一条语句可以是一个赋值语句&#xff0c;一个函数调用&#xff0c;一个循环&#xff0c;一个条件语句或者甚至是一个什么也不做的语句&#xff08;空语句&#xff09;。语句通常以分号结束。此外&#xff0c;还可以用花括号将一组语句封装…

怎么隐藏关闭或恢复显示输入法的悬浮窗

以搜狗输入法为例&#xff0c;隐藏输入法悬浮窗 悬浮窗在输入法里的官方叫法为【状态栏】。 假设目前大家的输入法相关显示呈现如下状态&#xff1a; 那我们只需在输入法悬浮窗&#xff08;状态栏&#xff09;的任意位置鼠标右键单击&#xff0c;调出输入法菜单&#xff0c;就…

Electron (02)集成 SpringBoot:服务与桌面程序协同启动方案

本篇是关于把springboot生成的jar打到electron里&#xff0c;在生成的桌面程序启动时springboot服务就会自动启动。 虽然之后并不需要这种方案&#xff0c;更好的是部署[一套服务端&#xff0c;多个客户端]...但是既然搭建成功了&#xff0c;也记录一下。 前端文件 1、main.js…

2025年计算机应用与神经网络国际会议(CANN 2025)

2025 International Conference on Computer Applications and Neural Networks &#xff08;一&#xff09;会议信息 会议简称&#xff1a;CANN 2025 大会地点&#xff1a;中国重庆 收录检索&#xff1a;提交Ei Compendex,CPCI,CNKI,Google Scholar等 &#xff08;二&#x…

振动分析中的低频噪声问题:从理论到实践的完整解决方案

前言 在振动监测和结构健康监测领域&#xff0c;我们经常需要从加速度信号计算速度和位移。然而&#xff0c;许多工程师在实际应用中都会遇到一个令人困扰的问题&#xff1a;通过积分计算得到的速度和位移频谱中低频噪声异常放大。 本文将深入分析这个问题的根本原因&#xf…

ncu学习笔记01——合并访存

全局内存通过缓存实现加载和存储过程。其中&#xff0c;L1为一级缓存&#xff0c;每个SM都有自己的L1&#xff1b;L2为二级缓存&#xff0c;L2则被所有SM共有。 数据从全局内存到SM的传输过程中&#xff0c;会去L1和L2中查询是否有缓存。对全局内存的访问将经过L1&#xff1b;…

2012 - 正方形矩阵

​​​​题目描述 晶晶同学非常喜欢方形&#xff0c;她希望打印出来的字符串也是方形的。老师给了晶晶同学一个字符串"ACM"&#xff0c;晶晶同学突发奇想&#xff0c;如果任意给定义一个整数n&#xff0c;能不能打印出由这个字符串组成的正方形字符串呢&#xff1f;…

C++中set的常见用法

在 C 里&#xff0c;std::set属于标准库容器的一种&#xff0c;其特性是按照特定顺序存储唯一的元素。下面为你详细介绍它的常见使用方法&#xff1a; 1. 头文件引入 要使用std::set&#xff0c;需要在代码中包含相应的头文件&#xff1a; #include <set> 2. 集合的定…

stm32移植freemodbus

1、设置串口 开启串口中断 2、设置定时器 已知在freemodbus中默认定义&#xff1a;当波特率大于19200时&#xff0c;判断一帧数据超时时间固定为1750us&#xff0c;当波特率小于19200时&#xff0c;超时时间为3.5个字符时间。这里移植的是115200&#xff0c;所以一帧数据超时…