MySQL中默认字符集的设置有四级:服务器级,数据库级,表级,字段级 ,最终是字段级的字符集设置。
注意前三种均为默认设置,并不代表你的字段最终会使用这个字符集设置。
所以我们建议要用show create table table ; 或show full fields from tableName; 来检查当前表中字段的字符集设置。
查看database或一个table的编码
show create database mytestdb;
show create table testapp_article;
创建table的时候就使用 utf8 编码
在每次创建表的时候都在最后加上 character set = utf8 即可:
如:
create table test_table (
id int auto_increment,
title text,
content text,
posted_on datetime,
primary key (id)
) character set = utf8;
修改已有table的编码
使用默认编码创建的table是不能支持中文的,这时候使用如下语句对表testapp_article进行修改:
mysql> alter table testapp_article convert to character set utf8;
mysql> show create table testapp_article;
今天遇到项目中,加过滤器调试麻烦的问题。加上了一个过滤器来处理每次登录的问题。
代码如下:
/** * 将通配符表达式转化为正则表达式 * * @param path * @return */ private String getRegPath(String path) { char[] chars = path.toCharArray(); int len = chars.length; StringBuilder sb = new StringBuilder(); boolean preX = false; for (int i = 0; i < len; i++) { if (chars[i] == '*') {//遇到*字符 if (preX) {//如果是第二次遇到*,则将**替换成.* sb.append(".*"); preX = false; } else if (i + 1 == len) {//如果是遇到单星,且单星是最后一个字符,则直接将*转成[^/]* sb.append("[^/]*"); } else {//否则单星后面还有字符,则不做任何动作,下一把再做动作 preX = true; continue; } } else {//遇到非*字符 if (preX) {//如果上一把是*,则先把上一把的*对应的[^/]*添进来 sb.
1.对ini文件进行序列化和反序列化 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; public class IniDeserialize<T> where T : class, new() { /// <summary> /// 若ini文件中无对应值,就提取默认对象中的值 /// </summary> T _defaultT; /// <summary> /// 序列化后的对象 /// </summary> public T Value { get; set; } IniRW _iniRW; public IniDeserialize(string path, T defaultT) { _iniRW = new IniRW(path); _defaultT = defaultT; Deserialize(); } /// <summary> /// 反序列化 /// </summary> /// <returns></returns> bool Deserialize() { Value = new T(); Type tInfo = Value.
如果实体类中的时间为Date类型,mapper中按时间查询时不指定javaType,Mybatis会视参数为Timestamp类型,时间参数被格式化为yyyy-MM-dd HH:mm:ss,如下案例
表结构:online_date类型是date 实体:时间段参数均是Date类型,而非String类型 public class UserOnline implements Serializable { private Long userId; // 在线时间,格式为yyyy-MM-dd HH:mm:ss private Date onlineTime; // 在线日期,格式为 yyyy-MM-dd private Date onlineDate; // 起始日期查询条件,格式为 yyyy-MM-dd private Date onlineDateStart; // 终止日期查询条件,格式为 yyyy-MM-dd private Date onlineDateEnd; } 定义用户在线实体,所有时间类型都定义为Date类型
mapper查询条件 如果不指定onlineDateStart的jdbcType=DATE,那么Mybatis会默认jdbcType=TIMESTAMP类型,查询的结果不会是预期的结果。
注意:如果使用between的话,指定了jdbcType=DATE也无效,mybatis会把数据当成Timestamp类型
<where> <if test="userId != null"> and user_id = #{userId} </if> <if test="onlineDateStart != null"> and online_date <![CDATA[ >= ]]> #{onlineDateStart,jdbcType=DATE} </if> <if test="onlineDateEnd != null"> and online_date <!
MQL5:在EA和脚本程序中引用指标 第一步 声明第二步 使用 iCustom 函数第三步 使用CopyBuffer复制引用指标中的指定数组 最近刚对MQL5语言有一点了解。 在写指标、EA的时候可以参考的、有用的资料除了MQL5自带的参考,能百度到的实在是少之又少。 也可能是我自己找到资料的能力有限。 今天通过看MQL5自带的参考文档,在脚本和EA中得到了想要的指标计算值。 果然多看看参考文档是没有错的。 那废话不说,看看我是怎么做的吧。
大致分为三步
1.使用 #property 声明引用的指标名;
2.使用 iCustom 函数,该函数返回能够连接指定到指标的句柄;
3.使用 CopyBuffer 函数,复制引用指标中的指定数组。
步骤清楚后,可能有的人会去认真看看参考文档。如果不太想看参考文档的(是本人),可以接着往下看。
第一步 声明 这步不写也不会有什么问题,目的是为了以后再看代码的时候知道自己做了什么,保持一个良好的编程习惯
比如我要引用的指标名为 zzd,所以声明就应该写成:
#property tester_indicator "zzd.ex5"
第二步 使用 iCustom 函数 这里放个函数链接 iCustom
然后看看 iCustom 函数的参数列表。
symbol 参数填 NULL 就代表当前图表的交易品种。period 参数填 0 就代表当前图表的周期。
3 .name 参数填的是你需要引用的指标名,比如我要引用的是 zzd 这个指标,它存放indicators目录下,如下图所示:
存放在此目录下, 在这个参数中就只需要填你要引用的指标的名字即可。此处我填的就是 zzd 。••• 省略部分填的是你引用的指标的参数列表。zzd指标的参数列表为这部分最好需要写到你的EA 或 脚本 中 ,这样就可以通过外部输入来控制引用指标得到你想要的值了。 所以根据参数介绍,我的 iCustom 函数应该这么写:
定义: int zzd_handle;
执行返回结果如下图
微分的概念和微分的基本公式与运算法则 微分的定义微分基本公式微分的四则运算法则复合函数的微分法则 微分的定义 设函数y=f(x)在点x的某个邻域内有定义,如果当自变量在点x处取得改变量∆x,y=f(x)相应的改变量∆y=f(x+∆x) - f(x)可表示为:
∆y=A(x)∆x+Ο(∆x)
其中A(x)与∆x无关,Ο(∆x)是当∆x->0是比∆x高阶的无穷小量,则称f(x)在点x处可微,并称A(x)∆x为函数f(x)在点x处的微分,记为:dy=A(x)∆x
函数y=f(x)在点x处可微与可导是等价的,且A(x)=f’(x);通常把自变量的增量称为自变量的微分,记为dx,即dx=∆x,所以,y=f(x)在点x处的微分可写为: dy = f’(x) dx
微分基本公式 (1)d( C ) = 0 (C为常数)
(2)d( xμ ) = μxμ-1dx
(3)d( ax ) = ax㏑adx
(4)d( ex ) = exdx
(5)d( ㏒ax) = 1/(x*㏑a)dx
(6)d( ㏑x ) = 1/xdx
(7)d( sin(x)) = cos(x)dx
(8)d( cos(x)) = -sin(x)dx
(9)d( tan(x)) = sec2(x)dx
(10)d( cot(x)) = -csc2(x)dx
(11)d( sec(x)) = sec(x)*tan(x)dx
(12)d( csc(x)) = -csc(x)*cot(x)dx
微分的四则运算法则 设f(x), g(x)都可导,则:
为什么要报考系统架构师考试 最近一年多,很多朋友来信,问我什么要报考系统架构设计师考试。为什么参加这个考试,这个考试有用吗?对自己的职业会带来什么好处?我想有以下几个方面:
一、强迫自己,去系统学习软件架构设计的理论,追踪业界架构设计的发展动态。去学习的动力有很多,如为了兴趣,为了工作,为了职位升迁,为了大幅提升薪水等。其实,为了应付考试,通过考试,也是学习知识的一种很好的方法。尤其,对自律能力不是很好的同学;
二、系统架构师考试,作为计算机技术与软件专业技术资格(水平)考试系列的最高级别专业考试,是国家认可的。如果通过,至少可以说明以下几点:
1.这是国家级别计算机领域最高级别的考试,难度程度不低于其他行业的司法考试,会计考试等,如果您通过了,那么说明您自己的智商至少不差,还是有一定学习能力,对付考试,还算有一套;
2.在同级别的高级资格里,系统架构师同系统分析师、网络规划设计师、信息系统项目管理师相比较而言,技术难度是最高,技术难度更高点,知识面更广阔点,专业深度很深些,更偏重技术研发;
3.至少说明自己还在追求进步,想在专业上有所突破,想参加这个考试;
4.参加这个考试,9点钟考试,6点就要起床,因为考点都在荒郊野外,偏离市中心;
十一月大冬天的起个大早上,北风那个吹呀,也是很苦的。
5.下午案例分析,怎么也要有论据,有观点,紧扣题意,总不能离题万里,答非所问,否则怎么通过下午案例考试,获得45分;
6.下午论文考试,能够在短短1个半小时时间里,写至少2500个汉字,也不简单,尤其现在大家天天用电脑,用键盘敲字,不提笔忘字,能文思泉涌,逻辑清晰,条理清晰,写出来这篇论文,有论据,有观点,还能够通过,也算点人才吧!
三、架构师理论,自成一派,架构模式,思维理念,对工作、对生活、对职业很有帮助。我们常说,思想决定行动,思想决定出路,思想决定命运,思想决定未来。架构设计思想,该是多么的重要的。学习架构设计的思想,是有百利无一害的。
四、架构师岗位,作为职业,研发领域的最高端岗位,学习架构理论,参加架构师工业和信息化部、人力资源和社会保障部主持的系统架构设计师考试,与也可以站在理论界、学术界的前沿,洞悉架构设计的本质,行业发展脉络;
五、这个考试有用吗?我想说,你上了大学有用吗?你考取了研究所有用吗?你获取了博士学位有用吗?大家一定也知道很多大学生滥竽充数,水平低下,博士能力平平,招摇过市。想获取一纸文凭,就衣食无忧,高高在上,丰衣足食,衣食无忧,这怎么可能呢?重要的是自己真材实料,货真价实。文凭代表的是知识,能做事,能解决实际问题代表是能力。这是两码事。这个架构师证书,又何尝不是这样呢?
六、在事业单位,国企单位,还是挺管用,至少在评定副高、高级职称的时候用得上;
七、通过了国家的系统架构师考试,至少你敢在求职简历上写,你是系统架构师。为什么呢?大家拿了大学文凭,博士学位,不都在简历上写着“大学生”、“博士”。哪怕读大学,天天旷课,打游戏,交女朋友。但是,大学文凭,博士学位,没偷没抢,没蒙没骗,正儿八经的按照学校规定获取了学分,提交论文,获取的。所以,咱这个系统架构师,也是光明正大的考试通过的。
八、自己可以理直气壮的争取系统架构师的职位,高端岗位,毕竟咱有较为雄厚的架构师的理论基础,有理论,有方法。
九、有朝一日,也可以参与软考培训行业,做IT高端培训,想做系统架构设计培训,哪可必须要有国家级的系统架构师证书哟!张友生搞得希赛IT教育培训,就是以软考培训起家的,也搞得有模有样,风水水起;想必参加软考的童靴,一定买过张友生老师主编的软考书籍。多一条路,多一个活法。老人常说,艺多不压身。
十、如果自己通过了,千万别把它太当回事,别以为自己真是系统架构师,具有系统架构师能力和学识了。别以为获取博士学位,就真是博士了。一个道理。这是万里长征的第一步。这是行走在系统架构师路上的一个垫脚石。路漫漫其修远兮,吾将上下而求索。
赋诗一首:
附1:小虎软考微信公众号:2019跟着小虎玩着去软考
一,Could not resolve all files for configuration ':app:releaseCompileClasspath react-native版本:0.57.1
这个问题原本不是rn版本的问题,原因是0.57.1将Android SDK的版本更新到27了。
先来看下错误日志: > Task :app:preReleaseBuild FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Could not resolve all files for configuration ':app:releaseCompileClasspath'.
> Could not find support-vector-drawable.aar (com.android.support:support-vector-drawable:27.1.1).
Searched in the following locations:
https://jcenter.bintray.com/com/android/support/support-vector-drawable/27.1.1/support-vector-drawable-27.1.1.aar
> Could not find livedata-core.aar (android.arch.lifecycle:livedata-core:1.1.0).
Searched in the following locations:
https://jcenter.bintray.com/android/arch/lifecycle/livedata-core/1.1.0/livedata-core-1.1.0.aar
> Could not find viewmodel.aar (android.arch.lifecycle:viewmodel:1.1.0).
Searched in the following locations:
目录
下载git。
下载失败解决方式。
1.下载git
在浏览器中输入网址:https://gitforwindows.org/
或者输入http://msysgit.github.io也可以跳转到下载地址。
或者在百度中搜索git,
看你是什么操作系统,如果是window系统则点击window;如果是Linux系统则点击Linux。
如果你是64位操作系统,则选择64bit Git for windows Setup;如果你是32位操作系统,则选择32bit Git for windows Setup。
2.下载失败解决方式
问题:在我点击下载后,一直下载不下来,两个网址都试过,提示下载失败!
解决方式:百度搜索了找到了解决办法。
在你要下载的界面按F12进入开发者工具中,
另外一种方式相同,关键就是找到该链接,把该链接复制到其他下载工具中下载即可。
版本信息:python 3.7,wxpython 4.0.4
设置背景图后StaticText控件有白色背景在上面,看起来很难受,于是百度一下搞定这个问题,虽然不是自己原创也记录一下吧,困扰很久的一个问题。直接上代码:
import wx class TransparentStaticText(wx.StaticText): """ 重写StaticText控件 """ def __init__(self, parent, id=wx.ID_ANY, label='', pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TRANSPARENT_WINDOW, name='TransparentStaticText'): wx.StaticText.__init__(self, parent, id, label, pos, size, style, name) self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_ERASE_BACKGROUND, lambda event: None) self.Bind(wx.EVT_SIZE, self.OnSize) def OnPaint(self, event): bdc = wx.PaintDC(self) dc = wx.GCDC(bdc) font_face = self.GetFont() font_color = self.GetForegroundColour() dc.SetFont(font_face) dc.SetTextForeground(font_color) dc.DrawText(self.GetLabel(), 0, 0) def OnSize(self, event): self.Refresh() event.Skip() 使用透明控件的效果图:
未使用控件的效果图:
使用方法非常简单直接替换之前的wx.StaticText即可。
如:
好了完事了。
本文是转载
1、下载 Qt5 离线安装包
下载地址:http://www.qt.io/download-open-source/ 进入后,请注意页面最下方有个【View All Downloads】链接,点击它可找到离线安装包! 根据自己的操作系统版本,选择对应的安装包: 2、添加执行权限
下载完成后,得到离线安装包,打开【终端】,进入离线安装包所在的目录,然后执行命令:
sudo chmod +x qt-opensource-linux-x86-5.4.1.run 1 3、开始安装
添加执行权限后,可以开始安装Qt5,在步骤2的基础上,继续运行命令:
sudo ./qt-opensource-linux-x86-5.4.1.run 1 可见如下窗口: 接下来按照编号指示的步骤依次操作: 4、配置环境变量
在【终端】中执行如下命令:
sudo gedit /etc/profile 1 添加如下内容: 32位系统:
export QTDIR=/opt/Qt5. 4.1/ 5.4 export PATH= $QTDIR/gcc/bin: $PATH export LD_LIBRARY_PATH= $QTDIR/gcc/lib: $LD_LIBRARY_PATH 123 64位系统:
export QTDIR=/opt/Qt5. 4.1/ 5.4 export PATH= $QTDIR/gcc_64/bin: $PATH export LD_LIBRARY_PATH= $QTDIR/gcc_64/lib: $LD_LIBRARY_PATH 123 上面的路径,请自己对照所安装的版本更改!
保存退出, 执行命令:source /etc/profile 让环境变量生效!
5、验证是否安装成功
终端下执行命令:qmake -version
如果出现如下信息,表示配置安装成功:
6、测试实例
打开Qt Creator,点击New Project,创建一个新项目:
直接插入排序 //直接插入排序 void InsertSort(int R[], int n) { int i, j; int tmp; for (i = 1; i < n; i++) { if (R[i] < R[i] - 1) { tmp = R[i]; j = i - 1; do { R[j + 1] = R[j]; j--; } while (j >= 0 && R[j] > tmp); R[j + 1] = tmp; } } } 折半插入排序 //折半插入排序 void BinInsertSort(int R[], int n) { int i, j, low, high, mid; int tmp; for (i = 1; i < n; i++) { if (R[i] < R[i - 1]) { tmp = R[i]; low = 0; high = i - 1; while (low <= high) { mid = (low + high) / 2; if (tmp < R[mid]) high = mid - 1; else low = mid + 1; } for (j = i - 1; j >= high + 1; j--) R[j + 1] = R[j]; R[high + 1] = tmp; //重点 } } } 希尔排序 //希尔排序 void ShellSort(int R[], int n) { int i, j, d; int tmp; d = n / 2; while (d > 0) { for (i = d; i < n; i++) //对所有组采用直接插入排序 { tmp = R[i]; j = i - d; while (j >= 0 && R[j] > tmp) { R[j + d] = R[j]; j -= d; } R[j + d] = tmp; } d = d / 2; } } 快速排序 //快速排序 void QuickSort(int R[], int s, int t) { int i; if (s < t) { i = partition(R, s, t); QuickSort(R, s, i - 1); QuickSort(R, i + 1, t); } } int partition(int R[], int s, int t) { int i = s, j = t; int tmp = R[i]; while (i < j) { while (j > i&&R[j] > tmp) j--; R[i] = R[j]; while (i < j&&R[i] < tmp) i++; R[j] = R[i]; } R[i] = tmp; return i; } 简单选择排序 //简单选择排序 void SelectSort(int R[], int n) { int i, j, min, tmp; for (i = 0; i < n - 1; i++) { min = j; for (j = i + 1; j < n; j++) { if (R[j] < R[min]) min = j; } if (min !
◆ 使用配置文件
>> Webpack对于output.path的要求是使用绝对路径(从系统根目录开始的完整路径),用node.js的路径拼装函数---path.join,将__dirname(node.js内置全局变量,值为当前文件所在的绝对路径)与dist(输出目录)连接起来,得到了最终的资源输出路径。
◆ webpack-dev-server
>> 安装npm install--production过滤掉devDependencies中的冗余模块,从而加快安装和发布的速度。
>> 综上我们可以总结出webpack-dev-server的两大职能:·令Webpack进行模块打包,并处理打包结果的资源请求。·作为普通的Web Server,处理静态资源文件请求。
>> ,而webpack-dev-server只是将打包结果放在内存中,并不会写入实际的bundle.js,在每次webpack-dev-server接收到请求时都只是将内存中的打包结果返回给浏览器
◆ CommonJS
>> 直到有了Browserify——一个运行在Node.js环境下的模块打包工具,它可以将CommonJS模块打包为浏览器可以运行的单个文件。这意味着客户端的代码也可以遵循CommonJS标准来编写了。
◆模块
>> CommonJS中规定每个文件是一个模块。将一个个JavaScript文件直接通过script标签插入页面中与封装成commonJS模块最大的不同在于,前者的顶层作用域是全局作用域,在进行变量及函数声明时会污染全局环境;而后者会形成一个属于模块自身的作用域,所有的变量及函数只有自己能访问,对外是不可见的。请看列子:
calculator.js
var name = 'calculator.js';
// index.js
var name = 'index.js';
require('./calculator.js');
console.log(name); // index.js
这里有两个文件,在index.js中我们通过CommonJS的require函数的加载函数calculator.js
。的结果是index.js,这说明calculator.js的变量不会影响index.js
◆ 导入
>> 有时我们加载一个模块,不需要获取其导出的内容,只是想要通过执行它而产生某种作用,比如把它的接口挂在全局对象上,此时直接使用require即可。Require(‘/task.js’)另外,require函数可以接收表达式,借助这个特性我们可以动态地指定模块加载路径。
Const modulesNames = [‘foo.js’,’bar.js’];
moduleNames.forEach(name=>{
Require(‘./’+name)
});
◆ 导出
>> 在使用命名导出时,可以通过as关键字对变量重命名。如:const name = 'calculator';const add = function(a, b) { return a + b; };export { name, add as getSum }; // 在导入时即为 name 和 getSum与命名导出不同.
本文预计阅读时间需要"7"分钟
今日关键词:Settings
继上篇给大家推送的Postman之集合(collections)今天跟大家细说一下Postman之settings,
之所以分享,是因为对于英文太差的我;有些时候对于英文版的工具实在是难以征服,毕竟文化有限(大专)英文三级,,,
针对人群:基于Poatman使用 #英文基础差劲 #测试小白 下面就划重点描述一些设置项的释义以及在我们使用中会产生的一些影响
01 进入设置
# 在顶部工具栏,点击Setting图标,在下来选项中选择Settings,即可打开设置对话框。或者使用快捷键 " Ctrl + ," 即可快捷打开设置页面;如下图所示:
# 点击settings打开设置选项,详细的设置对话框界面如下:
Postman在开发的时候,就基于用户的体验,尽可能少的提供设置项。
太多的配置项会很容易让用户懵逼。所以,对于大多数配置项,我们都不用修改,使用默认值即可。
如果我们想要适用更多的场景,那么我们就需要进行适当的调整。下面就对通用设置中的每个设置项进行简单的说明:
02 General Settings (通用设置)
# Trim keys and values in request body
释义:(在请求中装饰键和值):如果使用form-data或者url-encoded的方式向服务器发送数据;
影响:将该选项设置为ON,则会引起参数左右两侧的空格被删除,
# SSL certificate verification(SSL证书验证)
释义:防止应用程序在发出请求时检查SSL证书的有效性,
# Language detection(语音检测)
影响:将此设置为JSON将强制执行JSON呈现,而不管响应Content-Type标头,
# Request timeout in ms(0 for infinity)
影响:在显示服务器没有响应之前,设置应用等待响应的时间。0表示无穷大-Postman将永远等待响应,
# Send no-cache header(发送无缓存头)
发送一个no-cache标头可以确保请求从服务器获得最新的响应,而不是缓存数据,
# Send Postman Token header(发送Postman令牌header)
释义:这主要用于绕过Chrome中的错误。如果XmlHttpRequest处于挂起状态,并且使用相同的参数发送另一个请求,则Chrome会为它们返回相同的响应。发送随机令牌可避免此问题。这也可以帮助我们在服务器端区分请求;
# Retain headers when clicking on links(单链接时保留headers)
An End-to-End Compression Framework Based on Convolutional Neural Networks
论文链接:https://arxiv.org/pdf/1708.00838.pdf
一、引言
这周我主要在学习图像压缩方面的知识,主要是经典的图像压缩理论。包括图像冗余类型,图像压缩的编码解码部分,经典的图像压缩方法。
接下来谈一谈深度学习在图像压缩上的应用。
卷积神经网络在计算机视觉领域获得了巨大的成功,尤其是在高层的的视觉应用,例如识别和理解。但是在视觉的低层领域的应用是较少的,例如图像的压缩,这篇论文提出了一个基于卷积神经网络的对图像压缩方法。
预备知识:
compact representation,紧凑表示,这个词跟稀疏表示的意义应该是相同的(sprase representation)。对图像进行压缩,就是寻找图像的紧凑表示。
compression framework,压缩框架,指当下通用的国际压缩标准,例如JPEG,PNG,BMP等,其中JPEG是有损压缩,PNG是无损压缩,BMP存放的是图像的原始信息,没有对图像进行压缩。
Convolution Neural Network,卷积神经网络
文章亮点:
实现了深度学习在图像压缩上的应用,且压缩效果达到了state of art;
提出的压缩网络较新颖,一共有两个CNN组成。ComCNN对图像进行提取紧凑表示,再使用标准编码器对紧凑表达进行编码,RecCNN对解码结果进行图像超分辨率重建。
提出一种解决压缩标准中的量化函数导致的梯度无法反向传播的解决方法。
模型解释:
ComCNN compact CNN 学习图像的紧凑表示【注重图像的encode方面】
第一层有64个3×3×c的卷积核,c是图像通道数量,生成64通道的特征图,然后跟上一个Relu非线性激活;
第二层有64个3×3×64的卷积核,用来巩固特征图并下采样,下采样通过设置步长为2实现,然后跟上一个BN加上Relu激活函数;
第三层有c个3×3×64的卷积核,用来建立紧密的representation。
讨论环节:为什么可以用卷积神经网络对图像进行提取紧凑表示?
个人解析:CNN中的Convolution kernel 实际上是一个filter,每个kernel都过滤了相应的表达模式。例如颜色,纹理,边,角。这些简单的模式进行叠加可以组成,可以通过Conv+ReLU来观察图像中对应模式的有无情况。
Channel 标准编码模式,这篇论文用的是JPEG编码模式,对紧凑表达再进行编码压缩。
讨论环节:为什么图像经过紧凑表达了还可以进行图像压缩。
个人解析:举个例子:下面的图是衣服有256条横线组成的图像,每一条线的像素相同,线与线之间的像素各不相同
,
对于这幅图像进行紧凑表达,如果Kernel提取了这幅图像的特征,那么经过紧凑表达之后结果也一定是呈线条状的,因为在卷积扫描的方向上,卷积框内的图像数值都是相同的,那么得到的紧凑表达结果一定也是类似的一幅图像(只是猜想,没有实践,论文也没有提到这一点),那么对于紧凑表达之后的结果,显然是有巨大冗余的(这里主要是相关性冗余,利用行程编码可以解决这种冗余现象,甚至能够实现无损压缩)。标准编码过程为:,在映射器阶段去除像素之间的相关性,在量化器阶段去除图像的无关信息,在符号编码器阶段对信息进行熵编码
RecCNN 在解码端重建高质量的图像【注重图像的重建方向】
第一层有64个3×3×64的卷积核,后面跟上Relu非线性激活函数,生成64通道的特征图;
第二至十九层,每层有64个3×3×64的卷积核,后面跟上BN加Relu非线性激活;
最后一层有c个3×3×64的卷积核,BN和残差学习都被加入进来,用来重建原始图片。 学习算法
理论优化函数:
theta_1,theta_2分别代表ComCNN,RecCNN的训练参数,Cr(-)代表ComCNN,Re(-)代表RecCNN,Co(-)代表编解码器,这个loss function的本质是均方差最小
这个理论优化函数并不能训练,原因是Co(-)阶段有量化操作,梯度无法计算,在反向传播阶段,此处梯度将会停止传播
实际优化函数
通过控制theta_2,计算最优的theta_1:
通过控制theta_1,计算最优的theta_2:
引入辅助变量:
则表达式(3)变为表达式(5):
theta_2的参数可以通过表达书(5)进行训练
由于Co(-)对梯度带来的损失性,theta_1的计算过程相对比较复杂
假设Re(theta_2^hat,x_m^hat)对辅助变量x_m^hat是单调的
,即当初入与最优输入相差越大,则输出与最优输出也差距越大,那么可以得到:
,theta_1^hat实际上是使在theta_2固定的的情况下让重建后图像均方差最小的参数,那么根据刚刚单调性的假设,输入越接近最优输入,输出最接近最优输出theta_1^hat实际上还是使输入为最优输入的参数,编码解码是一个与theta_1无关的过程,但在量化过程中会损失一定的精度,因此可以近似的表示为:
,那么,最终训练theta_1参数的表达式为:
训练算法:
一、Requests 库基本方法介绍 最重要的两个对象:
request
response
1.1 request方法
requests.request() :构造一个请求,支撑以下各方法的基础方法
requests.get() :获取HTML网页的主要方法,对应于HTTP的GET
requests.head() :获取HTML网页头信息的方法,对应于HTTP的HEAD
requests.post() :向HTML网页提交POST请求的方法,对应于HTTP的POST
requests.put() :向HTML网页提交PUT请求的方法,对应于HTTP的PUT
requests.patch() :向HTML网页提交局部修改请求,对应于HTTP的PATCH
requests.delete() :向HTML页面提交删除请求,对应于HTTP的DELETE
注:request方法实际上是后面六种方法的封装,也就是说,requests库实际上只有request一种方法。
1.2 response对象属性
r.states_code :获取返回的状态码 ,200代表成功r.text / r.read() :HTTP响应内容的字符串形式,即url对应页面的内容r.content :HTTP响应内容的二进制形式r.son() :HTTP响应内容的json形式r.raw :HTTP响应内容的原始形式r.url :返回请求的urlr.encoding :从HTTP的header中猜测的响应内容编码方式,如果header中不存在charset,则认为编码为ISO-8859-1r.apparent_encoding :从内容中分析出的响应内容编码方式(备选编码方式)r.raise_for_status() :失败请求(非200响应)抛出异常 1.3、requests库的异常
requests.ConnectionError:网络连接错误异常,如DNS查询失败、拒绝连接等
requests.HTTPError:HTTP错误异常
requests.URLRequired:URL缺失异常
requests.TooManyRedirects:超过最大重定向次数,产生重定向异常
request.ConnectTimeout:连接远程服务器超时异常
requests.Timeout:请求URL超时,产生超时异常
1.4、最常用的方法
requests.get( ) 方法 基本形式:requests.get(url,params=None,**kwargs) ~url :模拟获取页面的url连接 ~params :url 中的额外参数,字典或字节流格式,无需对其编码,可选 ~**kwargs :12个控制访问的参数 import requests data = {"age":"22","name":"germey",} response = requests.get("http://httpbin.org/get",params=data) # 给URL传参 print(response.text) 注:Requests 会推测其编码然后解码,但是 HTTP 和 XML 自身可以指定编码,这样的话,应该使用 r.
layer.msg(data.msg, {icon: 6,time:2000, shade:0.4});
弹出时间两秒 有遮罩层
最近项目中涉及到跨页面传参数和后台进行数据交互,经过多方搜索参考决定用路由传参来解决。
Vue中给我们提供了三种路由传参方式,:
方法一:params传参(只能由name引入)
1.params传参、使用name: this.$router.push({ name:"Check", params:{id:item.id, num:item.num} }) 2.params接收参数: this.id = this.$route.params.id this.name = this.$route.params.num 3.router.js中的配置: { path: '/check', name: 'Check', component: Check, } 通过params传递参数,如果我们想获取id的 参数值,我们可以通过this.$route.params.id这种方式来打印出来就可以得到了;(注意:获取参数的时候是$route,跳转和传参的时候是$router)
方法二:路由属性配置传参:
this.$router.push({ name:"/Check/${item.id}", }) //这个组件对应的路由配置 { path: '/check:id', name: 'Check', component: Check, } 通过路由属性配置传参我们可以用this.$route.params.id来获取到id的值,注意this.$router.push方法里面路径带的是值,路由配置项那里带的是变量名(属性名)来实现的对应;
以上两种传参方式基本上可以理解为ajax中的post请求方式,参数都是不可见的,但是上面两种方法都有一个弊端,就是当页面刷新了是获取不到参数值的,那么有没有一种方法是页面刷新之后参数依然存在呢?
方法三:query传参
1.query传参、使用path: this.$router.push({ path:"Check", params:{id:item.id, num:item.num} }) 2.query接收参数: this.id = this.$route.query.id this.name = this.$route.query.num 3.router.js中的配置: { path: '/check', name: 'Check', component: Check, } 第三种方式是用query来传参,这种方式是可以解决页面刷新参数消失问题的,这种方式可以理解为是ajax中的get方法,参数是直接在url后面添加的,参数是可见的,所以解决页面刷新参数消失问题建议使用方法三来解决;
其实解决页面刷新参数丢失问题的方案还有很多,比如把参数存在sessionStorange或者localStorange中都是可行的,不过我们既然用vue框架,就要用vue的方式来解决问题。这里只是想告诉大家,问题的解决方案可以多种多样,要学会用多种方式或者说多种方案来解决一个问题,不要有太多的局限性!
项目过程中使用及参考链接:
https://www.cnblogs.com/dengyao-blogs/p/11399676.html
首先在js里,> <是应用隐式类型转换Boolean()规则,结果为true和false,true和false应用显示类型转换Number()后分别是1和0.
在此例中,2>1为true,等同1,后面即为1>3,判断结果即为false。
同理,在式子2>3<1中,2>3为false,即为0,0<1,判断结果为true。
参考:https://blog.csdn.net/u012602393/article/details/42649301
由MeshVS_DataSource派生自定义DataSource OCC在DataExchange中提供了.stl数据格式的导入与导出方法。在该类型文件中,模型以三角网格形式存储,OCC为此定义了针对.stl格式文件的数据存储方式,即XSDRAWSTLVRML_DataSource。如下为导入.stl并为其定义显示生成器的方法:
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, L"stl Files (*.stl)|*.stl;|STL Files (*.STL)|*.STL;||", NULL); CString SHAREPATHValue; SHAREPATHValue.GetEnvironmentVariable(L"CSF_OCCTDataPath"); CString initdir = (SHAREPATHValue + "\\stl"); dlg.m_ofn.lpstrInitialDir = initdir; if (dlg.DoModal() != IDOK) return; // read the data and create a data source TCollection_AsciiString aFileName((const wchar_t*)dlg.GetPathName()); Handle(Message_ProgressIndicator) aProgInd = Handle(Message_ProgressIndicator)(); Handle(Poly_Triangulation) aSTLMesh = RWStl::ReadFile(aFileName, aProgInd); Handle(XSDRAWSTLVRML_DataSource) aDS = new XSDRAWSTLVRML_DataSource(aSTLMesh); // create mesh Handle(MeshVS_Mesh) aMesh = new MeshVS_Mesh(); aMesh->SetDataSource(aDS); // use builder Handle(MeshVS_MeshPrsBuilder) aBuilder = new MeshVS_MeshPrsBuilder(aMesh); aMesh->GetDrawer()->SetColor(MeshVS_DA_EdgeColor, Quantity_NOC_YELLOW); aMesh->AddBuilder(aBuilder, Standard_False); myAISContext->Display(aMesh, Standard_True); Fit(); 如果不是读取STL文件,而是有三角网格的点坐标数据 std::vector< PointXYZ> CoordData 以及点之间的拓扑关系std::vector<std::vector> Ele2NodeData(比如三个点构成一个三角形的索引值),需要自己定义DataSource来显示网格。
用硬石开发板例程改个TCP通信程序,发现接收数据很慢,间隔达到250ms,很大上位机下发的命令都无法快速响应:
#define TCP_TMR_INTERVAL 1//250 /* The TCP timer interval in milliseconds. */
原来是250,改成1,这样1ms接收回调一次
LWIP server 主动上传数据tcp_write ,要500ms才成功发送一次,TCP_TMR_INTERVAL调小就可以了
但是最小也有60ms,最后在网上找到了,是LWIP内部的Nagle算法会把一些小帧数据合并成一个大的数据包再往外发送,
解决: 在 tcp_recv(pcb, tcp_server_recv)前加tcp_nagle_disable(tcp_send_pcb)
/* 禁止小帧数据合并,否则会出现阻塞,内存溢出错误 */
tcp_nagle_disable(tcp_send_pcb);
tcp_recv(pcb, tcp_server_recv);
根本原因:tcp_write只是把数据复制到发送队列中,并没有发送,要立即发送使用tcp_output
err = tcp_write(pcb, puf, TCP_FRAME_DATA_ADD, 1);
if(err == ERR_OK) {
( void )tcp_output( pcb );
}
对LWIP只是能用,对底层代码了解不足。防止下次出错记录下。
RANSAC简介 ransac是RANdom SAmple Consensus的简称,它是根据一组包含异常数据的样本数据集,通过迭代的方法计算出数据的数学模型参数,得到有效样本数据的非确定性的算法。它于1981年由 Fischler和Bolles最先提出。
对于RANSAC算法有一个基本的假设:样本中包含正确数据(inliers,符合模型的数据)和异常数据(Outliers,不符合模型的数据),即数据集中含有噪声。这些异常数据可能是由于错误的测量、错误的假设、错误的计算等产生的。同时RANSAC也假设, 给定一组正确的数据,存在可以计算出符合这些数据的模型参数的方法。
RANSAC算法的输入是一组观测数据(往往含有较大的噪声或无效点),一个用于解释观测数据的参数化模型以及一些可信的参数。RANSAC通过反复选择数据中的一组随机子集来达成目标。被选取的子集被假设为局内点,并用下述方法进行验证
1.有一个模型适应于假设的局内点,即所有的未知参数都能从假设的局内点计算得出。
2.用1中得到的模型去测试所有的其它数据,如果某个点适用于估计的模型,认为它也是局内点。
3.如果有足够多的点被归类为假设的局内点,那么估计的模型就足够合理。
4.然后,用所有假设的局内点去重新估计模型(譬如使用最小二乘法),因为它仅仅被初始的假设局内点估计过。
5.最后,通过估计局内点与模型的错误率来评估模型。
利用RANSAC筛选sift特征点匹配 在sift特征点匹配中,同一平面上的物体在不同方向上的成像有一个透视变换的过程。关于透视变换:
透视变换的变换矩阵为一个3×3的矩阵,因此需要4对匹配点来计算变换矩阵。不过这里需要注意的是,不同平面的物体在相机位置不同时候所拍的两张照片所对应的变换矩阵是不同的,由于RANSAC是按变换矩阵来筛选的,所有此算法不仅能筛选错误的匹配点,还能将一些不同平面的正确匹配点筛选。(其实在sift论文中作者已经用了一种去除错误点的方法,能达到很好的筛选效果,即d0<0.2d1,RANSAC个人感觉主要用于图像拼接)。大家可以直接跳到后面看我的筛选效果,筛选后的匹配点主要集中在电脑屏幕部分,因为它们在同一平面,像水杯、键盘部分的匹配点全部被去除了。而且我是为了筛选效果将d0<0.2d1这种筛选改了,本来在d0<0.2d1这种方法之后已经能达到较好的匹配效果。
RANSAC算法在SIFT特征筛选中的主要流程是:
(1) 从样本集中随机抽选一个RANSAC样本,即4个匹配点对
(2) 根据这4个匹配点对计算变换矩阵M
(3) 根据样本集,变换矩阵M,和误差度量函数计算满足当前变换矩阵的一致集consensus,并返回一致集中元素个数
(4) 根据当前一致集中元素个数判断是否最优(最大)一致集,若是则更新当前最优一致集
(5) 更新当前错误概率p,若p大于允许的最小错误概率则重复(1)至(4)继续迭代,直到当前错误概率p小于最小错误概率
筛选效果 在sift论文中,作者已经使用了一种筛选条件d0<0.2d1,这种条件能过滤大部分错误匹配,为了方便查看RANSAC的筛选效果,我这里将这个筛选条件改为d0<0.5d1,这样可以使错误匹配更多。由于匹配点过多,在程序里设置了最多显示80对匹配点,方便观
察。RANSAC算法筛选前:
RANSAC算法筛选后:
从图中可以看到RANSAC对之前的一些错误匹配进行了去除,除此之外,还对电脑键盘部分的正确匹配进行的筛除。原因是因为不同平面上的点进行透视变换所对应的变换矩阵不一样,这一点也是我看到的那些博客所没有提到的,我们使用RANSAC算法更多的是用于图像拼接,但是如果要达到好的图像拼接效果,还是要让所拼接的图像尽量在同一平面。我们这里由RANSAC算法筛选的就是每对特征点对应的变换矩阵。
参考:
RANSAC算法详解
利用RANSAC算法筛选SIFT特征匹配
create_pose 创建3D位姿
( : : TransX, TransY, TransZ, RotX, RotY, RotZ, OrderOfTransform, OrderOfRotation, ViewOfTransform : Pose)
输入:
TransX
沿x轴平移(以[m]为单位)。
默认值:0.1
建议值:-1.0,-0.75,-0.5,-0.25,-0.2,-0.1,-0.5,-0.25,-0.125,-0.01、0.0、0.01、0.125、0.25、0.5、0.1、0.2、0.25、0.5 ,0.75、1.0
TransY
沿y轴平移(以[m]为单位)。
默认值:0.1
建议值:-1.0,-0.75,-0.5,-0.25,-0.2,-0.1,-0.5,-0.25,-0.125,-0.01、0.0、0.01、0.125、0.25、0.5、0.1、0.2、0.25、0.5 ,0.75、1.0
TransZ
沿z轴平移(以[m]为单位)。
默认值:0.1
建议值:-1.0,-0.75,-0.5,-0.25,-0.2,-0.1,-0.5,-0.25,-0.125,-0.01、0.0、0.01、0.125、0.25、0.5、0.1、0.2、0.25、0.5 ,0.75、1.0
RotX
绕Rodriguez向量的x轴或x分量旋转(以[°]为单位或无单位)。
默认值:90.0
建议值:0.0、90.0、180.0、270.0
典型值范围:0≤RotX≤360
RotY
绕Rodriguez向量的y轴或y分量旋转(以[°]为单位或无单位)。
默认值:90.0
建议值:0.0、90.0、180.0、270.0
典型值范围:0≤RotY≤360
RotZ
绕Rodriguez矢量的z轴或z分量旋转(以[°]或不带单位)。
默认值:90.0
建议值:0.0、90.0、180.0、270.0
典型值范围:0≤RotZ≤360
OrderOfTransform
旋转和平移的顺序。
默认值:“ Rp + T”
建议值:“ Rp + T”,“ R(p-T)”
OrderOfRotation
旋转值的含义。
默认值:“ gba”
建议值:“ gba”,“ abg”,“ rodriguez”
ViewOfTransform
变换视角。
默认值:“point”
节日快乐,我们继续努力!!!
项目
服务器架构
C++基础
1.深拷贝和浅拷贝的区别
默认拷贝构造函数实现的是浅拷贝,浅拷贝只拷贝指针本身,不拷贝指针指向的数据内容
浅拷贝一般情况下没有问题,但类成员出现指针时,会导致指针悬挂
2.C++多态如何体现
3.vector内部实现,clear会释放vector的内存吗,如何释放vector等内存
要点: size,capacity,clear()只是将size改为0
释放内存的方法:
//方法一:可以使用swap用临时变量交换释放 vector<int>().swap(xx); //方法二:采取缩小容量至size()大小 clear(); shrink_to_fit(); 4.vector和list的区别
5.如何实现vector头部插入(deque:双端队列)
6.智能指针
unique_ptr、shared_ptr
使用智能指针的原因:
1)智能指针能够帮助我们处理资源泄露问题;
2)它也能够帮我们处理空悬指针的问题;
3)它还能够帮我们处理比较隐晦的由异常造成的资源泄露。
7.析构函数能否抛出异常
析构函数不能,也不应该抛出异常
C++异常处理模型最大的特点和优势就是对C++中的面向对象提供了最强大的无缝支持。那么如果对象在运行期间出现了异常,C++异常处理模型有责任清除那些由于出现异常所导致的已经失效了的对象(也即对象超出了它原来的作用域),并释放对象原来所分配的资源, 这就是调用这些对象的析构函数来完成释放资源的任务,所以从这个意义上说,析构函数已经变成了异常处理的一部分。
1)如果析构函数抛出异常,则异常点之后的程序不会执行,如果析构函数在异常点之后执行了某些必要的动作比如释放某些资源,则这些动作不会执行,会造成诸如资源泄漏的问题。
2)通常异常发生时,c++的机制会调用已经构造对象的析构函数来释放资源,此时若析构函数本身也抛出异常,则前一个异常尚未处理,又有新的异常,会造成程序崩溃的问题。
网络
1.TCP与UDP的最大区别
2.TCP的三次握手过程
3.TCP三次握手如果服务器没有收到最后一次握手会怎么样
当Client端收到Server的SYN+ACK应答后,其状态变为ESTABLISHED,并发送ACK包给Server,如果此时ACK在网络中丢失,那么Server端该TCP连接的状态为SYN_RECV,并且依次等待3秒、6秒、12秒后重新发送SYN+ACK包,以便Client重新发送ACK包。
Server重发SYN+ACK包的次数,可以通过设置/proc/sys/net/ipv4/tcp_synack_retries修改,默认值为5。
如果重发指定次数后,仍然未收到ACK应答,那么一段时间后,Server自动关闭这个连接。
但是Client认为这个连接已经建立,如果Client端向Server写数据,Server端将以RST包响应,方能感知到Server的错误
4.四次挥手如何处理大量的TIME_WAIT
5.多路复用网络模型
算法
1.正整数n以内的最大素数
2.最长递增子序列
因为之前在学数据分析课程的时候老师讲到时间序列这里,但只是简单的对这个经典的时间序列案例介绍了一下,并没有涉及对差分次数d的查找、找ARIMA模型的p、q值和模型检验 这三个步骤。
后来我搜寻了整个网络,终于结合各个文章的解释,对代码进行了重新的梳理,下面就是详细的整个代码过程(如果问题,欢迎提出来指正!):
--------------------------------------------------我是修正线---------------------------------------------------
2021.11.24 第三次更新
大家对本文的疑问在👉最新一期时序的博客 👈中有提到相关解决方法,欢迎大家前去围观🤝。
--------------------------------------------------我是修正线---------------------------------------------------
--------------------------------------------------我是修正线---------------------------------------------------
2021.06.01再次更新
鉴于最近各位朋友提出的疑问(也感谢大家的提问 掌柜也学到很多😁),这里特再次更新🆑!!!
如果你遇到的时序是季节/周期性的时序,那么请移步👉最新博客!进行参考
如果你遇到的时序是季节/周期性的时序,那么请移步👉最新博客!进行参考
如果你遇到的时序是季节/周期性的时序,那么请移步👉最新博客!进行参考
重要事情说三遍😂,谢谢!
PS:本博客搭配👉这篇👈一起服用效果更佳!!!
--------------------------------------------------我是修正线---------------------------------------------------
--------------------------------------------------我是修正线---------------------------------------------------
10.20 更新
感谢网友提出的问题,进行了一个修正,当时的代码少了最后用ARIMA对原始序列的一个预测步骤。这里补充一下:
from statsmodels.tsa.arima_model import ARIMA #感谢网友的指正,这里直接用data即可,之前想太多了😅 #还原到原始序列(不用这个!!!❌) #ts_restored = pd.Series([data[0]], index=[data.index[0]]) .append(data1).cumsum() #第六步:使用ARIMA模型进行预测 model = ARIMA(data,order=(7,0,0)) #导入ARIMA模型 result = model.fit(disp=-1) #print(result.summary()) result.conf_int()#模型诊断,可以发现所有的系数置信区间都不为0;即在5%的置信水平下,所有的系数都是显著的,即模型通过检验。 #最后画出时序图 fig, ax = plt.subplots(figsize=(12, 10)) ax = data.loc['1901':].plot(ax=ax) #注意起点是从1901开始 fig = result.plot_predict(5, 100) #因为前面是90个数,所以加上预测的10个就是100 plt.show() #数据预测并画图 #预测原始序列的未来10年数据 pred = result.predict(start = 90, end = 99, dynamic = True) pred --------------------------------------------------我是修正线---------------------------------------------------
互斥锁 线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。互斥锁为资源引入一个状态:锁定/非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性
1、互斥锁基本原理:
互斥锁是一个二元变量,其状态为开锁(允许0)和上锁(禁止1),将某个共享资源与某个特定互斥锁在逻辑上绑定(要申请该资源必须先获取锁)。
(1)访问公共资源前,必须申请该互斥锁,若处于开锁状态,则申请到锁对象,并立即占有该锁,以防止其他线程访问该资源;如果该互斥锁处于锁定状态,则阻塞当前线程。
(2)只有锁定该互斥锁的进程才能释放该互斥锁,其他线程试图释放无效。
2、初始化互斥锁:
使用之前,需要定义互斥锁,使用函数:pthread_mutex_t lock;进行定义
extern int pthread_mutex_init(pthread_mutex_t * **_mutex**,_const pthread_mutex_mutexattr_t* **_mutexattr**) 参数: _mutex 初始化的互斥锁的指针
_mutexattr 指向对象的指针,若为空则默认属性
3、申请互斥锁
如果一个线程要占用共享资源,必须先申请对应互斥锁,使用函数:
以阻塞方式申请互斥锁:
extern int pthread_mutex_lock(pthread_mutex* _mutex) 以非阻塞方式申请互斥锁:
extern int pthread_mutex_trylock(pthread_mutex* _mutex 4、释放互斥锁
释放互斥锁函数:
extern int pthread_mutex_unlock(pthread_mutex_t* _mutex) 死锁 死锁是指一个资源被多次调用,而多次调用方都未能释放该资源就会造成一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁
死锁产生:
一个线程内部多次加锁缺没有释放引起死锁
多个线程内部多次调用引起死锁
python中的实例
按钮摇杆的使用 1. 说明: 遥控器其中有一个元器件是按钮摇杆,为了以后自制遥控器铺垫,今天把摇杆按钮的原理实现一下。
2.实物图: 如图所示方向:x,y,z
其中x往前摆到底时是1023,往后摆到底部是0;
其中y往左摆到底时是1023,往右摆到底部是0;
z是往下按住时,为最大1023,其余时刻是小于1023的不定数。
3.接线图: 其中有五个引脚,GND,VCC就不用说了,
剩余三根引脚,一个是x方向,另一个是y方向,最后一个是z方向。
4.代码部分 /* 按钮摇杆的使用 */ //初始化引脚 x A0, y A1,z A2 int analogPin_x = 0; int analogPin_y = 1; int analogPin_z = 2; // 定义变量 int val_x,val_y,val_z; //设置延时 int t=1000; void setup() { Serial.begin(9600); } void loop() { //读取x方向的值 val_x = analogRead(analogPin_x); //输出x方向的值 Serial.print("analogPin_x:"); Serial.println(val_x); //延时 delay(t); val_y = analogRead(analogPin_y); Serial.print("analogPin_y:"); Serial.println(val_y); delay(t); val_z = analogRead(analogPin_z); Serial.print("analogPin_z:"); Serial.println(val_z); delay(t); } 5.
HTML提供了5种空格实体(space entity),它们拥有不同的宽度,非断行空格( )是常规空格的宽度,可运行于所有主流浏览器。其他几种空格(    ‌‍)在不同浏览器中宽度各异。
它叫不换行空格,全称No-Break Space,它是最常见和我们使用最多的空格,按下space键产生的空格。在HTML中,如果你用空格键产生此空格,空格是不会累加的(只算1个)。要使用html实体表示才可累加,该空格占据宽度受字体影响明显而强烈。
 
它叫"半角空格",全称是En Space,en是字体排印学的计量单位,为em宽度的一半。根据定义,它等同于字体度的一半(如16px字体中就是8px)。名义上是小写字母n的宽度。此空格传承空格家族一贯的特性:透明的,其占据的宽度正好是1/2个中文宽度,而且基本上不受字体影响。
 
它叫“全角空格”,全称是Em Space,em是字体排印学的计量单位,相当于当前指定的点数。例如,1 em在16px的字体中就是16px。此空格也传承空格家族一贯的特性:透明的,其占据的宽度正好是1个中文宽度,而且基本上不受字体影响。
 
它叫窄空格,全称是Thin Space。我们不妨称之为"瘦弱空格";,就是该空格占据的宽度比较小。它是em之六分之一宽。
‌
它叫零宽不连字,全称是Zero Width Non Joiner,简称"ZWNJ",是一个不打印字符,放在电子文本的两个字符之间,抑制本来会发生的连字,改为以这两个字符原本的字形来绘制。Unicode中的零宽不连字字符映射为“”(zero width non-joiner,U+200C),HTML字符值引用为:‌
‍
它叫零宽连字,全称是Zero Width Joiner,简称“ZWJ”,是一个不打印字符,放在某些需要复杂排版语言(如阿拉伯语、印地语)的两个字符之间,使得这两个本不会发生连字的字符产生了连字效果。零宽连字符的Unicode码位是U+200D(HTML: ‍)。
此外,浏览器还会把以下字符当作空白进行解析:空格( )、制表位(	)、换行(
)和回车( 
)还有中文全角空格( )等等。
题目描述 在有向图 GG 中,每条边的长度均为 11,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
路径上的所有点的出边所指向的点都直接或间接与终点连通。在满足条件11的情况下使路径最短。 注意:图 GG 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入格式 第一行有两个用一个空格隔开的整数 nn 和 mm,表示图有 nn 个点和 mm 条边。
接下来的 mm 行每行 22 个整数 x,yx,y,之间用一个空格隔开,表示有一条边从点 xx 指向点yy。
最后一行有两个用一个空格隔开的整数 s, ts,t,表示起点为 ss,终点为 tt。
输出格式 输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出-1−1。
输入输出样例 输入 #1复制
3 2 1 2 2 1 1 3 输出 #1复制
-1 输入 #2复制
6 6 1 2 1 3 2 6 2 5 4 5 3 4 1 5 输出 #2复制
3 说明/提示 解释1:
C++提供了三种访问类或者类对象的操作符,他们是 双冒号 ::, 点 ., 箭头 ->, 这三种操作符有着各自的使用场景和定义。
双冒号 :: A::B, :: 表示作用域运算符, A一定是一个类的名称或命名空间的名称, 仅仅用于当B是A类/A命名空间的一个成员的情况.
点 . A.B, A为一个实例化的类(也就是对象)或者结构体, B为A的一个成员.
箭头 -> a->b, 是指针指向其成员的运算符, 等价于 (*a).b,A 是指向结构体或者类的指针, B是A中的成员.
代码举例 #include<iostream> int Num=3; class Student { public : void setid(int ID); int getid(void); Student(); private: int id; }; Student::Student(void) //::可以实现在类体外构造函数 { std::cout << "Object is being created" << std::endl; } int Student::getid(void) //::可以实现在类体外定义其成员函数 { return id; } void Student::setid(int ID) { id = ID; } int main() { Student a; Student *b; int Num=4; a.
问题描述:最近更新了新的mac系统,发现原来的微信截图快捷键只能截到一个空白的桌面,其他的窗口、文件等都被隐藏了。想要截的位置及内容就截取不到了。
解决问题 :选择-系统偏好设置-屏幕录制-隐私将微信勾选允许微信录制屏幕。设置完毕后重启微信就可以再正常的使用微信截图了。
今天有同事用swagger2开发时,有一方法返回Map<String,List<Object>>出现无法解析错误。
Pom.xml引入的swagger版本如下:
<!--swagger start--> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> <version>1.5.20</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.1</version> </dependency> <!--swagger end--> 具体原因:
swaggerconfig没有默认添加map的复杂结构引起的,需要手动添加。
步骤:
1. 找到swaggerconfig类,在Docket方法里添加一些mapRule即可
2. 这里设计rule比较灵活,我就按标题的格式添加,其中Model.class是自定义的业务类,换成自己的即可。
docket.alternateTypeRules(AlternateTypeRules.newMapRule(String.class, List.class)); docket.alternateTypeRules(AlternateTypeRules.newMapRule(List.class, Model.class)); 具体代码如下:
@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket createRestApi() { Docket docket = new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) .paths(PathSelectors.any()) .build(); docket.alternateTypeRules(AlternateTypeRules.newMapRule(String.class, List.class)); docket.alternateTypeRules(AlternateTypeRules.newMapRule(List.class, Model.class)); return docket; } }
Example Code:
import tensorflow as tf record_path = '/tmp/tfrecord_write_test/part-r-00000' filename_queue = tf.train.string_input_producer([record_path]) reader = tf.TFRecordReader() _, serialized_example = reader.read(filename_queue) features = tf.parse_single_example(serialized_example, features={ 'label': tf.FixedLenFeature([], tf.float32), 'features': tf.FixedLenFeature([2], tf.float32), }) with tf.Session() as sess: init_op = tf.initialize_all_variables() sess.run(init_op) coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(coord=coord) for i in range(2): example = sess.run([features])#在会话中取出image和label print(example)
另外还有一个方法可以用来获取类的绝对路径(当前的classpath)
getClass().getResource("/").toString();
获取tomcat下的工程路径
String path = request.getRealPath("/");
servlet下得到工程或者类的位置 System.out.println(request.getSession().getServletContext().getRealPath("")); //得到tomcat下工程的位置
System.out.println(request.getSession().getServletContext().getRealPath("/")); //得到tomcat下工程的位置
System.out.println(request.getRealPath("/"));//得到tomcat下工程的位置
System.out.println(request.getRequestURL());//得到IE地址栏地址
System.out.println(request.getRequestURI());//得到相对地址
System.out.println(getClass().getResource("/").toString());//得到tomcat这个类编译后的位置
System.out.println(Thread.currentThread().getContextClassLoader().getResource("").getPath());//得到tomcat这个类编译后的位置 System.out.println(System.getProperty("user.dir"));//得到的是tomcat下的bin文件
得到的输出实例:
D:\apache-tomcat\apache-tomcat-7.0.41\webapps\test
D:\apache-tomcat\apache-tomcat-7.0.41\webapps\test\
D:\apache-tomcat\apache-tomcat-7.0.41\webapps\test\
http://localhost:8080/test/servlet/Test3
/test/servlet/Test3
file:/D:/apache-tomcat/apache-tomcat-7.0.41/webapps/test/WEB-INF/classes/
/D:/apache-tomcat/apache-tomcat-7.0.41/webapps/test/WEB-INF/classes/
D:\apache-tomcat\apache-tomcat-7.0.41\bin
都是绝对路径
java类执行的时候
System.out.println(System.getProperty("user.dir"));//获取工程路径
System.out.println(directory.getCanonicalPath());//获取标准的路径
System.out.println(directory.getAbsolutePath());//获取绝对路径
System.out.println(directory.getPath());//获取File括号里的路径
System.out.println(Class.class.getClass().getResource("/").getPath()); //类的绝对路径
得到的输出结果:
F:\Workspaces\test
F:\Workspaces\test
F:\Workspaces\test\.
.
/F:/Workspaces/test/build/classes/
argparse是一个Python解析命令行参数的接口,具有很强的使用性,在这里特地通过几个例子整理以下其用法, 持续更新
文章目录 一、参数二、例一:拼接字符串 一、参数 故名意思,该库就是用来传参的。在该库看来,参数分为两种:
选项参数: 用-或者--字符起始标识。位置参数: 与选项参数反之。 二、例一:拼接字符串 1、 使用选项参数实现:
编写parse.py文件如下
import argparse parser = argparse.ArgumentParser() parser.add_argument('-s1', '--a', metavar='string', help='字符串1') parser.add_argument('-s2', '--b', metavar='string', help='字符串2') args = parser.parse_args() print(args.a + args.b) 在命令行执行:
python parse.py -s1 '111' -s2 '222' 输出: 111222 代码解读:
第一个参数-x用来在命令行中指定参数,第二个参数--x可以用来在程序中指代该参数。而metavar是用来提示参数形式的提示语, help用来描述参数的作用
2、 使用位置参数实现:
编写parse.py文件如下import argparse parser = argparse.ArgumentParser() parser.add_argument('a', metavar='string', help='字符串1') parser.add_argument('b', metavar='string', help='字符串2') args = parser.parse_args() print(args.a + args.b) 命令行执行:python parse.py '111' '222' 输出: 111222 代码解读:
# include<iostream> using namespace std; int main(){ int n; cin >> n; int sum = 0, a = 2,total_sum = 0; for (int i = 1; i <= n; i++){ sum = (sum * 10) + a; total_sum += sum; } cout << total_sum << endl; return 0; }
软件测试 1 基本概念1.1 软件测试1.2 目的1.3 原则1.4 周期1.5 测试与开发过程的关系1.6 白盒测试与黑盒测试1.7 测试用例 2 白盒测试的测试用例设计2.1 逻辑覆盖2.1.1 语句覆盖2.1.2 判定覆盖2.1.3 条件覆盖2.1.4 判定-条件覆盖2.1.5 条件组合覆盖2.1.6 路径覆盖 3 黑盒测试的测试用例设计3.1 等价类划分3.1.1 划分等价类3.1.2 确定测试用例3.1.3 用等价类划分法设计测试用例的实例 3.2 边界值分析3.2.1 边界值分析方法的考虑3.2.2 选择测试用例的原则 1 基本概念 1.1 软件测试 为了保证软件的质量和可靠性,人们力求在分析、设计等各个开发阶段结束之前,对软件进行严格的技术评审。
软件测试是为了发现错误而执行程序的过程。
或者说
软件测试是根据软件开发各阶段的规格说明和程序的内部结构而精心设计一批测试用例(即输入数据及其预期的输出结果),并利用这些测试用例去运行程序,以发现程序错误的过程。
1.2 目的 目的:以最少的时间和人力,系统的找出软件中潜在的各种错误和缺陷。
Grenford J. Myers 就软件测试目的提出以下观点:
测试是程序的执行过程,目的在于发现错误;一个好的测试用例在于能发现至今未发现的错误;一个成功的测试是发现了至今未发现的错误的测试; 测试不能表明软件中不存在的错误,它只能说明软件中存在的错误。
1.3 原则 应当把“尽早地和不断地进行软件测试”作为软件开发者的座右铭。测试用例应由测试输入数据和与之对应的预期输出结果这两部分组成。程序员应避免检查自己的程序。在设计测试用例时,应当包括合理的输入条件和不合理的输入条件。充分注意测试中的集群现象。严格执行测试计划,排除测试的随意性。应当对每一个测试结果作全面检查。妥善保存测试计划、测试用例、出错统计和最终分析报告,为未来实施的维护提供方便。 1.4 周期 1.5 测试与开发过程的关系 1.6 白盒测试与黑盒测试 任何工程产品都可以使用以下两种方法之一进行测试:
已知产品的功能设计规格,可以通过测试证明每个实现了的功能是否符合要求。已知产品内部的工作过程,可以通过测试证明每种内部操作是否符合设计规格要求,所有内部成分是否已经过检查。 前者是黑盒测试,后者是白盒测试。
黑盒测试方法主要是为了发现:是否有不正确或遗漏了的功能?输入能否正确地接受?能否输出正确的结果?是否有数据结构错误或外部信息(例如数据文件)访问错误?性能上是否能够满足需求?是否有初始化或终止性错误?
所以,用黑盒测试发现程序中的错误,必须在所有可能的满足输入条件和输出条件中确定测试数据,检查程序是否都能产生正确的输出。
白盒测试主要是对程序模块进行检查:对程序模块的所有独立的执行路径至少测试一次;对所有的逻辑判定,取“真”与取“假”的两种情况都至少测试一次;在循环的边界和运行界限内执行循环体;测试内部数据结构的有效性等等。
因此白盒测试又称为结构测试或逻辑驱动测试。
1.7 测试用例 在测试阶段,穷举测试不可行,必须精心设计测试用例,从数量极大的可用测试用例中精心地挑选少量的测试数据,使得采用这些测试数据能够达到最佳的测试效果,或者说它们能够高效率地把隐藏的错误尽可能多的揭露出来。
事实说明,软件测试有一个致命的缺陷,即测试的不完全、不彻底性。由于任何程序只能进行少量(相对于穷举的巨大数量而言)的有限的测试,所以在发现错误时能说明程序有问题,但在未发现错误时,不能说明程序中没有错误、没有问题。
2 白盒测试的测试用例设计 2.1 逻辑覆盖 逻辑覆盖是以程序内部的逻辑结构为基础的设计测试用例的技术,它属于白盒测试。
在这个复用的弹出框中,有时操作成功后会在控制台报一个这样的错误:
百思不解,直到在报错信息中点击 `element-ui.common.js?5c96:17242` 后看到这一行:
再结合报错信息,我们可以得知,应该是我们每个 el-form-item 标签的 prop 属性有问题。果然,存在一个没有传入 prop 属性。
最开始时,金融系统只有IBM这些大的公司来提供设备,象各种主机与终端等。在各个计算机设备之间,需要交换数据。我们知道数据是通过网络来传送的,而在网络上传送的数据都是基于0或1这样的二进制数据,如果没有对数据进行编码,则这些数据没有人能够理解,属于没有用的数据。起初的X.25、SDLC以及现在流行的TCP/IP网络协议都提供底层的通讯编码协议,它们解决了最底层的通讯问题,能够将一串字符从一个地方传送到另一个地方。但是,仅仅传送字符串是没有太大意义的,怎样来解析字符串代表什么内容是非常重要的,否则传送一些“0123abcd”的字符串也是无用的乱码。
让我们随着时光回到几十年前的某个时刻,假设我们被推到历史的舞台上,由我们来设计一个通用报文协议,来解决金融系统之间的报文交换,暂且称该协议叫做ISO8583协议。此时,技术是在不断的前行,当初IBM一支独秀的局面好像已经不妙了,各种大小不一的公司都进入金融行业以求能有所斩获,呈一片百花齐放的局面。我们怎样来设计一个报文协议,能够将这些如雨后春笋般出现的所有公司都纳入进来,其实也不是一件很简单的事。 我们还是先一步步的来考虑吧。金融行业其实涉及到的数据内容并不是成千上万,无法统计,恰恰相反,是比较少的。我们都可以在心底数得过来,象交易类型、帐号、帐户类型、密码、交易金额、交易手续费、日期时间、商户代码、2磁3磁数据、交易序列号等,把所有能够总结出来的都总结起来不过100个左右的数据。那我们可以首先简单的设计ISO8583,定义128个字段,将所有能够考虑到的类似上面提到的“帐号”等金融数据类型,按照一个顺序排起来,分别对应128个字段中的一个字段。每个数据类型占固定的长度,这个顺序和长度我们都事先定义好。这样就简单了,要发送一个报文时,就将128个字段按照顺序接起来,然后将接起来的整串数据包发送出去。 任何金融软件收到ISO8583包后,直接按照我们定义的规范解包即可,因为整个报文的128个字段从哪一位到哪一位代表什么,大家都知道,只要知道你的数据包是ISO8583包即可,我们都已经定义好了。比如第1个字段是“交易类型”,长度为4位,第2个字段位是“帐号”,为19位等等。接收方就可以先取4位,再取接着的19位,依次类推,直到整个数据包128个字段都解完为止。 其实这种做法真是简单直接,基本上就可以满足需要了。不过我们有几个问题要思考下: 1、 我怎么知道每个字段的数据类型呢,是数字还是字符?
2、 每个传送的报文都把128个字段都传过去,那网络带宽能够承受得了,有时候我可能只需要其中5个字段,结果多收到了123个无用的字段。
3、 如果我某些字段的长度不固定,属于变长怎么办,因为你现在解包是当作数据包每个字段都是固定的,用C语言解包时直接依靠指针取固定长度的一串字符做为一个字段。
我们来一一解决这些问题。 第一个问题简单,我在定义ISO8583时除了定义每个字段表示什么,还规定其内容是数字或是字符等即可。考虑可能出现的类型不过有以下几种:字母、数字、特殊字符、年月日等时间、二进制数据。比如我对128个字段中的“商户类型”字段定义其长度是15,同时定义其类型为字母。再精细点,如果“商户类型”里面的数据同时包括数字和字母呢?那我们就定义其类型为字母也可,为数字也可,即一个字段可以同时属于多个类型。 第二个问题稍微复杂点。其本质就是如果我只传128个字段的5个字段,接收方怎么知道我传了哪几个字段给它了。要是我们把剩下的123全部填成0或其他特殊标识,标明该字段不需要使用?这种处理方法没有半点用处,没有解决网络带宽的本质问题,还是要传128个字段。 换个思路,我在报文前面加上个包头,包头里面包含的信息能够让别人知道只传了5个字段。怎样设计这个包头,可以这样,我们用16个字节,即128个bit(一个字节等于8bit)来表示128个字段中的某个字段是否存在。每个bit在计算机的二进制里面不是1就是0,如果是1就表示对应的字段在本次报文中存在,如果是0就是不存在。这样好了,如果别人接收到了ISO8583报文,可以先根据最前面的报文头,就知道紧接着报文头后面的报文有哪些字段,没有哪些字段了。比如,我要发送5个字段,分别属于128个字段中的第2、3、6、8、9字段,我就可以将128bit的报文头填成011001011000000000…………,一共128个bit,后面就全是0了。注意其中第2、3、6、8、9位为1,其他都为0。 有了这个128bit的报文头,我们就可以只发送需要的5个字段了。怎样组织报文?先放上这128bit,即16个字节的头,然后在头后面放2、3、6、8、9字段,这些字段紧挨在一起,3和6之间也不需要填上4、5这两个字段了。接收方收到这个报文,它会根据128bit的报文头来解包,它自然知道把第3个字段取出后,就直接在第3字段的后面取第6个字段,每个字段的长度在ISO8583里面都定义好了,很轻松就把数据包解出来了。 这下好了,为了解决上面的第二问题,我们只是在报文中增加了16个字节的数据,就轻松搞定了,我们把这16个字节称为bit map,即位图,用来表示某个位是否存在。不过我们再稍微优化一下,考虑到很多时候报文不需要128个字段这么多,其一半64个字段都不一定能够用完。那我可以将报文头由128bit减到64bit,只有在需要的时候才把剩下的64bit放到报文里面,这样报文长度不又少了8个字节吗? 是个好主意。我们把ISO8583的128个字段中最常见的都放到前64个字段中,那我们可以将处理缩小一倍。这样我一般发送报文时只需发送64bit,即8个字节的报文头,再加上需要的几个字段就可以了。如果有些报文用到64到128之间的字段呢?这个也好办,我把64bit报文头的第一位bit用来代表特殊含义,如果该bit为1,则表示64bit后面跟了剩下的64bit报文头;如果第一位bit为0,则表示64bit后面没有跟剩下的64bit报文头,直接是128个字段中的报文了。那们,接收方会判断一下报头的第一个bit是1还是0,从而知道报文头是64bit还是128bit了,就可以做相应处理。因为报文头第二个64bit属于有时候有,所以我们叫它Extended bit map扩展位图,相应的报文头最开始的64bit我们叫它Primary bit map主位图。我们直接把扩展位图固定放到128个字段的第一个字段,而主位图每个数据包都有,就强制性放在所有128个字段的前面,并不归入128个字段中去。
第三个问题可以考虑这样解决。比如第2个字段是“帐号”,是不定长的,可能有的银行帐号是19位,有的是17位等。我们定ISO8583规范时可以规定第2个字段是25位,这下足够将19和17的情况都包含进来,但是如果以后出现了30位的怎么办?那我们现在将字段定为100位。以后超过100位怎么办,况且如果你只有19位的帐号,我们定义了100位,那81位的数据不是浪费了网络的带宽。看来预先定义一个我们认为比较大的位数是不太好的。 我们这样,对于第2个字段“帐号”,在字段的开头加上“帐号”的长度。比如帐号是0123456789,一共10位,我们变成100123456789,注意前面多了个10,表示后面的10位为帐号。如果你接触过COM里面的BSTR,应该对这种处理比较熟悉了。接收方收到该字段后,它知道ISO8583规定第2个字段“帐号”是变长的,所以会先取前面的2位出来,获取其值,此时为长度,然后根据该长度值知道应该拷贝该字段后面哪几位数据,才是真正的帐号。如果你觉得长度如果只有两位最多只能表示99位长,不太够,我们也定义可以允许前面3位都为长度的变长字段,这样就有999位长,应该够了吧。在规范里面如果我定义某个字段的属性是“LLVAR”,你注意了,其中的LL表示长度,VAR表示后面的数据,两个LL表示两位长,最大是99,如果是三位就是“LLLVAR”,最大是999。这样看我们定义的ISO8583规范文档时直接根据这几个字母就理解某个变长字段的意思了。 该解决的几个问题到这里都解决了,我们来回顾下自己设计的ISO8583规范。其实没有什么,无非是把金融行业可能出现的数据分门别类,排好顺序,接着把它们连接起来,组成一个报文发送出去而已。其中针对该报文的设计进行了一些优化,引入了bit map位图的概念,也算是一个不错的想法。 剩下的工作就简单了,我们就直接收集金融行业可能出现的数据字段类型,分成128个字段类型,如果没有到128个这么多就先保留一些下来,另外考虑到有些人有特殊的要求,我们规定可以将128个字段中的几个字段你自己来定义其内容,也算是一种扩展了。 这样,最后我们就得到了ISO8583规范的那张字段描述表了。想要详细的知道每个字段的含义直接对着表看就可以,比较简单。 所以在交互得时候银行一般会给你一个xml得映射表,表示每一位对应的是什么key,多长,还是可变或者定常。你对着他送过得来得字符串去截取就行
全文完
局部性原理:如果在同一个地方、同一个时间犯了错,那么将很可能继续在同一地方犯错。
昨天,早上更新数据时忘记去重文件中的不可见字符,原因是我更新数据没有严格按照自己之前的流程来操作,导致xml工具处理数据失败,耽误了同事的进度;
同一天,下午,为了赶着8点下班,7点把代码提交给mentor审核,mentor指出了2个问题,然后马上知错就改,并想着早点走,改完后再提交,mentor又在我改的地方找到2个很明显的错误。
欲速不达,这一天,心里不知道为啥,总是很着急的样子,结果导致同一天犯了太多的错误。
在前公司,有一个工程师说,一天写的代码不能超过100行,否则容易出bug。
首先,我们要在页面的最上方引用:
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
下面是JSTL中自带的方法列表以及其描述:
fn:contains(string, substring)
假如参数string中包含参数substring,返回true
例如:<c:if test="${fn:contains(name, searchString)}">
fn:containsIgnoreCase(string, substring)
假如参数string中包含参数substring(忽略大小写),返回true
例如:<c:if test="${fn:containsIgnoreCase(name, searchString)}">
fn:endsWith(string, suffix)
假如参数 string 以参数suffix结尾,返回true
例如:<c:if test="${fn:endsWith(filename, ".txt")}">
fn:escapeXml(string)
将有非凡意义的XML (和HTML)转换为对应的XML character entity code,并返回
例如: <字符应该转为< ${fn:escapeXml(param:info)}
fn:indexOf(string, substring)
返回参数substring在参数string中第一次出现的位置
${fn:indexOf(name, "-")}
fn:join(array, separator)
将一个给定的数组array用给定的间隔符separator串在一起,组成一个新的字符串并返回。
${fn:join(array, ";")}
fn:length(item)
返回参数item中包含元素的数量。参数Item类型是数组、collection或者String。假如是String类型,返回值是String中的字符数。
${fn:length(shoppingCart.products)}
fn:replace(string, before, after)
返回一个String对象。用参数after字符串替换参数string中所有出现参数before字符串的地方,并返回替换后的结果
${fn:replace(text, "-", "•")}
fn:split(string, separator)
返回一个数组,以参数separator 为分割符分割参数string,分割后的每一部分就是数组的一个元素
${fn:split(customerNames, ";")}
fn:startsWith(string, prefix)
假如参数string以参数prefix开头,返回true
<c:if test="${fn:startsWith(product.id, "100-")}">
fn:substring(string, begin, end)
在本地搭建好后端环境之后,我们来实现登录功能
1、安装SDK插件 SDK插件用来获取用户的openId
SDK是server端(也就是后端)的插件,帮助我们很容易的获取openId。openId是微信中用户身份的唯一标识,我们通过openId来识别用户,方便后期的用户管理
~/WeChatProjects/truth_hold$ npm install --save wafer2-client-sdk //系统返回信息 + wafer2-client-sdk@2.1.0 added 1 package from 1 contributor and audited 10626 packages in 10.382s > wafer2-client-sdk应用文档 https://github.com/tencentyun/wafer2-client-sdk 2、添加授权登录按钮 编辑src/pages/index/index.vue文件的template部分,添加授权登录的按钮
登录按钮是小程序小程序集成的API,规定的登录按钮的写法
<!-- 参考代码,无需粘贴 <template> <div> —> <!-- 需要粘贴的部分 --> <button open-type="getUserInfo" lang="zh_CN" class='btn' @getuserinfo="login">授权登录</button> 3、配置登录链接 编辑src/config.js文件,config.js文件我们用来放配置型的代码,用下面的代码替换掉原先的代码
登录链接为什么是http://localhost:5757/weapp/login,后面的课程会具体分析
//域名,通过域名来找到服务器,在这里我们将本地电脑当成服务器 //所以现在配置的域名是本地的,当项目实际上线,这里需要换成已备案的域名 const host = 'http://localhost:5757' const config = { host, loginUrl: `${host}/weapp/login` } //我们在【ES6知识点详解】中讲过export的意思是向外暴露接口 //这样在其他文件中可以通过import config from '@/config'引用 //然后通过config.loginUrl就能得到在本文件中配置的值'http://localhost:5757/weapp/login' export default config 4、删除测试代码 在第二章学习ES6时,我们在index.
import jieba import pandas as pd import os 定义一个获取分词结果的函数,以列表形式返回:
def get_jieba_output(corpus_dataframe): word_set=[] # 空列表 for i in corpus_dataframe[0]: # 因为地名信息是数据框的第一列 obj_list = i for jie in jieba.cut(obj_list,cut_all=True): if len(jie) <2: # 长度小于2的词忽略掉 pass else: if jie not in word_set: # 不添加重复项 word_set.append(jie) else: pass word_list = obj_list.split(sep='|') # 因为原数据中省名、市名、区名等是由 | 分隔开的 for word in word_list: if word not in word_set: # 不添加重复项 word_set.append(word) else: continue return word_set 定义得到省及直辖市名的函数,返回一个相当于集合的列表:
def get_all_prov(corpus_dataframe): prov_set=[] for i in range(len(corpus_dataframe)): obj_list=corpus[0][i] word_list = obj_list.
文章目录 前言 一、多人聊天系统1.1 客户端1.2 服务器端 二、运行效果2.1 初始化2.2 登录成功2.3 发送信息2.4 发送文件 前言 GitHub地址:https://github.com/Samven7/multichat-system
开发环境:Eclipse Java 2019-06
注意:本项目只在单主机运行调试过,没试过在局域网和不同主机之间接发消息和文件(估计不行),有需要的自行查阅资料。
一、多人聊天系统 1.1 客户端 Login.java:登录界面
// Login.java package exp5; import java.awt.*; import javax.swing.*; public class Login { JTextField textField = null; JPasswordField pwdField = null; ClientReadAndPrint.LoginListen listener=null; // 构造函数 public Login() { init(); } void init() { JFrame jf = new JFrame("登录"); jf.setBounds(500, 250, 310, 210); jf.setResizable(false); // 设置是否缩放 JPanel jp1 = new JPanel(); JLabel headJLabel = new JLabel("
([\d]{4}(((0[13578]|1[02])((0[1-9])|([12][0-9])|(3[01])))|(((0[469])|11)((0[1-9])|([12][0-9])|30))|(02((0[1-9])|(1[0-9])|(2[0-8])))))|((((([02468][048])|([13579][26]))00)|([0-9]{2}(([02468][048])|([13579][26]))))(((0[13578]|1[02])((0[1-9])|([12][0-9])|(3[01])))|(((0[469])|11)((0[1-9])|([12][0-9])|30))|(02((0[1-9])|(1[0-9])|(2[0-9])))))
学习嵌入式,安装了keil5
淘宝买的J-link,按照提供的资料安装的J-link驱动V4.92
在keil5配置时都没有问题,编译后LOAD到开发板时,keil5就闪退,并提示-----The connected J-Link is defective,Proper operation cannot be guaranteed.
参考前辈们的帖子,原因如下:
高版本的keil5默认安装的J-Link驱动与我使用的J-link不匹配
解决方法:
更换J-link或更换J-link驱动,我选择后者
更换J-link驱动即换成低版本
(1)若原本有旧版本J-link驱动,可以将安装路径下的这仨文件拷贝下来
覆盖keil安装目录的keil/ARM/Segger中的对应文件
(2)原本没有J-link驱动的可以去官网下载 https://www.segger.com/downloads/jlink/
安装,把安装文件夹下的“JLink.exe”、“JLinkARM.dll”、“JLinkRDI.dll”拷贝覆盖keil安装目录的keil/ARM/Segger里面对应的文件。
然后打开配置窗口
发现dll原本为V6.16变成了V4.92,再次Load不再闪退即成功!
面对这样的需求 从下面地址详情中提取其所在行政区域(省、市、县/区 ),切分为右边表格的形式。
地址详情映射后地址信息详细地址省市县/区详细地址平罗县御景安家25-1-102宁夏回族自治区石嘴山市平罗县御景安家25-1-102达州渠县渠江镇珠山村一组57号四川省达州市渠县渠江镇珠山村一组57号兴庆区在水一方C区5-3-101宁夏回族自治区银川市兴庆区在水一方C区5-3-101成都市武侯区佳灵路九峰家园2栋四川省成都市武侯区佳灵路九峰家园2栋大田县集美路21号福建省三明市大田县集美路21号邢台桥东区高开东汪镇西静庵村河北省邢台市桥东区高开东汪镇西静庵村 方法一 pip install cpca 原理是通过jieba工具先对详细地址做分词,再将结果分段对比行政地区域地址库,代码如下:
import cpca area_str = ["平罗县御景安家25-1-102"] df_str = cpca.transform(area_str ) df_str 结果展示:
省 市 区 地址宁夏回族自治区 石嘴山市 平罗县 御景安家25-1-102 经纬度解析 cpca.latlng 以字典的形式将全国的行政区域经纬度保存(如下图:)
我们直接从该字典中查询行政区域对应的经纬度即可(如下:)
cpca.latlng['北京市', '北京市', '西城区'] 结果:('39.93428014370851', '116.37319010401802') 另一种类似的方法也可以解析地址经纬度(如下:)
方法二 pip install chinese_province_city_area_mapper 原理与方法相似,但在使用过程要比方法一更上手,很多拼写不全的地址用方法二都可以映射正确的省市县。实验以下地址的时候使用方法一解析失败,使用方法二解析成功,如下:
from chinese_province_city_area_mapper.transformer import CPCATransformer Ca = CPCATransformer() Ca.transform(['湖南省株洲县朱亭镇水口村跃进组12号', '青海省海东地区乐都县高庙镇白崖子村42号', '湖南省株洲县渌口镇凯裕名城B栋4单元301 ']) 使用chinese_province_city_area_mapper解析结果:
使用cpca解析结果:
只有市级和市级以下的行政区域存在重名的情况,例如中国有很多城市的区叫“朝阳区” ,如果详细地址中没有别的地址描述的话系统是不知道应该映射到哪个“朝阳区”,所以我们需要为一些市区指定默认所属省。
有两种方式指定默认值:
# 方法一:直接通过 CPCATransformer 指定 cpca = CPCATransformer({"朝阳区":"北京市"}) df = cpca.transform(location_str) # 方法二:通过内置模块 umap 调用默认地址字典 from chinese_province_city_area_mapper import myumap cpca = CPCATransformer(myumap.
使input文本框不可编辑的3种方法:
1、disabled 属性:规定禁用 input 元素,被禁用的 input 元素,不可编辑,不可复制,不可选择,不能接收焦点,后台也不会接收到传值。设置后文字的颜色会变成灰色。disabled 属性无法与 一起使用。
示例:<input type="text" disabled="disabled" />
2、readonly 属性:规定输入字段为只读可复制,但是,用户可以使用Tab键切换到该字段,可选择,可以接收焦点,还可以选中或拷贝其文本。后台会接收到传值. readonly 属性可以防止用户对值进行修改。
readonly 属性可与 或 配合使用。
示例:<input type="text" readonly="readonly">
3、readonly unselectable=“on” 属性:跟disable类似,input 元素,不可编辑,不可复制,不可选择,不能接收焦点,设置后文字的颜色也会变成灰色,但是后台可以接收到传值。和disabled的区别就是可以向后台传值
这种没有任何报错却返回为空的基本原因都在你提供post数据有误的问题,
【解决方法】:提供的post数据一定得是json字符串,不要直接传数组过去
【请求数据例子】: