目录
一、函数作用
二、输出内容的格式化处理
1.输出变量的类型
2.输出变量的位数
小数:
整数:
16 进制:
在做蓝桥杯第五届国赛试题的时候,遇到这样一个问题:题目要求单片机通过串口返回电脑一组数据,包括温度、湿度、时间等,数据很多问且中间有大括号等符号做间隔,如果一个字符一个字符的分开重新定义,发送的话就非常麻烦。通过上网学习,发现了一个非常有效的办法:sprintf()函数来实现。但是,在C51中的sprintf函数与标准C语言中有所差别,注意区分。经过上网查阅资料,特此总结一下。
首先,用这个函数的时候,前面要加上这个头文件:#include <stdio.h>
一、函数作用 sprintf() 是格式化输出函数,保存字符串到缓冲区中,起到拼接字符串的作用。
函数介绍: int sprintf(char *str, const char *format, ...);
参数: str: 数据缓冲区,通常是一个字符串数组
format:输出的内容
举个例子:
int a = 10;
char buf[100] = {0};
sprintf(buf,"a = %d\n",a); 作用:将a的值放置到%d的位置,然后"a = 10\n"这句话保存到数组buf中。
说明:函数sprintf()的用法和printf()函数一样,只是sprintf()函数给出第一个参数string(一般为字符数组,用来存储字符串),起到拼接字符串的作用。
又例如:
sprintf(s, "%d", 123); //产生"123" 把整数123 打印成一个字符串保存在s 中。
二、输出内容的格式化处理 对于输出的内容,还要对他进行格式化的处理,也就是上面例子中双引号内的部分。
1.输出变量的类型 b 表示字节数据;
bd 表示 8 位有符号整数(256)(KEIL里扩展出了b,h,l来对输入字节宽的设置:b八位(256);h十六位(65535);l三十二位);
bu 表示 8 位无符号整数;
bx 表示 8 位十六进制整数;
小数用f表示。
一、JSR303校验 1.使用校验注解 <!--Valid--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <version>2.3.2.RELEASE</version> </dependency> <!--自定义注解--> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> (1)@NotNull
The annotated element must not be null. Accepts any type.
注解元素禁止为null,能够接收任何类型
(2)@NotEmpty
the annotated element must not be null nor empty.
该注解修饰的字段不能为null或""
Supported types are:
支持以下几种类型
CharSequence (length of character sequence is evaluated)
字符序列(字符序列长度的计算)
Collection (collection size is evaluated)
集合长度的计算
Map (map size is evaluated)
map长度的计算
Array (array length is evaluated)
数组长度的计算
(3)@NotBlank
The annotated element must not be null and must contain at least one non-whitespace character.
Golang + vscode环境搭建 在学习go语言的时候,搭建环境通常是一个困扰的话题。笔者试图通过这篇文章,帮助像我一样的初学者解决部分环境搭建的问题,节省各位的时间。
下载go语言安装包 我使用的是Windows10系统,首先点击下面的链接(https://golang.google.cn/dl/),安装go语言。Go安装包下载链接
下载好安装包后,开始安装,默认会安装在 C:\Program Files\Go,也可以选择其他位置进行安装。
安装git 请参考其他博主发布的教程
环境变量 安装go语言的同时,会自动帮助配置环境变量,帮助系统在运行go命令时找到合适的位置。因为后续可能出现的问题,同时方便自行更改环境变量,我们简要说明一下go语言相关环境变量。
首先鼠标右键单击此电脑,点击属性,下拉在相关设置中选中高级系统设置,如图所示。
之后在高级系统设置中,选择进入环境变量。
GOPATH 是go语言的工作目录,我们将我们写的代码放在此目录下,通常可以设置为你喜欢的地方。这里笔者将默认值修改为我常写代码的目录。
PATH用户变量下进入Path,找到%USERPROFILE%\go\bin,这是你之前安装go的目录中,bin目录的地址。这里笔者使用的是默认值。
检查或修改环境变量完成后,windows + R,输入cmd或powershell,在命令行中输入go version,按照下图检查输出结果是否正确,正确则说明配置无误。
模块下载配置 由于go需要访问github下载相关模块,经常会出现连接失败的情况,所以我们需要配置go mod proxy,可以大大加快模块的下载速度。这里我们参考Goproxy中的配置方法进行配置。注意,如果想要永久保持此设置,建议按照链接中的方法配置环境变量,这里不做额外赘述。
下载vscode与相关插件 相应的文章有很多,这里不做额外赘述。此外,需要在vscode的扩展中下载go的插件,如下图所示。
使用vscode下载go语言的相关模块 使用vscode打开GOPATH文件夹,笔者这里是打开E:\CodeField\Golang,并创建一个hello.go文件,内容如下。
package main import "fmt" func main() { fmt.Println("Hello World!") } 这时你屏幕的右下角通常会跳出信息,提示你安装缺失的模块,点击install all。即可开始安装模块。
开始安装之后,可以在输出位置看到安装信息。这里提示一下,可能会跳出很多安装失败的信息,但是你不需要理会,只要最终显示安装成功就可以正常运行程序,笔者目前并没有发现什么问题。
笔者安装模块后的目录如下
运行第一个go程序 选择终端,新建终端,在终端输入go run hello.py,即可正常显示程序输出。
由于笔者也是go方面的小白,可能有很多问题和不足之处,请各位看官多多指教
// Online C++ compiler to run C++ program online #include<iostream> #include<vector> #include<stdlib.h> #include<algorithm> #include<iomanip> #include<string.h> #include<exception> #include<map> #include<cmath> #include<unordered_map> #include<set> #include<climits> #include<ctype.h> #include<queue> #include<stack> using namespace std; struct Serv { string name; int id; }; bool comp(Serv a, Serv b) { if (a.id < b.id) return true; return false; } vector<string> split(string str, char ch) { vector<string> list; str += ch; while (str.find(ch) != string::npos) { int idx = str.
python虽然没有指针的概念,但是对象、引用、地址这些内容还是存在的,尤其是像列表对象、某类型对象的引用上,搞清楚对象变量的复制和赋值很有必要,不然容易出现“莫名其妙”的错误。
目录 认清对象、引用、地址(直接以“=”赋值变量)以列表为例以自定义类为例 浅拷贝(copy()函数的使用)无嵌套的情况有嵌套的情况以列表为例以自定义类为例 深拷贝(deepcopy()函数的使用) 认清对象、引用、地址(直接以“=”赋值变量) 以列表为例 python中给一个变量a赋值列表实际上是创建了一个列表对象,并将该列表的地址赋值给a,而变量a此时就成为了这个列表对象的引用。当用a给变量b赋值时,其实只是把这个列表对象的地址赋值给了b,即a和b都成为了该对象的引用,因此直接对a或b进行修改,都将使该对象发生变化,下面给出一段代码示例:
a = ["abc","bcd","cde",1,2,3] #创建了一个对象并用变量a引用它 b = a #将a赋值给b,让b和a都同时作为列表对象的引用 print("a=",a,"b=",b) #输出a,b列表中的内容 print("a:",type(a),id(a),"b:",type(b),id(b))#输出a,b的类型和地址 b[0] = 0 #通过引用b将列表第一个元素赋值为0 a.remove(3) #通过引用a将列表中第一个值为3的元素删除 print("修改后:") print("a=",a,"b=",b) #输出a,b列表中的内容 print("a:",type(a),id(a),"b:",type(b),id(b))#输出a,b的类型和地址 a = ["a","new","list"] #创建一个新的对象赋值给a,即让变量a成为新列表对象的引用 print("a=",a,"b=",b) #输出a,b列表中的内容 print("a:",type(a),id(a),"b:",type(b),id(b))#输出a,b的类型和地址 运行结果为:
a= ['abc', 'bcd', 'cde', 1, 2, 3] b= ['abc', 'bcd', 'cde', 1, 2, 3] a: <class 'list'> 2072617426752 b: <class 'list'> 2072617426752 修改后: a= [0, 'bcd', 'cde', 1, 2] b= [0, 'bcd', 'cde', 1, 2] a: <class 'list'> 2072617426752 b: <class 'list'> 2072617426752 a= ['a', 'new', 'list'] b= [0, 'bcd', 'cde', 1, 2] a: <class 'list'> 2072617436224 b: <class 'list'> 2072617426752 可以看到,一开始a和b共同代表了创建的列表["
附和导线平差程序(by C#) 内容简介过程简介程序源码矩阵类Matrix点类Point角类Angle主程序 更新 内容简介 本文主要内容包括本人编写附和导线平差程序的过程及附和导线平差程序源代码,在此记录,以供有兴趣的朋友参考学习。
过程简介 最近学习《C#(注:读音为C sharp)程序设计》这门课时,老师布置了一个设计导线平差程序的作业,一直在学python,好久没用类C语言了,很是头大,好在参考博主:流浪猪头拯救地球的一系列文章,终于是将程序编写出来。
(2020/12/7:初始版本优点是方便上手,缺点是还有很多地方可以优化,下一版本将在不久后更新,coding……)
程序源码 附和导线平差C#程序工程文件及用于测试的文本已上传至附和导线平差C#程序。
此程序一共用到三个类库,分别是矩阵类Matrix、点类Point、角类Angle。
矩阵类Matrix 此类库代码量过大,无法放入博文中,有兴趣的话可以从C#矩阵类库下载。
点类Point using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing;//与PointF 联系起来了 namespace work //这里改成和您的namespace 名字一样即可 { public class Point {//Define fields public string name; public double x; //coordinate public double y; public double z; public string Name { get { return name; } set { name = value; } } public double X { get { return x; } set { x = value; } } public double Y { get { return y; } set { y = value; } } public double Z { get { return z; } set { z = value; } } //The constructor public Point(double x = 0, double y = 0, double z = 0, string name = "
来自个人博客:http://www.coolsite.top/archives/368
陈硕的书中有说到过网络编程有三个层次:
● 读过教程和文档,做过练习
● 熟悉本系统 TCP/IP 协议栈的脾气
● 自己写过一个简单的 TCP/IP stack
个人觉得自己第一层次已经没有什么问题,自己编写过一些经典的的网络编程代码(chat、echo、proxy),能够不错地运行在开发环境;第二层次通过自己开发的 serverlite 网络库也对网络编程和 TCP/IP 的一些坑有所了解,欠缺一些线上调试和解决问题的经验,这个需要多年的工作积累目前尚未达到,所以第二层次算是入门。但经验积累不是一蹴而就的,交给时间。但好奇心驱使下想在这里一窥第三层次的感觉,但内核代码又过于庞大冗长,因此这里想分享一个应用层的 TCP/IP 协议栈源码,代码简洁且严格遵从 TCP/IP 协议规范,便于阅读理解。
level-ip 源码地址:https://github.com/saminiir/level-ip
本文主要分享 TCP 接收消息的部分。
相关函数如下,tcp_input_state 是消息到达网卡后,经过层层传递和解包(链路层和网络层),最终到达的地方,其接收的参数有三个,分别是 struct sock* sk,表示一个传输层相关数据;struct tcphdr* th,表示 tcp 头信息,struct sk_buff *skb表示完整的一个包数据。
所以该函数的工作就是根据当前 TCP 连接的状态和数据包的头信息,来对接收的数据包做不同的处理,是 TCP 接收数据的核心函数。
/* * Follows RFC793 "Segment Arrives" section closely */ int tcp_input_state(struct sock *sk, struct tcphdr *th, struct sk_buff *skb) { struct tcp_sock *tsk = tcp_sk(sk); struct tcb *tcb = &tsk->tcb; tcpsock_dbg("
文章目录 为什么需要DockerFile什么是DockerFileDockerFile构建过程DockerFile指令DockerFile定义规则实战测试自定义扩展版centOS自定义镜像 Tomcat发布镜像到DockerHub发布镜像到阿里云镜像服务 为什么需要DockerFile 大家想想,Nginx,tomcat,mysql 这些镜像都是哪里来的?官方能写,我们不能写吗?
我们要研究自己如何做一个镜像,而且我们写的微服务项目以及springboot打包上云部署,Docker就是最方便的。
微服务打包成镜像,任何装了Docker的地方,都可以下载使用,极其的方便。
流程:开发应用=>DockerFile=>打包为镜像=>上传到仓库(私有仓库,公有仓库)=> 下载镜像 => 启动
什么是DockerFile dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
构建步骤:
编写DockerFile文件docker build 构建镜像docker run 我们先找一个官方镜像来看它的DockerFile 有一个初步印象
以centos为例 地址:https://hub.docker.com/_/centos
DockerFile构建过程 Docker从基础镜像运行一个容器执行一条指令并对容器做出修改执行类似 docker commit 的操作提交一个新的镜像层Docker再基于刚提交的镜像运行一个新容器执行dockerfile中的下一条指令直到所有指令都执行完成! 说明
从应用软件的角度来看,DockerFile,Docker镜像与Docker容器分别代表软件的三个不同阶段。
DockerFile 是软件的原材料 (代码)Docker 镜像则是软件的交付品 (.apk)Docker 容器则是软件的运行状态 (客户下载安装执行) DockerFile 面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可!
DockerFile:需要定义一个DockerFile,DockerFile定义了进程需要的一切东西。DockerFile涉及的内容
包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进
程和内核进程(当引用进行需要和系统服务和内核进程打交道,这时需要考虑如何设计 namespace的权
限控制)等等。Docker镜像:在DockerFile 定义了一个文件之后,Docker build 时会产生一个Docker镜像,当运行Docker 镜像时,会真正开始提供服务Docker容器:容器是直接提供服务的 DockerFile指令 FROM # 基础镜像,当前新镜像是基于哪个镜像的 MAINTAINER # 镜像维护者的姓名混合邮箱地址 RUN # 容器构建时需要运行的命令 EXPOSE # 当前容器对外保留出的端口 WORKDIR # 指定在创建容器后,终端默认登录的进来工作目录,一个落脚点 ENV # 用来在构建镜像过程中设置环境变量 ADD # 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包 COPY # 类似ADD,拷贝文件和目录到镜像中! VOLUME # 容器数据卷,用于数据保存和持久化工作 CMD # 指定一个容器启动时要运行的命令,dockerFile中可以有多个CMD指令,但只有最 后一个生效! ENTRYPOINT # 指定一个容器启动时要运行的命令!和CMD一样 ONBUILD # 当构建一个被继承的DockerFile时运行命令,父镜像在被子镜像继承后,父镜像的 ONBUILD被触发 DockerFile定义规则 每条保留字指令都必须为大写字母且后面要跟随至少一个参数指令按照从上到下,顺序执行#表示注释每条指令都会创建一个新的镜像层,并对镜像进行提交流程 实战测试自定义扩展版centOS Docker Hub 中99% 的镜像都是通过在base镜像(Scratch)中安装和配置需要的软件构建出来的
JavaScript源码 分享111个JavaScript源码,总有一款适合您
源码下载链接:https://pan.baidu.com/s/1aUIpouX5nTwW1FF-8lStnw?pwd=jh3v 提取码:jh3v
采集代码下载链接:采集代码.zip - 蓝奏云
下面是文件的名字,我放了一些图片,文章里不是所有的图主要是放不下...,大家下载后可以看到。
import os import shutil import time from time import sleep import requests from bs4 import BeautifulSoup from docx import Document from docx.shared import Inches from framework.base.BaseFrame import BaseFrame from sprider.business.DownLoad import DownLoad from sprider.business.SeleniumTools import SeleniumTools from sprider.business.SpriderTools import SpriderTools from selenium import webdriver from selenium.webdriver.common.by import By from sprider.model.SpriderEntity import SpriderEntity from sprider.access.SpriderAccess import SpriderAccess class HuaJunCode: base_url = "
文章目录 题目题解同类题解决方案 剑指 Offer 26. 树的子结构 题目 输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
例如:
给定的树 A:
3 / \ 4 5 / \ 1 2 给定的树 B:
4 / 1 返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。
示例 1:
输入:A = [1,2,3], B = [3,1]
输出:false
示例 2:
输入:A = [3,4,5,1,2], B = [4,1]
输出:true
JAVA版本答案:
class Solution { public boolean isSubStructure(TreeNode A, TreeNode B) { return (A != null && B !
加深对时间操作的理解,最怕的就是操作时间,还有日历类,到现在都不大会,感觉最难的就是涉及到时间转化的操作
public static void main(String[] args) throws ParseException { //yyyy-MM-dd'T'HH:mm:ss.SSSZ 对应格式在SimpleDateFormat类源码中有 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); String format1 = dateFormat.format(new Date()); System.out.println("format1 = " + format1);//format1 = 2023-01-13T15:20:25.233+0800 SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); //时间转字符串(日期格式化) //将日期格式化所以参数是日期 String format = sdf.format(new Date()); System.out.println("format = " + format);//format = 2023/01/13 15:20:25 //Date类型和LocalDateTime的日期格式化操作类似,都是格式化类调用format()方法格式日期 //但字符串转时间不同,Date还是使用的格式化类,而LocalDateTime类自己提供了parse()转化方法 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS"); String format2 = formatter.format(LocalDateTime.now()); System.out.println("format2 = " + format2);//format2 = 2023/01/13 15:20:25.285 //字符串转时间(可以会有异常) //将字符串转时间所以参数是字符串,2022-1-3居然会出异常,斜杠恐怖如斯 Date parse = sdf.
报错内容如下,也就是没有成功关联上远程仓库
首次关联仓库
git remote add origin +你的仓库地址
首次推送
git push -u origin "master"
推送失败可以查看是否成功关联上远程仓库
git remote -v
如果有相应的地址在尝试推送,如果失败删除关联库重新去关联
git remote rm origin
5.也可以查询.git 文件下的config内容。和成功的对比只有
手动添加以下信息【备注:除了url处其他的不用修改,url不需要使用引号进行包裹 】
最后使用1,2步骤进行推送
尝试以下方法,但是还是会报错
git config --global url."https://".insteadOf git://
把https://代替git://的意思 以及使用cnpm install下载
找到C盘下的C:\Users\用户名 下找到.gitconfig(注意是右键打开记事本)
最后实现方法
具体如下:
1、打开package.json把"tui-editor"删掉
2、删除"tui-editor"相关路由、components,具体文件地址如下:
路由位置:
src/router/modules/components.js 搜索"markdown",把相应markdown路由代码删除;
!!!【这一步做了在下载也运行成功了】
components位置:
src/components/MarkdownEditor 删除后,再执行npm install 或 npm install --registry=registry.npm.taobao.org 下载并运行成功!
TCP/IP协议核心是传输控制协议 (TCP) 和互联网协议 (IP)。TCP负责在两台计算机之间建立可靠的数据传输连接,确保数据正确无误地到达目的地。IP则负责在网络中传输数据包,并确定数据包的路径。
WIFI可以让我们的网络运行得更快,尤其是对于工作来说,它是不可或缺的。但是有时候,我们明明在笔记本电脑上看到WIFI,但就是连接不上,笔记本电脑连接不上wifi怎么办?方法主要有下面4个!
演示机型:联想GeekPro2020 系统版本:Windows 10 方法一:查看WiFi开关 有一部分电脑会有无线网络的硬件开关,检查下有没有关闭,关闭的话打开即可。
笔记本电脑找不到连接wifi的图标?除此之外,笔记本电脑也有控制无线网的快捷键,检查电脑的F功能键有没有WIFI的图标,或者是飞行模式(比如,我的是F12,按下【Fn+F12】就可以打开无线网)。
方法二:查看网络 你可以查看你的网络有没有被禁用。笔记本电脑找不到无线网络怎么办?操作如下:
1、同时按下【Win+i】打开控制面板,再点击【网络和Internet】;
2、在打开窗口的右侧,找到并单击【更改适配器选项】;
3、接着鼠标右键WIFI连接,选择【启用】。
方法三:查看网卡驱动以及WiFi服务 你可以查看网卡驱动以及WiFi服务,笔记本WLAN不见了。操作如下:
1、鼠标右键电脑桌面上的【此电脑】,选择打开列表的【管理】;
2、窗口打开后,单击【设备管理器】,然后在界面右侧点击展开【网络适配器】,查看里面有没有黄色图标,有的话就要重新安装网卡驱动;
3、如果驱动程序没有问题,就展开【服务和应用程序】,单击【服务】。找到【WLAN自动配置】,单击左上角的【启动此服务】。
方法四:查看是否自动获取IP 你可以查看是否可以自动获取IP,笔记本电脑连接wifi操作如下:
1、同样是按下【Win+i】,单击【网络和Internet】,然后单击【更改适配器选项】。鼠标双击【WLAN】,在打开的窗口点击【属性】;
2、在项目列表里面,查找并双击以打开【Internet协议版本4(TCP/IPv4)】;
3、单击【高级】;
4、切换到【WINS】界面,把【启用TCP/IP上的NetBIOS】前面的方框勾选上,再选择【确定】。然后查看【ipv4连接】的状态,如果看到了【internet】,这表示网络可以正常使用了。
你还会问:笔记本电脑连接不上wifi怎么办?以上就是连接不上WIFI的解决方法。遇到这方面困扰的朋友,赶紧来试试吧!还有更多电脑小技能,大家可以关注我们为你推送更多精选文章。
往期推荐:
怎么看电脑是32位还是64位?超级简单的方法!https://mp.csdn.net/mp_blog/creation/editor/128654629电脑怎么恢复出厂设置?Win10系统恢复出厂设置的方法https://mp.csdn.net/mp_blog/creation/editor/128654297误删的文件不在回收站如何找回?分享一些恢复数据的教程https://mp.csdn.net/mp_blog/creation/editor/128654947
在项目开发中往往需要使用到数据的导入和导出,导入就是从Excel中导入到DB中,而导出就是从DB中查询数据然后使用POI写到Excel上。
写本文的背景是因为在工作中遇到了大数据的导入和导出,问题既然来了逃跑不如干掉它!!!
只要这一次解决了,后期遇到同样的问题就好解决了。
废话不多说,开始撸起来!!!
1.传统POI的的版本优缺点比较 其实想到数据的导入导出,理所当然的会想到apache的poi技术,以及Excel的版本问题。
既然要做导入导出,那么我们就先来大致看一下传统poi技术的版本以及优缺点对比吧!
首先我们知道POI中我们最熟悉的莫过于WorkBook这样一个接口,我们的POI版本也在更新的同时对这个几口的实现类做了更新:
HSSFWorkbook :
这个实现类是我们早期使用最多的对象,它可以操作Excel2003以前(包含2003)的所有Excel版本。在2003以前Excel的版本后缀还是.xls
XSSFWorkbook :
这个实现类现在在很多公司都可以发现还在使用,它是操作的Excel2003--Excel2007之间的版本,Excel的扩展名是.xlsx
SXSSFWorkbook :
这个实现类是POI3.8之后的版本才有的,它可以操作Excel2007以后的所有版本Excel,扩展名是.xlsx
大致知道了我们在导入导出操作的时候会用到这样三个实现类以及他们可以操作的Excel版本和后缀之后,我们就要从优缺点分析他们了
HSSFWorkbook 它是POI版本中最常用的方式,不过:
它的缺点是 最多只能导出 65535行,也就是导出的数据函数超过这个数据就会报错;
它的优点是 不会报内存溢出。(因为数据量还不到7w所以内存一般都够用,首先你得明确知道这种方式是将数据先读取到内存中,然后再操作)
XSSFWorkbook 优点:这种形式的出现是为了突破HSSFWorkbook的65535行局限,是为了针对Excel2007版本的1048576行,16384列,最多可以导出104w条数据;
缺点:伴随的问题来了,虽然导出数据行数增加了好多倍,但是随之而来的内存溢出问题也成了噩梦。因为你所创建的book,Sheet,row,cell等在写入到Excel之前,都是存放在内存中的(这还没有算Excel的一些样式格式等等),可想而知,内存不溢出就有点不科学了!!!
SXSSFWorkbook 从POI 3.8版本开始,提供了一种基于XSSF的低内存占用的SXSSF方式:
优点:
这种方式不会一般不会出现内存溢出(它使用了硬盘来换取内存空间,
也就是当内存中数据达到一定程度这些数据会被持久化到硬盘中存储起来,而内存中存的都是最新的数据),
并且支持大型Excel文件的创建(存储百万条数据绰绰有余)。
缺点:
既然一部分数据持久化到了硬盘中,且不能被查看和访问那么就会导致,
在同一时间点我们只能访问一定数量的数据,也就是内存中存储的数据;
sheet.clone()方法将不再支持,还是因为持久化的原因;
不再支持对公式的求值,还是因为持久化的原因,在硬盘中的数据没法读取到内存中进行计算;
在使用模板方式下载数据的时候,不能改动表头,还是因为持久化的问题,写到了硬盘里就不能改变了;
2.使用方式哪种看情况 经过了解也知道了这三种Workbook的优点和缺点,那么具体使用哪种方式还是需要看情况的:
我一般会根据这样几种情况做分析选择:
1、当我们经常导入导出的数据不超过7w的情况下,可以使用 HSSFWorkbook 或者 XSSFWorkbook都行;
2、当数据量查过7w并且导出的Excel中不牵扯对Excel的样式,公式,格式等操作的情况下,推荐使用SXSSFWorkbook;
3、当数据量查过7w,并且我们需要操做Excel中的表头,样式,公式等,这时候我们可以使用 XSSFWorkbook 配合进行分批查询,分批写入Excel的方式来做;
3.百万数据导入导出(正菜) 铺垫也做了不少,那么现在开始讲讲我在工作中遇到的超百万数据的导入导出解决方案:
想要解决问题我们首先要明白自己遇到的问题是什么?
1、 我遇到的数据量超级大,使用传统的POI方式来完成导入导出很明显会内存溢出,并且效率会非常低;
2、 数据量大直接使用select * from tableName肯定不行,一下子查出来300w条数据肯定会很慢;
3、 300w 数据导出到Excel时肯定不能都写在一个Sheet中,这样效率会非常低;估计打开都得几分钟;
4、 300w数据导出到Excel中肯定不能一行一行的导出到Excel中。频繁IO操作绝对不行;
5、 导入时300万数据存储到DB如果循环一条条插入也肯定不行;
想要减少噪音,更好地聆听音乐,或者是看电视,很多人都会选择戴耳机。其中蓝牙耳机成为越来越多人的选择,它方便携带,没有有线的缠绕。
可能有人会问:无线蓝牙耳机可以连接电脑吗?当然可以。可是很多人不知道该怎么操作,蓝牙耳机怎么连接电脑?操作步骤很简单,前提是你的电脑可以连接蓝牙设备,这样我们才可以把无线蓝牙耳机连接上电脑。
一、蓝牙连接电脑前的准备工作 很多人问:笔记本电脑找不到蓝牙设备怎么办?其实方法很简单,操作前,建议先做好一些准备工作。
操作环境:
演示机型:华为笔记本Mate Book 14 系统版本:Windows 10 准备工作:
打开耳机的电池盒盖,然后长按耳机的【开关键】,进入【配对模式】。当信号灯长时间闪烁时,就可以进行后续的操作了。
二、蓝牙连接电脑的操作步骤 做好准备工作后,电脑连无线耳机怎么连?具体的操作步骤如下:
第1步:打开电脑,单击桌面左下角的【开始图标】。在打开的列表里面,选择【设置】,就是齿轮样式的图标。
第2步:在【Windows设置】界面,找到并点击【设备】。
第3步:设置窗口打开后,单击界面左侧的【蓝牙和其他设备】。然后在右侧找到【蓝牙】,打开它的开关。再点击【添加蓝牙或其他设备】选项。
第4步:这时会再弹出一个窗口,选择【蓝牙】,然后电脑的蓝牙模式那里就会开始搜索附近可以连接的设备。搜索到,一般都可以连接成功。
第5步:选择你要连接的蓝牙设备,电脑就会开始连接。耳机连接电脑成功后,就可以打开音乐软件,或者是看视频的软件来测试下,检查音量的大小和连接是否稳定。
无线耳机怎么连接电脑?蓝牙耳机怎么连接电脑?以上都有详细的教程,跟着操作准没错。如果你还有其他关于蓝牙耳机连接电脑的做法,不妨分享在文章下方,大家一起学习讨论呀!
往期推荐:
电脑怎么恢复出厂设置?Win10系统恢复出厂设置的方法https://mp.csdn.net/mp_blog/creation/editor/128654297怎么看电脑是32位还是64位?超级简单的方法!https://mp.csdn.net/mp_blog/creation/editor/128654629误删的文件不在回收站如何找回?分享一些恢复数据的教程https://mp.csdn.net/mp_blog/creation/editor/128654947
SDK:(software development kit)软件开发工具包。被软件开发工程师用于为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件的开发工具的集合。因此,Android SDK 指的是Android专属的软件开发工具包。
Android SDK官网下载地址
因为我使用的电脑是Win10系统,而且已经下载好了对应的SDK和Android版本,如果你也是Windows系统,点击下面链接自取吧~👇
链接:https://pan.baidu.com/s/1faIQ10ih2IC8SQxgBYeuvg 提取码:y7a0
我这里下载保存在D盘,如下图所示~ (或参考链接:Android SDK下载和安装,以及部署)
2. 将下载好的压缩包解压到当前文件夹,并在D盘新建一个文件夹,命名为Android,将解压好的android-sdk-windows文件夹复制到Android文件夹中。将解压好的android-21文件夹复制到D:\Android\android-sdk-windows\platforms路径下。
双击打开D:\Android_sdk_Windows\android-sdk-windows下的SDK Manager.exe,若能看到对应的SDK和Android版本状态变为Installed,则证明安装成功了,如下图👇(因为我已经安装过了,所以显示Update…)
SDK环境配置
在安装完成后,就可以开始配置环境变量了,与Java JDK的环境变量配置类似。具体步骤👇
第一步:右键“我的电脑(此电脑)”—“属性”—“高级系统设置”—“环境变量”—“系统变量”—“新建”-
变量名:ANDROID_HOME,
变量值:D:\Android\android-sdk-windows”
第二步:“系统变量”-“找到path,点击编辑”-“点击新建”-(将SDK的platform-tools和tools的路径添加到Path 变量内)
新建1:%ANDROID_HOME%\platforms
新建2:%ANDROID_HOME%\tools
新建3:%ANDROID_HOME%\platforms\android-21
最后,打开cmd,在命令终端输入android -h,出现下面提示则证明安装配置成功啦!!!
若是Mac OS, 打开终端,输入android,出现下面提示则证明安装成功了!
文章目录 0 前言1 先看一下最终的效果图2 2048核心2 EasyX库2.1 配色2.2 文字2.3 填充 3 总结 0 前言 最近比较迷2048小游戏,于是想自己写代码实现出来,恰好也在网上找到一个现成的2048的VS工程,但是界面做得很难看,且运行逻辑存在一定问题,于是花了一天时间把原2048工程完善了一下,记录一下实践要点。
1 先看一下最终的效果图 2 2048核心 既然要做2048游戏,首先是要实现2048这个游戏规则。由于C语言中没有Python语言中便捷操作矩阵的方法,因此只能老实定义二维数组、然后用循环去实现。因此代码相对复杂。
#include <iostream> #include <conio.h> #include <stdlib.h> using namespace std; //#include"2048base.h" /*矩阵转置*/ void transform(int *p, int len) { for (int i = 0; i < len; i++) for (int j = 0; j < len; j++) if (i>j) //转置时只需要更新对角部分即可 { int tmp = *(p + i*len + j); *(p + i*len + j) = *(p + j*len + i); *(p + j*len + i) = tmp; } } /*删除某一行数据中的零元素——把零元素根据rev往一个方向去堆叠*/ void delZeros(int *p, int len, bool rev) { int k = rev ?
下面是基于 PyTorch 实现的一个多对多分类预测代码示例:
import torch import pandas as pd # 读入数据 data = pd.read_csv("data.csv") X_train, y_train = data.iloc[:800, :4], data.iloc[:800, 4:] X_test, y_test = data.iloc[800:, :4], data.iloc[800:, 4:] # 转换为 PyTorch 张量 X_train, y_train = torch.tensor(X_train.values),
1. List集合失效的校验 @PostMapping("saveBatch") @ApiOperation("批量保存") @LogOperation("批量保存") public Result saveBatch(@RequestBody @Validated List<ResultFieldDTO> list) { resultFieldService.saveBatch(list); return Result.ok(); } 2. 针对List集合的校验有两种方案 2.1 第一种方案 重新定义一个集合ValidList,需继承集合List,并且定义一个List集合属性,并添加@Valid注解
@Data public class ValidList<E> implements List<E> { @Valid // 这里是关键 private List<E> list = new ArrayList<>(); @Override public int size() { return list.size(); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public boolean contains(Object o) { return list.contains(o); } @Override public Iterator<E> iterator() { return list.iterator(); } @Override public Object[] toArray() { return list.
今天在做的时候需要用到字符串换行,在网上找了一下,换行是通过添加white-space: pre-wrap属性,通过\n进行换行
在这里记录一下
<style lang="scss" scoped> ::v-deep .el-table th.el-table__cell > .cell{ white-space: pre-wrap; font-size: 12px; } </style> 使用的时候直接\n就可以换行了
文章目录 Docker架构环境说明安装步骤阿里云镜像加速Docker底层原理 Docker架构 镜像(image):
Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。 就好似 Java 中的 类和对象,类就是镜像,容器就是对象
容器(container):
Docker 利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。
它可以被启动、开始、停止、删除。每个容器都是相互隔离的,保证安全的平台。
可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)
和运行在其中的应用程序。
容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
仓库(repository):
仓库(Repository)是集中存放镜像文件的场所。
仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓
库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库分为公开仓库(Public)和私有仓库(Private)两种形式。
最大的公开仓库是 Docker Hub(https://hub.docker.com/),存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云 等
需要正确的理解仓储/镜像/容器这几个概念 :
Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个
可交付的运行环境,这个打包好的运行环境就似乎 image镜像文件。只有通过这个镜像文件才能生
成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。
同一个 image 文件,可以生成多个同时运行的容器实例。
image 文件生成的容器实例,本身也是一个文件,称为镜像文件。
一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,
也就是我们的容器至于仓库,就是放了一堆镜像的地方,我们可以把镜像发布到仓库中,需要的时候从仓库中拉下来就可以了。
环境说明 我们使用的是 CentOS 7 (64-bit)
目前,CentOS 仅发行版本中的内核支持 Docker。
Docker 运行在 CentOS 7 上,要求系统为64位、系统内核版本为 3.10 以上。
查看自己的内核:
uname -r #打印当前系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型等) 结果如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <style> div { height: 200px; width: 500px; background-color: black; margin: 50px auto; color: aliceblue; } button { background-color: aquamarine; } p { height: 100px; width: 300px; background-color: skyblue; margin: auto; margin-top: 25px; text-align: center; line-height: 100px; font-size: 20px; } </style> <body> <div> <button>开始</button> <button>停止</button> <p></p> </div> <script> var arr = ['上三', '钢弹', '狗子', '老六', '小气', '王五']; var btn1 = document.
博主目前在蚂蚁集团-体验技术部,AntV/S2 是博主所在团队的开源项目——多维交叉分析表格,欢迎使用,感谢到 S2 github 仓库点赞 star,有任何关于前端面试、就业、技术问题都可给在文章后留言。
对于做前端的朋友,相信看到像素(pixel)、分辨率(resolution)、CSS长度单位这些概念都不陌生,但是对它们之间的关系是否清楚呢?以及如何区分应用场景?本文将带你搞懂这些内容。
一、像素 像素是图像的基本采样单位,它不是一个确定的物理量,也不是一个具体的点或小方块(尽管可以用点或小方块来呈现),而是一个抽象概念。
不同的设备,其图像基本单位是不同的,比如显示器的点距,可以认为是显示器的物理像素。现在的液晶显示器的点距一般在0.25mm到0.3mm之间。
液晶显示器点距参考表(1 英寸 = 2.54 厘米):
尺寸规格点距15.6英寸16:9宽屏(1366×768)0.252mm×0.252mm17英寸16:10宽屏(1440×900)0.255mm×0.255mm17英寸5:4普屏(1280×1024)0.264mm×0.264mm18.5英寸16:9宽屏(1366×768)0.300mm×0.300mm19英寸16:10宽屏(1440×900)0.285mm×0.285mm19英寸16:10宽屏(1680×1050)0.244mm×0.244mm19英寸5:4普屏(1280×1024)0.294mm×0.294mm20英寸5:4普屏(1400×1050)0.292mm×0.292mm20英寸5:4普屏(1600×1200)0.255mm×0.255mm20英寸16:9宽屏(1600×900)0.276mm×0.276mm20英寸16:10宽屏(1680×1050)0.258mm×0.258mm21.5英寸16:9宽屏(1920×1080)0.248mm×0.248mm21.6英寸16:10宽屏(1680×1050)0.276mm×0.276mm22英寸16:10宽屏(1680×105)0.282mm×0.282mm23英寸16:9宽屏(1920×1080)0.266mm×0.266mm23英寸16:9宽屏(2048×1152)0.249mm×0.249mm23英寸16:10宽屏(1920×1200)0.258mm×0.258mm24英寸16:9宽屏(1920×1080)0.276mm×0.276mm24英寸16:10宽屏(1920×1200)0.27mm×0.27mm25.5英寸16:10宽屏(1920×1200)0.2865mm×0.2865mm27英寸16:10宽屏(1920×1200)0.303mm×0.303mm30英寸16:10宽屏(2560×1600)0.2505mm×0.2505mm而打印机的墨点,也可以认为是打印机的物理像素,300DPI就是0.085mm,600DPI就是0.042mm。 接下来介绍关于像素的几个概念:
设备像素: 设备的物理像素,其尺寸大小是绝对的。
逻辑像素: CSS 的像素单位,其尺寸大小是相对的,也称为独立像素。
DPI(dots per inch): 像素密度,表示水平或垂直方向每英寸长度的像素数目。
PPI(pixels per inch): 像素密度,表示沿对角线每英寸长度的像素数目。
缩放因子(Scale Factor): 逻辑像素相对于设备像素的放大比例,可通过 window.devicePixelRatio 获得,但二者并不完全等同。
设备像素 = 逻辑像素 × 缩放因子
设备像素都是固定的,所以逻辑像素大小由缩放因子决定。对于桌面设备,逻辑像素通常就等同于物理像素,本来是不用考虑缩放问题的。而现在屏幕变得越来越高清,PPI 越来越大,如果没有缩放,所有的东西看起来都会比较小,因此需要放大。所以决定缩放因子大小的,就是像素密度,密度越大、越高清的屏幕,需要的缩放比例就越大。
PC 上的缩放比例是自定义的,而移动端的缩放比例是通过 viewport 确定的,viewport 就是屏幕那块固定的可视区域。默认情况下,移动端浏览器会将 viewport 宽度设为980px(也有可能是1024px 或其它值),也就是说1px = 设备屏幕宽度的1/980。这跟缩放因子没有任何关系。这时的1px 非常小,所有的元素都变得非常小,移动端浏览器之所以这么做,是为了尽可能完整的显示 PC 端的网页,然后允许用户通过缩放来查看细节。
如果我们不希望采用默认的设置,就需要人为设置 viewport:<meta name=“viewport” content=“width=device-width”>
将 viewport 宽度设为设备宽度,就跟缩放因子有关了。比如:iphone6(750 × 1334)的 PPI 是326,缩放因子是2,所以1个逻辑像素的大小等于2个设备像素。对于 iphone6,1px = 屏幕宽度的1/375,相比1/980放大了不少,而这时候的1px 就是一个比较理想的大小,即比较符合我们在 PC 端使用 px 时的感受。
目录 一、下载项目到本地二、三板斧1. git add2. git commitgit push 初次在Linux上使用git需要先登录: git config --global user.name “用户名” git config --global user.email “邮箱” 一、下载项目到本地 创建好一个放置代码的目录
git clone [url] 这里的url就是项目的链接。
二、三板斧 1. git add 将代码放到目录中
git add [文件名] 将需要用git管理的文件告知git
2. git commit 提交改动到本地
git commit -m "提交日志" . 最后的“.”表示当前目录
提交的时候应该注明提交日志,描述改动的详细内容。
git log //用于查看过去提交记录 git push 同步到远程服务器上
git push 需要填入用户名和密码,同步成功后刷新gitee或github页面就能看到代码改动了。
C语言结构体占用内存原理解析 结构体内存原理解析:共用体内存原理解析:sizeof计算结构体内存占用需要注意 结构体内存原理解析: 结构体在内存中的存储有以下规则:
结构体成员中的起始地址应该是该成员所占内存的整数倍,如果不足整数倍需要补齐结构体所占内存为结构体成员中最大的基础数据类型的整数倍。
这里说下基础类型:int,short,char,long,long long,double,float
规则1解析: typedef struct{ char a; int b; }Msg; 结构体Msg在内存中的存储方式如下图所示:
a占用了第0个字节,b并没有占用第一个字节,因为b的起始位置要是b的整数倍,所以b空了3个字节占用了4,5,6,7字节。所以这个结构体sizeof的结果就是8;
规则2解析:
typedef struct { int a; char c[6]; }Data; typedef struct{ double head; Data data; }Msg; 结构体Msg的存储方式如下:
head占用了0-7共8个字节,结构体Data中的成员a占用了8-11共4个字节字符串c占用了12-17共6个字节,此时该结构体共占内存18个字节,但是规则2中规定了结构所占内存为成员中最大基本类型的整数倍,最小基准类型为double,所以为8的整数倍2乘以8<18<3乘以8;故此结构体Msg占内存3*8=24个字节。如果子结构体中的成员类型为最大基本类型,那么结构体所占内存就是子结构体中最大基本类型的整数倍。下面举例:
typedef struct { double a; char c[3]; }Data; typedef struct{ int head; Data data; }Msg; 结构体Msg的存储方式如下:
head占用4个字节,子结构体成员a占用8个字节此时注意规则1,所以空4个字节从8-15存储a,字符串的基本类型是char所以不用空,共占用19个字节下面考虑对其补齐:
如果按照结构体成员最大类型int为最大基本类型算出来所占内存就是20字节;如果按照最大类型为子结构体(子结构体所占内存为16字节)为最大类型算出来所占内存就是就是32字节;如果按照子结构体和子结构体成员基本类型为最大类型(double为最大基本类型)那么算出所占内存就为24字节。
上面总结了三种对其方式,C语言中的补齐方式为第3种,前2种也是读者在计算结构体占用内存可能出现错误的地方。所以规则2中强调的是基本类型,不包括结构体,共用体这种。 通过上面的存储方式分析,希望读者在定义结构体时成员顺序要有考量,否则会导致无效的内存占用:
typedef struct{ char b; int head; char a; }Msg; 上面这么定义结构体占用内存空间为12字节;
下面两种定义方式结构体占用内存空间为8字节;
typedef struct{ int head; char b; char a; }Msg; typedef struct{ char b; char a; int head; }Msg; 共用体内存原理解析: 共用体多个数据成员只能同时存在一种,并不是将空间分配给每个成员,而是只按照最大成员的大小分配内存空间。如果共用体中出现结构体,那么就先算出结构体所占空间,和其他成员比较所占内存大小,按照最大的成员分配内存空间,同时需满足最大基本类型整数倍原则。
java -jar arthas-boot.jar
选择要修改的进程
jad --source-only com.demo.Demo > Demo.java
sc -d com.demo.Demo
会获取到一个 classLoaderHash 1554909b
mc -c 1554909b /home/jar/Demo.java -d /home/jar
使用第四步获取到的hash值重新编译,/home/jar是启动arthas的目录,第三步生成的java会保存到这
redefine /home/jar/com/demo/Demo.class
热更新
目录
一、对象定义的三大方法
1、直接以对象类型定义
2、通过函数构建
3、通过Object构造器自定义
二、对象属性名和属性值的获取与删除
1、获取方法
2、属性删除
3、getters和setters
三、this引用对象
四、对象的继承
1、原型对象和原型链
2、基于原型链的继承方法
3、prototype的使用
五、对象的比较(从内存角度理解)
1、比较对象怪象
2、解释该现象
一、对象定义的三大方法 1、直接以对象类型定义 此方法即是按照我们所理解的对象形式,直接按照{}组织定义,如下:但是这样构造出来的对象无法调用其原型prototype也无法基于原型链创造孩子。
var test={ aIndex:'1', bIndex:0, cIndex:'hello' displayType : function() { console.log(this.aIndex); } }; 2、通过函数构建 函数方法就是将定义的函数作为对象去处理,如下:
function Car(make, model, year) { this.make = make; this.model = model; this.year = year; //this引用,定义属性的属性值 //也可以定义方法 this.displayType = function() { console.log(this.make); } } var mycar = new Car("Eagle", "Talon TSi", 1993); //创建对象实例 mycar.displayType(); //调用方法 3、通过Object构造器自定义 利用原型对象Object的构造器进行定义,如下:但是这样构造出来的对象无法调用其原型prototype也无法基于原型链创造孩子。
Element UI 中的表格组件提供了一个名为 "body-scrolling" 的事件,你可以监听这个事件来实现滚动到底部加载更多的功能。
下面是一个简单的示例:
<template> <el-table :data="tableData" @body-scrolling="loadMoreData"> <!-- table columns --> </el-table> </template> <script> export default { data() { return { tableData: [], }; },
在日常工作中我们经常收到一些诸如此类需求:“用户给点击了开屏广告,给用户下发私信”、“用户进入了推荐线,但在60秒内没有任何点击操作,弹框引导用户选择感兴趣的内容”、“用户点赞了某位作者的两篇以上的内容,但并没有关注过此作者,则弹框引导用户关注作者”、“用户点击了活动入口,进入了活动页、发生了点赞、收藏等交互操作,引导用户进入活动下一流程”。这些需求大致可以分为如下三大类:
完成事件A,触发运营动作。完成时间A多次,触发运营动作。在固定时间内完成事件A,但未完成事件B,触发运营动作。依次完成事件A,B,C,触发运营动作。 这些需求从开发角度来看,代码有很高的相似性,所以我们对这些需求进行了抽象,基于flink开发了一套行为规则引擎,并在规则引擎之上将常用的运营动作模块化,真正做到十分钟上线一个运营策略,相对之前天级别的交付时间,效率大幅提升。
先看下规则引擎整体的架构:
一个任务上线,从“数据流输入”到“用户触达”,整个任务流程分为6个阶段:输入事件流、数据准备、规则平台、维度数据、规则引擎、用户触达系统。
输入事件流
数据主要来自于行为日志,也就是用户通过sdk上报的埋点数据以及后端埋点数据。为了后规则引擎易于处理,通常会对一些嵌套数据进行扁平化操作。
数据准备
这个阶段的主要工作就是为规则引擎准备输入数据,分为四个步骤:数据预处理、数据预过滤、数据流维度补充、数据流分区。
规则平台
规则平台面向的用户主要是运营。运营人员通过规则平台配置运营策略。规则平台会将这些规则分发给规则引擎,规则引擎将规则转换成处理逻辑。
维度数据
维度数据包含三部分:画像数据、业务库数据以及用户历史行为数据。这些数据在数据准备阶段会填充到数据流中,后续会介绍。
规则引擎
目前规则引擎支持四种规则类型,在实现上分别对应一个flink程序:
完成事件A完成事件A多次完成事件A、未完成事件B依次完成事件A、B、C、D 接下来我们通过举例,从易到难的方式,介绍规则引擎的数据处理流程。
第一个例子:用户发生点赞行为(规则类型1)
输入数据流:
{ "uid":111, "oid":"562asdf12", "action":"like", "time":"1672383110" } 这条数据意思为:用户(uid:111)在时间(time:1672383110)对内容(oid:562asdf12)进行了点赞操作(action:like),这个场景再简单不过了。
我们需要通过规则平台告诉规则引擎如何处理这个需求,例如我们先定义了一个能满足当前需求的规则串
{ "rule_id":"00001", "rule_type":"1", "conditions":{ "action":"like" } } 稍微解释字段含义
rule_id:规则id,规则唯一标识
rule_type:规则类型,当前规则为“完成事件A”,故该值为“1”.
conditions:规则引擎需要判定条件。
在这个例子中flink规则引擎只要判断数据流中的action的值是否为“like”。
第二个例子:用户触发点赞行为2次。(规则类型2)
和第一个例子不一样的地方在于这个例子出现计数场景。先看下规则串和之前的例子有什么不同
{ "rule_id":"000012", "rule_type":"2", "pk":"rule_id::uid", "conditions":{ "action":"like", "eventCount":"eq:2" } } rule_type:2,告诉规则引擎这是个”完成事件A多次“的任务,并且规则串新增属性pk、eventCount。‘pk’代表分区键,对应这flink程序中keyby中的字段,“eventCount”:"eq:2"在这个例子中代表:点赞次数等于2
第三个例子:用户给同一作者文章点赞超过2次(规则类型2)
在这个例子中需要用到作者信息,但是数据流中并没有。这就需要介绍下”数据预处理“部分。
”数据预处理“阶段会干两件事:补充数据主体、数据扁平化。
数据主体什么意思?对于一款UGC产品,最核心的主体包括:用户、内容、作者等。电商产品,主体包括:用户、商家、商品、品牌等。在我们的规则引擎里,数据主体通常作为关联数据的主键id,所以在数据预处理阶段,我们需要尽可能的将数据主体梳理全,并补充到数据中。在这个例子中我们可以通过oid,把作者id补充到数据中去。
{ "uid":111, "oid":"562asdf12", "action":"like", "time":"1672383110", "author_id":12454 } “数据扁平化”:为了让规则引擎更好的处理数据,我们会在数据预处理阶段把嵌套的数据进行扁平化操作。
回到例子,规则串可以如下描述
{ "rule_id":"000012", "rule_type":"2", "pk":"rule_id::uid::author_id", "conditions":{ "
二叉树的遍历是最基础的算法,也是比较简单的算法,作为一名大学生这是我们必须掌握的基础知识。因为遍历的思路很简单,所以今天这篇是纯代码篇,我们直接在代码中学习。
目录
一、二叉树前序遍历
二、二叉树的中序遍历
三、二叉树的后序遍历
四、二叉树的层序遍历
一、二叉树前序遍历 题目链接:力扣
前序遍历的遍历顺序:根 左 右
所以这道题就很简单了,我们可以写出递归版本和迭代版本的代码。
递归版:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public: vector<int> res; vector<int> preorderTraversal(TreeNode* root) { dfs(root); return res; } void dfs(TreeNode* root){ if(root == nullptr) return; res.
目录
一、为什么要调度
二、调度均衡
三、进程调度框架
3.1 调度队列
3.2 进程唤醒
3.3 调度时机
主动调度:
被动调度:
四、调度算法
4.1 先来先服务调度算法
4.2 最短作业优先调度算法
4.3 高响应比优先调度算法
4.4 时间片轮转调度算法
4.5 最高优先级调度算法
4.6 多级反馈队列调度算法
一、为什么要调度 早期的计算机没有调度,程序只能一个一个地运行,一个进程死亡之后才能去运行下一个进程。这里面首先存在的问题就是我们没法同时运行多个进程。其次就算我们不需要同时运行多个进程,程序在运行的过程中如果要等IO,CPU就只能空转,这也十分浪费CPU资源。
后来协作式多任务诞生了,当程序由于要等IO而阻塞时就会去调度执行其它的进程。但是协作式多任务存在着很大的问题,就是每个进程运行的时间片长短是不确定的,而且是很偶然很随机的。如果一个进程它一直在做运算就是不进行IO操作,那么它就会一直霸占CPU。
后来随着计算机的普及,以及计算机的使用者和程序员这两个角色的分离,强制性多任务产生了,也就是抢占式多任务。抢占式多任务使得每个进程都可以相对公平地平分CPU时间,如果一个进程运行了过长的时间就会被强制性地调度出去,不管这个进程是否愿意。有了抢占式多任务,我们在宏观上不仅可以同时运行多个进程,而且它们会一起齐头并进地往前运行,不会出现某个进程被饿死的情况,这样我们使用电脑的体验就非常完美了。抢占式多任务和协作式多任务不是对立的,它们是相互独立的,可以同时存在于系统中。
抢占又分为用户抢占和内核抢占。由于抢占对进程来说是异步的,进程被抢占时不一定运行在什么地方,有可能运行在用户空间,也有可能运行在内核空间(进程通过系统调用进入内核空间)。如果抢占点是在用户空间,那么抢占就是安全的,如果在内核空间就不一定安全,这是为什么呢?因为对于用户空间来说,如果抢占会导致线程同步问题,那么用户空间有责任使用线程同步机制来保护临界区,只要用户空间做好同步就不会出问题。如果内核也做好了同步措施,内核抢占也不会出问题。
所以如果没有调度的话,就不能实现多任务,一次就只能运行一个程序,我们使用电脑的体验就会大大降低。有了调度就有了多任务,我们就能同时执行很多程序。
二、调度均衡 调度均衡可以分为个体均衡和总体均衡。
个体均衡是从进程的角度出发选择到一个相对清闲的CPU上去运行。总体均衡是从CPU的角度出发如何从别的CPU上拉取一些进程到自己这来执行,使得所有CPU的工作量尽量平均。个体均衡的触发点有三个:一是新进程刚创建时,二是进程要执行新程序时,三是进程被唤醒时,在这三个点进程都可以选择去哪个CPU的运行队列上去等待执行。在个体均衡下,每个进程都尽量选择相对清闲的CPU,所以所有CPU的负载应该还是会比较均衡的。但是时间长了可能还是会出现负载不均衡的情况,此时就要进行总体均衡了。总体均衡的触发点有三个:一是CPU即将idle前会去找到最忙的CPU然后拉取一些任务过来;二是定时器中断的周期性检测,会检查是否所有的CPU都一样忙,如果忙闲差别太大就会进行进程迁移,使得所有CPU忙闲程度接近;三是在idle进程中如果CPU发现自己太忙而有的CPU在idle就会唤醒那个CPU进行负载均衡。
三、进程调度框架 3.1 调度队列 我们先来看一下进程的状态转换图。
处于就绪(Runnable)状态的进程可以被调度到CPU上去执行。但是处于就绪状态的进程可能不止一个,所以我们需要一个运行队列来安放所有就绪的进程,由于CPU也不止一个,所以我们需要NR_CPU个运行队列。
我们看一下调度队列的定义(代码经过了高度删减):linux-src/kernel/sched/sched.h
struct rq { raw_spinlock_t __lock; unsigned int nr_running; struct cfs_rq cfs; struct rt_rq rt; struct dl_rq dl; struct task_struct __rcu *curr; struct task_struct *idle; struct task_struct *stop; int cpu; int online; }; linux-src/kernel/sched/core.
一、剑指 Offer 17. 打印从1到最大的n位数 题目链接:力扣
题目描述:输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
示例 1:
输入: n = 1 输出: [1,2,3,4,5,6,7,8,9] 题目解析:这道题很简单,求出10的n次方,然后遍历存到数组中就行了。
解题代码:
class Solution { public: vector<int> printNumbers(int n) { vector<int> res; for(int i=1;i<pow(10,n);i++){ res.push_back(i); } return res; } }; 二、剑指 Offer 18. 删除链表的节点 题目链接:给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。返回删除后的链表的头节点。
示例 1:
输入: head = [4,5,1,9], val = 5 输出: [4,1,9] 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
使用JS的函数功能,获取屏幕的宽度和高度,并实现居中效果。登录区域设置一定的宽度和高度;打开登录页面时,登录区在浏览器水平、垂直方向上都居中。登录过程中会有相应的提示功能,输入正确后会显示登录成功,否则失败。
CSS部分:
<style> body{ background-image: url(风景.jpg); background-position: 60% 100%; background-size:cover;} div#login{ line-height: 3; font-family: 楷体; font-size: 18px; padding: 20px; background: no-repeat; border: 3px solid black; background-color:azure; width: 300px; position:fixed;} </style> HTML部分:
<body> <div id="login"> 用户名:<input id="Na" type="text" class="inputs" onchange="Name()"> <div id="name" class="red" style="color: red;"></div> 密 码:<input id="pwd" type="password" onchange="checkPwd()"> <div id="pwdId" class="red" style="color: red;"></div> <input type="button" value="登录"> <input type="reset" value="重置"> </div> </body> Javascript部分:
<script> var loginDiv = document.getElementById("login"); var divW = loginDiv.
2023.1.11今天我学习了使用element el-select组件下拉框选择数据失效的原因以及解决办法。
如图:
当我已经选择启用状态的时候,然后点击停用状态没反应。
原因: 是因为在配置表单的过程中,重复使用了这个字段。
如:
this.form.status = row.data.status <el-form-item label="状态" prop="status"> <el-select v-model="form.status"> <el-option :label="label" > </el-option> </el-select> </el-form-item> 就是在表单中重复使用了status这个字段,然后导致选择失效。
解决办法: 在el-select加入@change事件,进行强制渲染,这样就可以完成下拉框的选择。
<el-form-item label="状态" prop="status"> <el-select v-model="form.status" @change="change"> <el-option :label="label" > </el-option> </el-select> </el-form-item> change(){ //强制渲染 this.$forceUpdate() }
import os, random, shutil def moveFile(fileDir, tarDir, picknumber, moname): """ Parameter: fileDir: 原图片文件夹 tarDir: 接受文件夹 picknumber: 图片选取的数量 moname: 要重命名的图片名字,在本函数中图片名字会被重命名为:{moname} + {count} + ".jpg", 其中".jpg"为图片的原格式。这个可以自己修改 """ pathDir = os.listdir(fileDir) sample = random.sample(pathDir, picknumber) count = 1 for name in sample: shutil.move(fileDir + name, tarDir + name) os.rename(os.path.join(tarDir, name), os.path.join(tarDir, moname + str(count) + ".jpg")) print(os.path.join(tarDir, moname + str(count) + ".jpg")) count += 1 if __name__ == "__main__": fileDir = "D:/LearnDeep/COCO/val2014/" tarDir = "
一、基础知识 1.1 Linux系统的文件结构 /bin 二进制文件,系统常规命令 /boot 系统启动分区,系统启动时读取的文件 /dev 设备文件 /etc 大多数配置文件 /home 普通用户的家目录 /lib 32位函数库 /lib64 64位库 /media 手动临时挂载点 /mnt 手动临时挂载点 /opt 第三方软件安装位置 /proc 进程信息及硬件信息 /root 临时设备的默认挂载点 /sbin 系统管理命令 /srv 数据 /var 数据 /sys 内核相关信息 /tmp 临时文件 /usr 用户相关设定 1.2 Linux系统命令行的含义 示例:root@app00:~# root //用户名,root为超级用户@ //分隔符app00 //主机名称~ //当前所在目录,默认用户目录为~,会随着目录切换而变化,例如:(root@app00:/bin# ,当前位置在bin目录下)# //表示当前用户是超级用户,普通用户为$,例如:("yao@app00:/root$" ,表示使用用户"yao"访问/root文件夹) 1.3 命令的组成 示例:命令 参数名 参数值 二、基础操作 2.1 重启系统 (1)立刻关机 shutdown -h now 或者 poweroff (2)两分钟后关机 shutdown -h 2 2.2 关闭系统 (1)立刻重启 shutdown -r now 或者 reboot (2)两分钟后重启 shutdown -r 2 2.
4261孤独的照片 分辨具体情况,计算值的主要部分可以通过规律找到左右“值”的计算和 注意连续处理及可以用函数max等简化判断语句 4344上课睡觉 重在推导值,乘积形式和因数相关,1...根号n 遍历可从大值开始遍历 x/i 3443学分绩点 printf("%.2lf",ans);//保留两位小数 4645选数异或 dp思路真的强,重点注意三个值的异或关系 4653数位排序 在获取值的时候做处理计算,比较时能简化运算 4655重新排序 差分很神奇,没有想到可以直接统计次数,用次数和值来*得到中间结果,统计次数 b[l]++,b[r+1]--;//差分 for(int i=1;i<=n;i++){ b[i]+=b[i-1]; }
1、引言 最近需要复现一篇论文的工作,该工作代码已经在github上开源了,开始采用网页界面下载压缩包的方式,但是发现该github项目内嵌套了其他github子项目,直接下载压缩包会导致子项目文件夹下为空白,因此需要使用以下命令:
git clone --recursive https://github.com/nvlabs/instant-ngp 但是发现git clone命令下载的非常慢,后续查了是需要将github代理改一下。
2、GitHub设置代理 该部分主要是参考《Git 配置代理,高速拉取GitHub项目》
我再写一次教程只是为了自己日后查阅方便。
1、首先需要查看自己的端口号,我的上网工具终端设置界面内可以查看(如下图),找不到端口号的可以参考这个视频:
2、再打开C:\Users\UserName.gitconfig文件,输入以下内容:
[http] proxy = http://127.0.0.1:55681 [https] proxy = http://127.0.0.1:55681 至此,就完成了,配置ssh部分由于项目用不到暂时没有设置,有需要可以参考《Git 配置代理,高速拉取GitHub项目》进行配置。
LVS负载均衡 1.LVS服务简述 1.1lvs服务简介 LVS(Linux Virtual Server)即Linux虚拟服务器,是一个虚拟的服务器集群系统,该项目是1998年5月由章文嵩博士主导的开源负载均衡项目,是国内最早出现的自由软件项目之一。目前 LVS 已经被集成到Linux内核模块中。
通过LVS的负载均衡技术和LINUX操作系统可以实现一个高性能、高可用的LINUX服务器集群,它具有良好的可靠性、可扩展性和可操作性。LVS架构从逻辑上可分为调度层、Server集群层和共享存储层。
1.2LVS的发展与组成 1.IPVS(LVS)的发展史 (1)在Linux2.2内核时,IPVS就已经以内核补丁的形式出现。
(2)从Linux2.4.24版本以后,IIPVS便成为Linux官方标准内核的一部分。
2.LVS的组成 LVS由两部分程序组成,即IPVS和IPVSADM。
IPVS:IP Virtual Server的缩写,其代码工作在系统内核空间,也是实现调度的代码段。
IPVSADM:工作在用户空间,负责为IPVS内核框架编写规则,定义谁是前端集群服务器,谁是后端真实服务器(Real Server)。
1.3.为什么需要LVS 简单来说,当并发连接数超过了Ngix的负载上限时,就需要使用LVS了。就目前实际环境来讲,日均页面访问量(pv)在1000万~2000万或并发量在5万以下时都可以使用Nginx。流量超过这个标准或一些大型的门户网站、电商平台也会使用LVS,这是因为它们的流量或并发量随时可能存在高峰时段,或者说可能在某个点会超过以往所有的流量峰值。
LVS与Nginx的功能对比如下。
(1)、LVS比Nginx具有更强的抗负载能力,性能比较高(能达到F5性能的60%左右),而且LVS工作在网络4层仅做请求分发之用,没有流量,所以在效率上基本不需要太过考虑,且对内存和CPU资源消耗比较低,只考验网卡或 linux2.4 内核的承载能力。
Nginx则工作在网络的应用层,可以针对HTTP应用实施一些分流策略。
(2)、LVS安装配置比较简单,对网络的依赖较大,但稳定性较高。Ngix安装配置相对复杂,对网络的依赖较小。
(3)、LVS不支持正则匹配处理,不能做动静态分离,而Ngx具有这方面的功能。
(4)、LVS适用的协议范围较广。Nginx仅能支持HTTP、HTTPS、Email协议,因此适用范围就大大缩小了。
(5)、基本上能支持所有应用,因为lvs工作在4层,所以它可以对几乎所有应用做负载均衡,包括httP、数据库、聊天室等等。
注:LVS 需要手工动态增加命令,所以需要 Keepalived 来实现自动配合。
常见负载均衡对比优势缺点硬件:F5性能好技术支持价格昂贵购买2台1对.Ivs工作四层效率极其高对数据做的转发负载 均衡在低数据量的效率不高,高效率需要在大数据量才体现(运维成本较高)nginx使用简单 支持4层(1.9版本后支持)和7层反 向代理缓存流量镜像处理数据代理模式替用户去查找找到后发送给用户并发 较大(5w以上)haproxy相对复杂支持4层和7层反向代理处理数据代理模式替用户去查找找到后发送给用户并发 较大(10w以上比nginx多) 14.需了解arp协议 arp解析过程
1.发出广播请求ip对应的mac地址是?Who has10.0.0.8?Tell10.0.0.7
2.发出响应单播告诉对方我的mac地址是xXXx
3.0.8发请请求询问0.7的mac地址单播
4.0.7把自己mac地址发送给.8
2、ipvsadm命令及参数介绍 部署和配置LVS服务会经常用到一些命令,如ipvsadm,可以使用“ipvsadm一help”命令查看使用帮助。
ipvsadm命令的常用参数及其说明如下。
参数说明-C清空配置列表-A增加虚拟vip服务-E编辑虚拟vip服务-D删除虚拟vip服务-a添加真实主机-e编辑真实主机配置-d删除真实主机配置-L显示详细列表信息-h显示帮助信息-s指定算法-g指定DR模式(默认的模式)-i指定TUN模式-m指定NAT模式-w指定权重参数-c查看连接数–timeout查看超时–daemon进程输出信息–states输出静态信息-n以数字形式输出信息 ipvsadm命令还有其他一些不常用的参数,可以访问官方网站了解。
LVS中文官网: http://zh.linuxvirtualserver.org/
1.3LVS相关的术语 在学习LVS服务时,首先要了解VS中相关的专业术语,以便更好地理解与掌握LVS服务。
LVS相关术语及其说明如下表。
术语说明DS (Director Server)前端负载均衡节点服务器RS (Real Server)后端真实服务器DIP (Director Server IP)用于与内部主机通信的IP地址VIP (Virtual IP)向外部直接面向用户请求,用于用户请求的目标IP地址RIP (Real Server IP)后端真实服务器的IP地址CIP (Client IP)访问客户端的IP地址 3、LVS的工作模式 3.
最近在频繁地配环境,期间需要导入cv2这个包。需要注意的是,虽然我们编写代码时是import cv2,但在导入包时,pip的应该是opencv-python。
以下是我导入cv2包的两种亲测有用的方法:
1. 使用pip
pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple some-package 2. 使用conda
conda install -c menpo opencv 最后简单地谈一下cv2和OpenCV的关系:OpenCV是一个用C/C++编写的开源的计算机视觉库,具有Python、Java、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。cv2表示调用的是用C++开发的OpenCV的接口。
永远相信美好的事情即将发生。
准备后台
后台源代码分享 。。 。。
ssm-oa.rar - 蓝奏云
前端测试代码分享
oa-mini.rar - 蓝奏云
前端发送请求封装
Promise
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
promise运行中有三个状态: pending: 等待 (进行中) promise一创建出来,就是pending进行中fulfilled: 成功 (已完成), 调用 resolve, 就会将状态从pending改成fulfilled, 且将来就会执行.thenrejected: 失败 (拒绝), 调用 reject, 就会将状态从pending改成rejected, 且将来就会执行.catch注意点: 一旦promise的状态发生变化, 状态就会被凝固如果再调用reject或resolve,进行状态修改就没有意义了 准配请求接口地址
创建config/api.js
// 以下是业务服务器API地址 // 本机开发API地址 var WxApiRoot = 'http://localhost:8080/wx/'; // 测试环境部署api地址 // var WxApiRoot = 'http://192.168.0.101:8070/demo/wx/'; // 线上平台api地址 //var WxApiRoot = 'https://www.oa-mini.com/demo/wx/'; module.exports = { IndexUrl: WxApiRoot + 'home/index', //首页数据接口 SwiperImgs: WxApiRoot+'swiperImgs', MettingInfos: WxApiRoot+'meeting/list', AuthLoginByWeixin: WxApiRoot + 'auth/login_by_weixin', //微信登录 UserIndex: WxApiRoot + 'user/index', //个人页面用户相关信息 AuthLogout: WxApiRoot + 'auth/logout', //账号登出 AuthBindPhone: WxApiRoot + 'auth/bindPhone' //绑定微信手机号 }; 封装request
一、system()函数 1、头文件#include <stdlib>
2、()里面可以写①cmd命令
②可以打开外部程序用 \\或者/
二、数据类型 1、基本类型 整型: int short long long long 字符型:char
实型:float double 2、printf("%.2f",变量名);
3、宏定义#define
typedef
4、无符号整型使用%u、
5、十六进制前面加上 0x
6、短整型 %hd ,长整型 %ld ,长长整型 %lld
7、小数据类型可以给大数据类型
但是大数据类型不可以给小数据类型,会造成高位数据丢失
8、常用转义字符
\n 换行(顾名思义跳到下一行的竖形未知) \r 回车(跳到改行的开始) \t 等价于TAB键
9、double %lf
float %f
%p 显示十六进制的内存地址
10、有符号和无符号的取值范围
(1)8bit的数据区间 -2*7~(2*7-1)
(2)int/long -2*15~(2*15-1) / -2*31 ~(2*31-1)
(3)long long -2*63~(2*63-1)
(4)float 1.17x10*(-38)~3.4x10*(38)
(5)double 2.23x10(-308)~1.8x10*308
(6)3.36x10*(-4032)~1.19x10*4932
11、类型限定
extern 声明一个变量(在A文件中显示B文件的变量)
const 定义一个常量
volatile 防止编译器优化
register 定义寄存器变量 调高效率
项目场景: 芯片:STM32F411CEU6和STM32F429IGT6
MDK版本:5,32
HAL库版本:1.27.1
STM32CubeMX版本:6.7.0
问题描述: 在使用DMA的情况下,串口发送的数据不更新,无论发送缓冲区内容是什么都只发送第一次发送的数据。
硬件配置 下面是STM32CubeMX的串口、DMA以及中断配置:
注:USART1的DMA中断开不开效果相同,都会出现上述问题,开了中断记得清除标志位。
问题代码以及错误现象 void UART1_Send_AT_Cmd(char *at_cmd) { char *AT_CMD = at_cmd; int AT_length = strlen(AT_CMD); HAL_UART_Transmit_DMA(&huart1, (const uint8_t *)AT_CMD, AT_length); while(__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TCIF3_7) == SET); __HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx, DMA_FLAG_TCIF3_7); __HAL_DMA_ENABLE(&hdma_usart1_tx); //使能串口DMA发送 } //定义全局变量或者局部变量是一样 的效果 char a* = "ccc"; char b* = "aaa"; int main(void) { //省略CubeMX生成的初始化 UART1_Send_AT_Cmd(a); //HAL_Delay(500); //延时加不加也是同样的问题 UART1_Send_AT_Cmd(b); while(1) { UART1_Send_AT_Cmd(a); //HAL_Delay(500); //延时加不加也是同样的问题 UART1_Send_AT_Cmd(b); HAL_Delay(500); HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);//这条的目的是检查是不是发生了中断,或者发生中断没有清除标志位 HAL_Delay(500); } } 串口助手的现象
一直发送*a的字符,*b的字符看都看不到,而且灯也在闪烁,说明DMA发送是正常的,芯片工作也是正常的。
工作总结
BigDecimal使用小结 当业务涉及到大数的精确计算,比如钱或者重量等有小数点且要求一定精度的数值时,常常会使用BigDecimal类型定义该字段,这里列举了一些BigDecimal的常用用法
1).获取BigDecimal数值 1. 直接定义变量并赋值 BigDecimal money100 = new BigDecimal(100); 2. 直接获取常量值 //获取BigDecimal类型的0 BigDecimal money0 = BigDecimal.ZERO; //获取BigDecimal类型的1 BigDecimal money1 = BigDecimal.ONE; //获取BigDecimal类型的10 BigDecimal money10 = BigDecimal.TEN; 3. 其他类型的数值转BigDecimal //new BigDecimal()会有精度问题,所以建议使用字符串去创建对象而不是浮点类型 //BigDecimal.valueOf()底层使用的就是用字符串去创建对象,确保精度不会丢失 //获取BigDecimal类型的整数 BigDecimal money11 = BigDecimal.valueOf(11); //获取BigDecimal类型的浮点数 BigDecimal money1_1 = BigDecimal.valueOf(1.1); 2).常用BigDecimal函数 /** * 四则运算 */ //加-add():100+1 BigDecimal money101 = money100.add(money1); //减-subtract():100-1 BigDecimal money99 = money100.subtract(money1); //乘-multiply():10*1.1 BigDecimal money11 = money10.multiply(money1_1); //整除-divide()(不整除时抛异常java.lang.ArithmeticException):99/11 BigDecimal money9 = money99.divide(money11); //不整除-divide(BigDecimal divisor, int scale, int roundingMode):101/11 //divisor:除数 scale:保留小数位数 roundingMode:舍入策略 BigDecimal money9_18 = money101.
要将一列 object 类型的数据转化为数值型,可以使用 pandas 库的 to_numeric 函数。使用方法如下:
df['column_name'] = pd.to_numeric(df['column_name'], errors='coerce')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <style> div { height: 80px; width: 100px; background-color: black; text-align: center; line-height: 80px; color: white; font-size: 30px; float: left; margin-left: 30px; } </style> <body> <div class="a"></div> <div class="b"></div> <div class="c"></div> <script> var a = document.querySelector('.a'); var b = document.querySelector('.b'); var c = document.querySelector('.c'); times(); setInterval(times, 1000); function times() { var nowTime = new Date(); var inputTime = new Date('2023-10-9 16:00:00'); // 毫秒转为秒 var res = (inputTime - nowTime) / 1000; // 小时 var h = parseInt(res / 60 / 60 % 24); a.
1 题目描述 定义一个 Lingjian 类,拥有整型的数据成员 Weight 和静态数据成员 AllWeights(初始化为 0),每定义一个对象时, 在AllWeights 中增加该零件的重量 Weight;在析构函数中减去 Weight;静态成员函数 GetAllWeights()获取AllWeights。设计程序,定义两个对象之后, 输出类的 AllWeights。其中 Weight 是通过成员函数输入对单个零件重量赋值。
源代码 #include <iostream> using namespace std; class Lingjian { private: int Weight; static int AllWeights; public: static int GetAllWeights() { cout << AllWeights << endl; } Lingjian(int weight) { Weight = weight; AllWeights += Weight; } ~Lingjian() { AllWeights -= Weight; } }; int Lingjian::AllWeights = 0; int main() { int a,b; cin>> a>> b; Lingjian P1(a),P2(b); Lingjian::GetAllWeights() ; return 0; } 2 题目描述 定义狮子 Lion与老虎 Tiger 两个类,二者都有 weight 私有整型属性,定义二者的一个友元函数totalWeight(参数表),计算二者的重量和。设计程序,定义狮子与老虎两个对象之后,调用 totalWeight(参数表),计算二者的重量和,然后输出。其中狮子与老虎的 Weight 是在各自的类成员函数中读数赋值。 源代码 #include <iostream> using namespace std; class Tiger; class Lion; class Lion { private: int Weight; public: Lion(int weight) { Weight = weight; } friend int totalWeight(Lion &P1,Tiger &P2); }; class Tiger { private: int Weight; public: Tiger(int weight) { Weight = weight; } friend int totalWeight(Lion &P1,Tiger &P2); }; int totalWeight(Lion &P1,Tiger &P2) { cout << (P1.
背景 一直以来,Python 没有其他语言的 switch 方法来实现多条件分支,要求支持的呼声很高,Python 3.10.0 支持了它,而且是超级版的,实现的思路与它们大有不同。match 与 case 配合,由 case 从上到下将目标与语句中的每个模式进行比较,直到确认匹配,执行相应的模式下的语句。如果未确认完全匹配,则最终用通配符 _(如提供)将用作匹配情况。如所有的都不匹配且没有通配符,则相当于空操作。
模式由序列、映射、基本数据类型以及类实例构成。 模式匹配使得程序能够从复杂的数据类型中提取信息、根据数据结构实现分支,并基于不同的数据形式应用特定的动作。
Python 3.10 实现的 match 功能是其他开发语言中传统的 switch 的超集,它不仅仅是 switch,可以实现更为复杂的功能。模式匹配大大增加了控制流的清晰度和表达能力。
语法 match subject: case <pattern_1>: <action_1> case <pattern_2>: <action_2> case <pattern_3>: <action_3> case _: <action_wildcard> match 语句接受一个表达式并将其值与以一个或多个 case 语句块形式给出的一系列模式进行比较。 具体来说,模式匹配的操作如下:
给定具有特定类型和结构的数据 (subject)针对 subject 在 match 语句中求值从上到下对 subject 与 case 语句中的每个模式进行比较: 直到确认匹配到一个模式,执行与被确认匹配的模式相关联的动作如果没有确认到一个完全的匹配: 如果提供了使用通配符 _ 的最后一个 case 语句,则它将被用作已匹配模式不存在使用通配符的 case 语句,则整个 match 代码块不执行任何操作 用法 匹配一个字面值
grade = 3 match grade: case 1: print('一年级') case 2: print('二年级') case 3: print('三年级') case _: print('未知年级') # 三年级 匹配后,将执行与该 case 相关的动作:变量名 _ 作为 通配符 并确保目标将总是被匹配,是可选的, 如果之前没有匹配到,那么会执行这个语句 还可以用 | (表示或者)在一个模式中组合几个字面值: