Nodejs学习(六)--异步流控制

1.串行无关联 2.并行无关联 3.串行有关联 4.paralleLimit:与paralle相似, 但是多了一个limit, limit参数限制任务只能同时并发一定的数量, 而不是无限制的并发 1.串行无关联 var async = require('async') function oneFun() { var ii=0; setInterval(function() { console.log('aaaaaa' + new Date()); ii++; if (ii == 3){ clearInterval(this); } }, 1000) console.log('oneFun') } function twoFun() { console.log('twoFun') } function exec() { async.series( { one:function(done) { var ii=0; setInterval(function() { console.log('aaaaaa' + new Date()); ii++; if (ii == 3){ clearInterval(this); done(null,'one completed'); } }, 1000) }, two:function(done) { var jj=0; setInterval(function() { console.

php 错误级别日志

1、error_reporting(“E_ALL”) 设置错误显示等级 下面列举一些错误报告级别: 值 常量 说明 1 E_ERROR 报告导致脚本终止运行的致命错误 2 E_WARNING 报告运行时的警告类错误(脚本不会终止运行) 4 E_PARSE 报告编译时的语法解析错误 8 E_NOTICE 报告通知类错误,脚本可能会产生错误 32767 E_ALL 报告所有的可能出现的错误(不同的PHP版本,常量E_ALL的值也可能不同) <?php //禁用错误报告 error_reporting(0); //报告运行时错误 error_reporting(E_ERROR | E_WARNING | E_PARSE); //报告所有错误 error_reporting(E_ALL); ?> 2、ini_set(“display_errors”, “on”) 设置让php显示错误,在关于错误显示控制中,其优先级最高 注意:配置文件php.ini中display_errors的默认值为On,代表显示错误提示,如果设置为Off,就会关闭所有的错误提示。 使用 error_reporting(0) 或者在函数前面加 @,可以抑制错误输出,以防止错误消息泄露敏感信息。 3、ini_set('error_log', dirname(__FILE__) . '/error_log.txt'); 设置错误日志文件 4、注册错误日志文件 //注册错误日志处理函数 /** * 错误处理函数 * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline */ function errHandler($errno,$errstr,$errfile,$errline){ $msg = "

五种使用python储存数据的方式

在python编程开发中,总是不可避免的遇到数据储存的问题,下面就介绍python与几种数据储存方式交互的方法。 json文件 json是一种轻量级的数据交换格式。采用完全独立于编程语言的文本格式来存储和表示数据。层次结构简洁而清晰,易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。 最主要的是,通过json这个包可以很方便的解决无论是py2还是py3中的编码问题,json的内容结构也近似于python中的字典和列表,操作起来特别方便。 import json # 此时有一个json文件,结构大概是 [{},{},{}...] 打开这个文件 # 使用json load读取文件内容,然后可以直接用列表或者字典的方式去操作con这个变量 con = json.loads(content) # 那么如何储存为json文件呢? # 使用dumps将列表序列化并且转换为unicode编码,储存的时候,就可以存你最喜欢的utf-8了 lis = [{},{},{}...] data = json.dumps(lis, ensure_ascii=False) f.write(data.encode('utf-8')) csv文件 转换为csv文件后,我们就可以直接用excel打开拉图表了 import csv # 打开文件 with open(filename, 'w') as f: writer = csv.writer(f) # 构造写入器 data = ('1','2','3') # 填写三格 data = ('','','3') # 填写一格,前两格空起来 data = ('1','') # 填写第一格,后面无论多少格都空起来 writer.writerow(data) # writerow每执行一次,写入一行 注意其中的参数data需要是一个元组 # 注意,在windows中,打开文件需要使用 with open(filename, 'w', newline='') as f: # 否则每写一行都会多一个空行 # 原因是 windows中换行符号是 \n\r ,csv库中并没有做特别的处理,所以会产生空行 MySQL数据库

Feign client 设置请求头信息

2019独角兽企业重金招聘Python工程师标准>>> Feign client端 @FeignClient(url = "${test.url}", name = "cclient",configuration= ClientConfiguration.class,fallback = APIClientFallback.class) public interface APIClient { @RequestMapping(method = RequestMethod.POST, value = "/check/test") String checkResult(@RequestParam("sendTelNo") String sendTelNo,@RequestParam("certType") String certType,@RequestParam("certCode") String certCode,@RequestParam("userName") String userName); @RequestMapping(method = RequestMethod.POST, value = "/userstaus/test") String inusetime(@RequestParam("sendTelNo") String sendTelNo); @RequestMapping(method = RequestMethod.POST, value = "/userstaus/test") String offnetIdentify(@RequestParam("sendTelNo") String sendTelNo,@RequestParam("date") String date); 配置文件 application-dev.yml test: url: https://xxxxxx:8243/test tokenId: 11111112222222 feign configuration 这里配置全局的请求头和 token @Configuration public class ClientConfiguration { @Value("

拟合函数

拟合函数是用于曲线拟合的函数。拟合是指已知某若干离散函数值{f1,f2,…,fn},通过调整该函数中的若干待定系数f(λ1,λ2,…,λn),使得该函数与已知点集的差别(最小二乘的意义)最小。 在一个函数中,如果只知道x和y有关,但是不知道是神马关系,只能通过实验得到一组数据,如x=x1时y=y1,x=x2时y=y2,…这里(x1,y1)、(x2,y2)、…都是实验结果。则可以在直角坐标系中画出各个坐标点,描点可观察到两者关系的曲线。根据曲线的形状选择适合的函数,如果是线性的,叫作线性拟合或者线性回归,否则叫作非线性拟合或非线性回归,可以选择y是x的多项式,如y=a*x*x*x+b*x*x+c*x+d等等,也可以是其他形式的函数类型,然后利用最小二乘法或其他拟合方法求出系数a,b,c,d等,即可得到y和x的关系,这个过程就是曲线拟合,这个函数就是拟合函数。由于实验有误差,选择的函数也不一定就很合适,拟合出来的函数一般难以准确通过各点,但可以离各点尽量近,从而近似地表示y和x的关系。表达式也可以是分段函数,叫作样条拟合。 形象的说,拟合就是把平面上一系列的点,用一条光滑的曲线连接起来。因为这条曲线有无数种可能,从而有各种拟合方法。拟合的曲线一般可以用函数表示,根据这个函数的不同有不同的拟合名字。 拟合以及插值还有逼近是数值分析的三大基础工具,通俗意义上它们的区别在于:拟合是已知点列,从整体上靠近它们;插值是已知点列并且完全经过点列;逼近是已知曲线,或者点列,通过逼近使得构造的函数无限靠近它们。

framework添加res资源并打包进新的Android.jar

编译带有资源的jar包,需要更改frameworks层,方法如下: 一.增加png类型的图片资源 1.将appupdate模块所有用到的png格式图片拷贝到framework/base/core/res/res/drawable-mdpi里。但是要确保没有与原生的没有重名文件。 2.在framework/base/core/res/res/values/public.xml文件里增加对这些图片的声明。(例: ,此id要保证唯一,以drawable类型的最后一个id为基数增加) 3.framework/base/core/res/res/ 下mm编译 4. \Honeycomb下 make update-api 二.增加string资源 1.将appupdate模块定义的string.xml里面的所以string拷贝到framework/base/core/res/res/values/string.xml里。但是确保没有重名的。 2.在framework/base/core/res/res/values/public.xml文件里增加对这些string的声明。(例:此id要保证唯一,以string类型的最后一个id为基数增加) 3.framework/base/core/res/res/ 下mm编译 4. \Honeycomb下 make update-api 三.增加layout资源 1.将appupdate模块的layout文件里定义的5个xml文件拷贝到在framework/base/core/res/res/layout里。但是要确保没有重名文件被覆盖。 2.在framework/base/core/res/res/values/public.xml文件里增加对这些layout的声明。(例:此id要保证唯一,以layout类型的最后一个id为基数增加) 3.framework/base/core/res/res/ 下mm编译 4. \Honeycomb下 make update-api 说明:若layout中包含xml,直接把xml拷贝到framework相应目录下。 例如(1)button的selector。将appupdate模块的drawable/common_btn_selector.xml文件拷贝到framework/base/core/res/res/drawable里,确保没有重名文件。 (2)将appupdate模块的anim/loading.xml文件拷贝到framework/base/core/res/res/anim里,确保没有重名文件。 四.增加style资源 1.将appupdate模块的style文件里定义的所有style拷贝到framework/base/core/res/res/values/style.xml里。确保没有覆盖原生的style. 2.在framework/base/core/res/res/values/public.xml文件里增加对这些style的声明。 3.framework/base/core/res/res/ 下mm编译 4. \Honeycomb下 make update-api 五.增加color资源 1.将appupdate模块的style文件里定义的所有style拷贝到framework/base/core/res/res/values/color.xml里。确保没有覆盖原生的color. 2.在framework/base/core/res/res/values/public.xml文件里增加对这些color的声明。 3.framework/base/core/res/res/ 下mm编译 4. \Honeycomb下 make update-api 六.增加资源id 1.在framework/base/core/res/res/values/ids.xml里定义你jar中所用的id(R.id)*)。确保没有覆盖原生的. 2.在framework/base/core/res/res/values/public.xml文件里增加对这些id的声明。 3.framework/base/core/res/res/ 下mm编译 4. \Honeycomb下 make update-api 最后,eclipse源码中要修改以下: 1. 把R.*.*全部替换成android.R.*.*例如R.layout.appupg_tip_dialog 要更换为android.R.layout.appupg_tip_dialog 2. 资源文件中对资源的调用需要添加android:如<textview p="" <="" 要改成 3. Import *.

在framework下新建系统api

过程如下: 先在framework/base 下创建一目录叫venus /venus 目录下有两个文件夹: |-- java | `-- android`-- jni |-- Android.mk |-- jni.cpp java 下的类包遵循java 类包命名规则,好了,进入关键的第二步: 在文件build/core/pathmap.mk中的FRAMEWORKS_BASE_SUBDIRS变量里添加 venus\ OK,大功告成, 在Android 源码目录执行如下命令: make update-api make make PRODUCT-sdk-sdk 新增的接口在源码环境和SDK环境中都有了,存放在 android.jar 里 ------------------------------------------------------------------------------------ 最近因项目需要,在frameworks\base\core\java\android\preference里面新添加了一个继承TwoStatePreference的类XXXSwitchPreference 经过查证后得知: Android SDK中有些JAVA类是开放的,有些是不开放的,API同样如此。这里所谓开放的类或API,只是javadoc的范畴,并不是java中public和private,也就是说,对于源码的编译无所谓,但是对android的上层应用有影响,因为非开放的类或API,android上层应用无法直接访问。 对于在原有的类中添加方法,google 给了两个解决方法: 1. 在你添加的API或者变量前面,增加 javadoc 注释@hide。但是要注意的是,并不是简单写个@hide 或者 /*@hide*/ 就可以了,这些都是错误的javadoc注释格式,标准的javadoc都是这样的 /** */ 而且对于 format 变量 应该加上 { }。应该写成 /** {@hide} */ 2.想要在生成的javadoc里面出现这个方法或者变量,你必须执行: make update-api 1 这样的话,系统自动将新增加的API添加到frameworks\base\api\current.txt中了,但是如果修改的是google没有开放出来的类,比如RIL,PhoneFactory,就不会出现这个问题。 而如果要加进新的类, 1、在原有的包下面加类,这个最简单,加完之后执行make update-api,在frameworks\base\api\current.txt中会自动增加一段代码 2、若加在framework/base下面,这时你make update-api是不会在frameworks\base\api\current.txt里生成你新增的API的。这时,需要修改android源码根目录下的build/core/pathmap.mk把你的目录加进去.(未经亲自验证) ------------------------------------------------------------------------------------ 如何向Android的framework里添加新类 google对于所有的类和API,分为开放式和不开放式两种。所谓的开放式就是值javadoc所包含的,并不是java中有public和private,而是跟javadoc有关系,代码 没有关系。

利用JMeter进行Tomcat调优

九月底面华为的时候被问到了Tomcat调优,答得不好,趁着十一国庆这几天简单的研究了一下,现在总结下。 Tomcat的优化分成Tomcat启动命令行中的优化参数即JVM优化以及Tomcat容器自身参数的优化。这里分别对我本机(Win10)上以及学院集群上(Redhat)的Tomcat进行调优 一. Windows环境Tomcat调优 1.1本机(Win10)Tomcat调优 Tomcat首先跑在JVM之上的,因为它的启动其实也只是一个java命令行,首先我们需要对这个JAVA的启动命令行进行调优,修改catalina.bat(apache-tomcat-9.0.0.M22\bin),添加启动参数 set JAVA_OPTS=-server -Xms5000M -Xmx5000M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking 参数解释: 1)-Xms&-Xmx:设置初始堆大小&最大堆大小 2)-Xss:设置线程栈大小 3)-XX:+AggressiveOpts:使用最新加入的优化技术 4)-XX:+UseBiasedLocking:优化线程锁 记得从startup.bat启动tomcat。如果利用windows的系统服务启动tomcat服务,上面的设置就不生效了,就是说set JAVA_OPTS没起作用。 windows服务执行的是bin\tomcat.exe.他读取注册表中的值,而不是catalina.bat的设置.。 启动参数有好多,这里简单设置了几个常用的,后面有时间再调试其他参数。 接下来进行Tomcat容器内的优化,增加吞吐量。打开tomcat安装目录\conf\server.xml文件,定位到这一行: <Connector port="8080" protocol="HTTP/1.1" 改为 <Connector port="8080" protocol="HTTP/1.1" URIEncoding="UTF-8" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" disableUploadTimeout="true" connectionTimeout="20000" acceptCount="300" maxThreads="300" maxProcessors="1000" minProcessors="5" useURIValidationHack="false" compression="on" compressionMinSize="2048" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" redirectPort="8443" /> 参数解释: 1)URIEncoding=”UTF-8”:使得tomcat可以解析含有中文名的文件的url 2)maxSpareThreads:如果空闲状态的线程数多于设置的数目,则将这些线程中止,减少这个池中的线程总数。 3)minSpareThreads:最小备用线程数,tomcat启动时的初始化的线程数。 4)connectionTimeout:网络连接超时时间毫秒数 5)maxThreads:使得tomcat可以解析含有中文名的文件的url 6)maxSpareThreads:表示Tomcat可创建的最大的线程数,即最大并发数。 7)acceptCount:当线程数达到maxThreads后,后续请求会被放入一个等待队列,这个acceptCount是这个队列的大小。 1.2本机(Win10)JMeter测试结果 利用压力测试软件Jmeter模拟2000*100个线程请求不断的访问localhost:8080。运行结果截图可得:: 调优前 调优后 参数解释: 1)Samples:表示你这次测试中一共发出了多少个请求,这里模拟了100个用户,每个用户迭代2000次,那么这里显示200000。 2)Average:平均响应时间——默认情况下是单个 Request 的平均响应时间。 3)Max:最大响应时间. 4)Throughput:吞吐量——默认情况下表示每秒完成的请求数(Request per Second)。 由于是本机测试发布服务本机测试,测试结果很可能不精确。但是通过Throughput可见调优后的Tomcat吞吐量明显提高了。 二. Linux环境Tomcat调优 2.

TCP的seq和ack号计算方法

seq和ack号存在于TCP报文段的首部中,seq是序号,ack是确认号,大小均为4字节(注意与大写的ACK不同,ACK是6个控制位之一,大小只有一位, 仅当 ACK=1 时ack字段才有效。建立 TCP 连接后,所有报文段都必须把 ACK 字段置为 1。) seq:占 4 字节,序号范围[0,2^32-1],序号增加到 2^32-1 后,下个序号又回到 0。TCP 是面向字节流的,通过 TCP 传送的字节流中的每个字节都按顺序编号,而报头中的序号字段值则指的是本报文段数据的第一个字节的序号。 ack:占 4 字节,期望收到对方下个报文段的第一个数据字节的序号。 1、三次握手过程中seq和ack的值: 一个TCP连接的建立是通过三次握手来实现的 1. (A) –> [SYN] –> (B) 假如服务器B和客户机A通讯. 当A要和B通信时,A首先向B发一个SYN (Synchronize) 标记的包,告诉B请求建立连接. 注意: 一个 SYN包就是仅SYN标记设为1的TCP包(参见TCP包头Resources). 认识到这点很重要,只有当B受到A发来的SYN包,才可建立连接,除此之外别无他法。因此,如果你的防火墙丢弃所有的发往外网接口的SYN包,那么你将不能主动连接外部任何主机,除非不是TCP协议。 2. (A) <– [SYN/ACK] <–(B) 接着,B收到后会发一个对SYN包的确认包(SYN/ACK)回去,表示对第一个SYN包的确认,并继续握手操作. 注意: SYN/ACK包是仅SYN 和 ACK 标记为1的包. 3. (A) –> [ACK] –> (B) A收到SYN/ACK 包,A发一个确认包(ACK),通知B连接已建立。至此,三次握手完成,一个TCP连接完成 Note: ACK包就是仅ACK 标记设为1的TCP包. 需要注意的是当三此握手完成、连接建立以后,TCP连接的每个包都会设置ACK位 握手阶段: 序号方向seqackSYNACK1A->B100000102B->A2000010000+1=10001113A->B1000120000+1=2000101 解释: 1:A向B发起连接请求,以一个随机数初始化A的seq,这里假设为10000,此时ACK=0 2:B收到A的连接请求后,也以一个随机数初始化B的seq,这里假设为20000,意思是:你的请求我已收到,我这方的数据流就从这个数开始。B的ACK是A的seq加1,即10000+1=10001 3:A收到B的回复后,它的seq是它的上个请求的seq加1,即10000+1=10001,意思也是:你的回复我收到了,我这方的数据流就从这个数开始。A此时的ACK是B的seq加1,即20000+1=20001 2、数据传输过程中seq和ack的值: 序号方向seqacksize23A->B40000 70000 1514 24B->A 70000 40000+1514-54=41460 54 25A->B4146070000+54-54=70000151426B->A70000 41460+1514-54=42920 54 解释: 23:B接收到A发来的seq=40000,ack=70000,size=1518的数据包 24:于是B向A也发一个数据包,告诉A,你的上个包我收到了。A的seq就以它收到的数据包的ack填充,ack是它收到的数据包的seq加上数据包的大小(不包括:以太网协议头=14字节,IP头=20字节,TCP头=20字节),以证实B发过来的数据全收到了。 25:A在收到B发过来的ack为41460的数据包时,一看到41460,正好是它的上个数据包的seq加上包的大小,就明白,上次发送的数据包已安全到达。于是它再发一个数据包给B。这个正在发送的数据包的seq也以它收到的数据包的ack填充,ack 就以它收到的数据包的seq(70000)加上包的size(54)填充,即ack=70000+54-54(全是头长,没数据项)。 减去54的原因见下图(链路层使用的是Ethernet II 格式,这个格式有14字节以太网首部+4字节以太网尾部): 应用数据=size-14-20-20=size-54。(假设IP首部和TCP首部都没有可选选项) 为什么不减去以太网尾部的4字节呢? 因为在物理层上网卡要先去掉前导同步码和帧开始定界符,然后对帧进行CRC检验,如果帧校验和错,就丢弃此帧。如果校验和正确,就判断帧的目 的硬件地址是否符合自己的接收条件(目的地址是自己的物理硬件地址、广播地址、可接收的多播硬件地址等),如果符合,就将帧交“设备驱动程序”做进一步处 理。这时我们的抓包软件才能抓到数据,因此,抓包软件抓到的是去掉前导同步码、帧开始分界符、FCS之外的数据, 3、四次挥手过程中seq和ack的值: TCP连接的结束是四次挥手的过程,ACK一直等于1 序号方向seqackFINACK1A->B8000090000112B->A9000080000+1=80001013B->A9500080001114A->B8000195000+1=9500101 1.

将InputStream转换为byte数组

感觉不难,但用的时候一时半会写不出来,浪费时间,于是记录下来。 public static byte[] read(InputStream inputStream) throws IOException { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int num = inputStream.read(buffer); while (num != -1) { baos.write(buffer, 0, num); num = inputStream.read(buffer); } baos.flush(); return baos.toByteArray(); } finally { if (inputStream != null) { inputStream.close(); } } }

WPF特效-鱼游动动画3

WPF不支持骨骼,故使用3DMax导出了序列模型文件(.mtl;.obj)。 方法1: 使用Blend 2013打开所有obj文件,拖动排列一下即可在usercontrol中显示,使用RenderTargetBitmap生成png的序列图,使用Timer播放序列图即可。 方法2: WPF有很多动态加载obj模型文件的类库,使用循环方法,动态加载所有obj文件,动态生成每个obj对应的序列图。(尚未尝试,理论毫无问题)。 方法3: 使用Unity3D 打开导出的带骨骼的模型文件,生成png序列图在WPF中加载(尚未尝试)。 方法一详细: 1、Blend打开obj序列并排列(blend项目可以用vs打开,下图为VS中呈现的效果,使用了5个Obj文件,用于测试) 2、使用RenderTargetBitmap生成png序列图 string sTargetFile = AppDomain.CurrentDomain.BaseDirectory + "Fish1.png"; RenderTargetBitmap oRenderTargetBitmap = new RenderTargetBitmap((int)this.GdMainZm.Width, (int)this.GdMainZm.Height, 96, 96, PixelFormats.Pbgra32); oRenderTargetBitmap.Render(this.GdMainZm); PngBitmapEncoder oPngEncoder = new PngBitmapEncoder(); oPngEncoder.Frames.Add(BitmapFrame.Create(oRenderTargetBitmap)); using (Stream stm = File.Create(sTargetFile)) { oPngEncoder.Save(stm); stm.Close(); } 运行后生成的png效果图如下: 3、使用Timer播放序列图 private ImageSource ImageSrc; private DispatcherTimer TimerPlay; private int Index = -1; private void FishItem8_Loaded(object sender, RoutedEventArgs e) { this.Loaded -= FishItem8_Loaded; AsynchUtils.AsynchDelayExecuteFunc(() => { this.

设计算法,把十进制整数转换为二至九进制之间的任一进制输出。

设计算法,把十进制整数转换为二至九进制之间的任一进制输出。 #include<iostream> using namespace std; typedef struct Node{ int data; struct Node *next; }LinkStack; LinkStack *Push(LinkStack *LS,int x){ LinkStack *p; p=(LinkStack *)malloc(sizeof(LinkStack)); p->data=x; p->next=LS; LS=p; return LS; } LinkStack *Transform(LinkStack *LS) { int n=0,d=0; cout<<"请输入要转换的整数:"; cin>>n; cout<<endl; cout<<"请输入基数(2-9之间):"; cin>>d; if(n<0||d<2||d>9) { cout<<"输入错误!"<<endl; exit(0); } if(n==0) LS=Push(LS,0); while(n) { LS=Push(LS,n%d); n=n/d; }return LS; } void Print(LinkStack *LS){ LinkStack *p; p=LS; cout<<"转换的结果为:"<<endl; while(p!=NULL) { cout<<p->data; p=p->next; }cout<<endl; } void main(){ LinkStack *LS; LS=NULL; LS=Transform(LS); Print(LS); }

Python获取全国所有的省、市、县、镇、村

#!/usr/bin/python3 # -*- coding: utf-8 -*- # author=He """ 通过国家统计局数据 获取中国所有城市列表 """ import sys import os import re from urllib import request from bs4 import BeautifulSoup sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) url = 'http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/' header = { 'Cookie': 'AD_RS_COOKIE=20080917', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \ AppleWeb\Kit/537.36 (KHTML, like Gecko)\ ' 'Chrome/58.0.3029.110 Safari/537.36'} class GetHttp: def __init__(self, url, headers=None, charset='utf8'): if headers is None: headers = {} self._response = '' try: print(url) self.

用C语言实现在一个链表删除指定的一个或多个元素

#include<stdio.h> #include<stdlib.h> typedef struct node{ int data; struct node *next; }LinkList; //创建一个链表 LinkList *Creatlist_L(LinkList *L,int n){ LinkList *p,*h; L=(LinkList*)malloc(sizeof(LinkList)); L->next=NULL; h=L; for(int i=0;i<n;i++){ p=(LinkList*)malloc(sizeof(LinkList)); scanf("%d",&p->data); p->next=h->next; h->next=p; } return L; } //删除指定的元素 LinkList *deletenode(LinkList *head,int m){ LinkList *p,*q,*s; p=head; q=head->next; while(q){ if(q->data==m){ p->next=q->next; s=q; q=q->next; free(s); }else{ p=p->next; q=q->next; } } return head; } //输出链表 void printlist(LinkList *head){ LinkList *p; p=head->next; if(!p){ printf("The link is NULL!"); exit(0); } while(p){ printf("

递归删除链表中的指定元素x

/* 问题描述:递归删除链表中的x 说明:此处要注意的是,在递归删除x的时候,中间并没有产生断链。因为函数传递的是引用。 关于引用,这次又详细的查了一下。特说明如下: 其实引用,在教材上被解释成别名。就是给变量另起一个名字。从本质上说,其实并没有引用这回事,引用的内部实现过程还是利用指针来实现的。 比如说:int i; int &j = i; 然后我们就可以说j是i的引用了,在编译器编译的时候,一般来说,它会把上面的第二条语句翻译成这样, int const *j = &i;然后在程序中所有用到j的地方都用*j来代替。只是对于我们来说,这个过程被屏蔽了。我们不用再去管j这个指针,使用时直接当成和i相似的变量就行。个人觉得普通的变量用引用没什么必要,在C++中更多的当成指针的引用来传递参数,使得在函数内部可以改变指针所指的对象,这个在链表中用的较多。其实在也可以用C语言的二重指针实现,可能是因为二重指针有点烦,易出错,所以C++才规定了引用这个东西,把引用给包装了起来。在深入一点,JAVA中连指针也没有了,应该是在C++的基础上用了更高层次的封装了吧。 */ //删除x(普通方法) void Delete_x(LinkList &L,int x) { LNode *p = L,*q; while(p->next !=NULL) { q = p->next; if(x == q->data) { p->next = q->next; delete q; } else p = p->next; } } //递归删除元素x void Del_xByRecursion(LinkList &L,int x) { LNode *p; if(L == NULL) //如果为空,则返回 return ; if(L->data == x) //如果L指向x,则删除当前指针 { p = L; L = L->next; //注意此处并没有造成短链,因为函数传递的是引用的缘故 delete p; Del_xByRecursion(L,x); } else Del_xByRecursion(L->next,x); } 附:

从零开始写Python爬虫 --- 1.5 爬虫实践: 获取百度贴吧内容

从零开始写Python爬虫 --- 1.5 爬虫实践: 获取百度贴吧内容 Ehco 5 个月前 经过前期大量的学习与准备,我们重要要开始写第一个真正意义上的爬虫了。本次我们要爬取的网站是:百度贴吧,一个非常适合新人练手的地方,那么让我们开始吧。 本次要爬的贴吧是<< 生活大爆炸吧 >>,生活大爆炸是我一直很喜欢的一部美剧,平时有空也会去看看吧友们都在聊些什么。所以这次选取这个吧来作为实验材料。 贴吧地址 : http://tieba.baidu.com/f?kw=%E7%94%9F%E6%B4%BB%E5%A4%A7%E7%88%86%E7%82%B8&ie=utf-8 Python版本 : 3.6 浏览器版本: Chrome 目标分析: 由于是第一个实验性质爬虫,我们要做的不多,我们需要做的就是: 从网上爬下特定页码的网页 对于爬下的页面内容进行简单的筛选分析 找到每一篇帖子的 标题、发帖人、日期、楼层、以及跳转链接 将结果保存到文本。 前期准备: 看到贴吧的url地址是不是觉得很乱?有那一大串认不得的字符? 其实这些都是中文字符, %E7%94%9F%E6%B4%BB%E5%A4%A7%E7%88%86%E7%82%B8 在编码之后就是: 生活大爆炸 。 链接的末尾处:&ie=utf-8 表示该连接采用的是utf-8编码。 windows的默认编码是GBK,在处理这个连接的时候,需要我们在Python里手动设置一下,才能够成功使用。 Python3相对于Python2对于编码的支持有了很大的提升,默认全局采用utf-8编码,所以建议还在学Python2的小伙伴赶紧投入Python3的怀抱,真的省了老大的功夫了。 接着我们翻到贴吧的第二页: url: `url: http://tieba.baidu.com/f?kw=%E7%94%9F%E6%B4%BB%E5%A4%A7%E7%88%86%E7%82%B8&ie=utf-8&pn=50` 注意到没有,连接的末尾处多了一个参数&pn=50, 这里我们很容易就能猜到,这个参数的与页码的联系: &pn=0 : 首页 &pn=50: 第二页 &pn=100:第三页 &pn=50*n 第n页 50 表示 每一页都有50篇帖子。 这下我们就能通过简单的url修改,达到翻页的效果了。 chrome开发人员工具的使用: 要写爬虫,我们一定要会使用开发工具,说起来这个工具是给前段开发人员用的,但是我们可以通过它快速定位我们要爬取的信息,并找到相对应的规律。 按cmd+opt+I 打开chrome工具,(win可以看按F12或者手动在chrome工具栏里打开) 使用模拟点击工具快速定位到一个单独帖子的位置。(左上角的鼠标箭头图标) 我们仔细的观察一下,发现每个帖子的内容都包裹在一个li标签内: <li class=" j_thread_list clearfix"> 这样我们只要快速找出所有的符合规则的标签, 在进一步分析里面的内容,最后筛选出数据就可以了。 开始写代码吧? 我们先写出抓取页面内人的函数: 这是前面介绍过的爬取框架,以后我们会经常用到。

流氓软件之会声会影[彻底卸载]

随着计算机的逐步发展,我们日常接触到的软件也越来越多,或这或那的原因,有些软件逃避不了卸载的命运。而软件制作商可谓费尽心思,要在我们的计算机里留下一星半点“足迹”,这次博主要提的是流氓软件之一——会声会影。 博主为了临时做一个视频,就在网上下了一个会声会影x8,但是命途多舛,装这么个小玩意儿,花费了不少功夫。第一次下载安装可谓顺风顺水,但是下载完之后,双击Corel VideoStudio Pro X8之后,竟然没有反应。于是百度了一下,看到有人说目录必须是英文,好吧,怪我手贱,创建了一个叫“会声会影”的文件夹。那就改一下目录名呗,但是,只该目录名是没有用的,那不管三七二十一,卸了重装好了(此处开始入坑)。 当博主把安装的整个目录文件删除之后,再点安装,发现安装不了了,具体效果就是点了安装程序,没有任何反应。于是开始一波网上搜索,有说重装系统的,有说删除相关注册表的,博主心里就有句mmp不知当讲不当讲。⑴重装系统?开玩笑吧,为了一款流氓软件,让我舍弃一堆软件重装?果断放弃;⑵删除相关注册表?那请告诉我有哪些相关的注册表呀,而且,我照你们说的删了还是安装不了诶。 【正解】借助Windows Installer Clean Up来删除会声会影的相关配置信息:①这种方法要先下载Windows Installer Clean Up工具(网上找找一大堆);②安装完之后,我们要去路径C:\Program Files\Windows Installer Clean Up下运行msicuu.exe(32位系统去Program Files文件夹内,64位系统去Program Files(x86)文件夹内),如下图 ③先找找规律 在Windows里会声会影x4的配置信息: (All Useers)PureHD[14.0.0.342] (All Useers)Setup[14.0.0.342] (All Useers)VIO[14.0.0.342] (All Useers)VSClasbic[14.0.0.342] (All Useers)VSPro[14.0.0.342] 选中它们,点【Remove】(删除)。 这样就彻底的删除了会声会影x4的配置信息,然后就可以重新安装会声会影x4了。 在Windows里会声会影x5的配置信息: (All Useers)Contents[15.0.0258] (All Useers)Corel Videostudio proTitle Pack[1.00.000](如果你安装了更新才有此项) (All Useers)ICA[15.0.0258] (All Useers)IPM-VS-Pro[15.0] (All Useers)ISCOM[15.0.0.258] (All Useers)Setup[15.0.0.258] (All Useers)Share[15.0.0.258] (All Useers)VSClassic[15.0.0.258] (All Useers)VSHelp[15.0.0.258] (All Useers)VSPro[15.0.0.258] 选中它们,点【Remove】(删除)。 这样就彻底的删除了会声会影x5的配置信息,然后就可以重新安装会声会影x5了。 由上可见,对于会声会影xn,一般存在的形式都是[1n.x.x.x],例如我的会声会影x8,它的相关配置都是[18.0.1.32]的,所以只要找出这些文件Remove掉,就可以正常安装了。

iOS 11 安全区域适配总结

导语:本文主要是对iOS 11下企鹅 FM APP中tableView内容下移20pt或下移64pt的问题适配的一个总结。内容包括五个部分:问题的原因分析、adjustContentInset属性的计算方式、什么情况下的tableView会发生内容下移、有哪些解决方法、解决这个问题时遇到的另外一个小问题。 一、iOS 11下APP中tableView内容下移20pt或下移64pt的原因分析 问题如下图所示: 1. 原因分析 原因是iOS 11中Controller的automaticallyAdjustsScrollViewInsets属性被废弃了,所以当tableView超出安全区域时系统自动调整了SafeAreaInsets值,进而影响adjustedContentInset值,在iOS 11中决定tableView的内容与边缘距离的是adjustedContentInset属性,而不是contentInset。adjustedContentInset的计算方式见本文第二部分内容。因为系统对adjustedContentInset值进行了调整,所以导致tableView的内容到边缘的距离发生了变化,导致tableView下移了20pt(statusbar高度)或64pt(navigationbar高度)。 如果你的APP中使用的是自定义的navigationbar,隐藏掉系统的navigationbar,并且tableView的frame为(0,0,SCREENWIDTH, SCREENHEIGHT)开始,那么系统会自动调整SafeAreaInsets值为(20,0,0,0),如果使用了系统的navigationbar,那么SafeAreaInsets值为(64,0,0,0),如果也使用了系统的tabbar,那么SafeAreaInsets值为(64,0,49,0)。关于什么情况下会发生内容下移的问题,本文第三部分有介绍。 2. 安全区域的概念 系统自动调整tableView内容偏移量,是根据安全区域来调整的。安全区域是iOS 11新提出的,如下图所示: 安全区域帮助我们将view放置在整个屏幕的可视的部分。即使把navigationbar设置为透明的,系统也认为安全区域是从navigationbar的bottom开始,保证不被系统的状态栏、或导航栏覆盖。可以使用additionalSafeAreaInsets去扩展安全区域使它包括自定义的content在界面上。每个view都可以改变安全区域嵌入的大小,Controller也可以。 safeAreaInsets属性反映了一个view距离该view的安全区域的边距。对于一个Controller的根视图而言,SafeAreaInsets值包括了被statusbar和其他可视的bars覆盖的区域和其他通过additionalSafeAreaInsets自定义的insets值。view层次中的其它view,SafeAreaInsets值反映了该view被覆盖的部分。如果一个view全部在它父视图的安全区域内,则SafeAreaInsets值为(0,0,0,0)。 二、 adjustContentInset属性的计算方式 首先看scrollView在iOS11新增的两个属性:adjustContentInset 和 contentInsetAdjustmentBehavior。 /* Configure the behavior of adjustedContentInset. Default is UIScrollViewContentInsetAdjustmentAutomatic. */@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior adjustContentInset表示contentView.frame.origin偏移了scrollview.frame.origin多少;是系统计算得来的,计算方式由contentInsetAdjustmentBehavior决定。有以下几种计算方式: 1.UIScrollViewContentInsetAdjustmentAutomatic:如果scrollview在一个automaticallyAdjustsScrollViewContentInset = YES的controller上,并且这个Controller包含在一个navigation controller中,这种情况下会设置在top & bottom上 adjustedContentInset = safeAreaInset + contentInset不管是否滚动。其他情况下与UIScrollViewContentInsetAdjustmentScrollableAxes相同 2.UIScrollViewContentInsetAdjustmentScrollableAxes: 在可滚动方向上adjustedContentInset = safeAreaInset + contentInset,在不可滚动方向上adjustedContentInset = contentInset;依赖于scrollEnabled和alwaysBounceHorizontal / vertical = YES,scrollEnabled默认为yes,所以大多数情况下,计算方式还是adjustedContentInset = safeAreaInset + contentInset 3.UIScrollViewContentInsetAdjustmentNever: adjustedContentInset = contentInset

js写登录界面 回车直接登录

在js中写入以下代码,并在点击事件上绑定 function keyLogin(){ if (event.keyCode==13) {//回车键的键值为13 var toClick=document.getElementById("keyBtn") toClick.click(); //调用登录按钮的登录事件 } }` function IbtnEnter_onclick() { keyLogin(); } 在jsp文件中写页面 <div class="login" onkeydown="keyLogin()"> <div class="body"> <input class="userInputUserName" placeholder="请输入用户名""/> <input class="userInputPassword" placeholder="请输入密码" "/> <button id="keyBtn"class="btn"onclick="IbtnEnter_onclick()"> 登录</button> </div> </div>

读取excel中数据时,数字格式发生改变

在读excle 的数据时,可能出现的问题: 例如:在excel某一单元格中存储的数据为30253996,使用 XSSFROW 对象进行取值的时候,可能会把数字转化为科学计数法的形式,即 3.0253996E07,特别当我们希望得到excle中原有的数据格式时出现这种问题就不太好了。 解决: 方法一: String values = xssfRow.getCell(0).toString().replace(".", ""); if(values.contains("E")){ values = values.substring(0, values.lastIndexOf("E")); } 方法二: BigDecimal big = new BigDecimal(xssfRow.getCell(0).toString()); String values = big.toPlainString();

Linux下Tomcat的基础配置

使用Java开发的WEB项目,最常用的Tomcat进行部署。在部署应用的时候,需要注意以下几项配置,对于性能会有一定的提升。以下以Linux环境中的配置为例说明: 1、修订"catalina.sh"中的环境配置。在最上方加入: JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms256m -Xmx1024m -XX:PermSize=32m -XX:MaxPermSize=128m -XX:+DisableExplicitGC" 内存优化,启动时告诉JVM我要一块大内存(调优内存是最直接的方式) 2、修订"server.xml",进行端口的配置。及线程的开辟等。 <Connector port="8088" protocol="HTTP/1.1" maxThreads="600" minSpareThreads="100" maxSpareThreads="500" acceptCount="700" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" ompression="on" compressionMinSize="500" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"/>其中"URIEncoding="UTF-8"", 主要规避数据传输乱码问题。在“外经贸”项目中,出现过未配置,导致的空数据问题。 3、APR(Apache Portable Runtime) 的安装和启用 主要处理包括文件和网络IO操作,以提升性能。具体信息,请自行百度。安装步骤如下: 1)安装apr yum install apr-devel apr apr-util 2)安装tomcat-native。 从Tomcat/bin目录中,解压tomcat-native.tar.gz文件 tar -zxvf tomcat-native.tar.gz进入对应的文件夹位置 cd tomcat-native-1.1.33-src/jni/native/执行如下配置命令: ./configure --with-apr=/usr/bin/apr-1-config --with-java-home=/usr/java/jdk1.7.0_79 && make && make install JDK的路径,根据实际位置,进行配置。 3)修改环境变量 vi /etc/profile在文件最后增加: export LD_LIBRARY_PATH=/usr/local/apr/lib执行命令,使配置生效 source /etc/profile到此,执行startup.sh 。如果在“catalina.out” 文件中,出现如下信息,表明配置成功 INFO: Loaded APR based Apache Tomcat Native library 1.

共词聚类分析

一、概念 共现聚类分析法,通过文献计量和聚类统计的方法,计算主题词之间的联系密切程度(在同一篇文献共同出现的频率),将距离较近的主题词聚集在一起,形成一个个概念相互独立的类团,使得类团内属性相似性最大,类团间属性相似性最小。 二、关键流程 1、聚类时距离的确定 在进行聚类分析时,类组合的确定有两种概念方式,一是类与类之间的距离,二是点与点之间的距离。 (1)类间距离:例如组间距离法 (2)点间距离:例如欧氏距离法 2、聚类方法的确定 聚类分析是物以类聚的一种统计分析方法,实质是寻找一种能客观反映元素之间亲疏关系的统计量,然后根据这种统计量把元素分成若干类,目前常用的聚类方法有: (1)K类中心聚类(快速聚类) (2)等级聚类(系统聚类、层次聚类): a.分解法:开始先把所有合体视为一个大类,然后根据距离和相似性逐层分解,直到参与聚类的每个个体自成一类为止。 b.凝聚法:先把n个元素看成n类,然后将性质最为接近的2类合并成一个新类,得到n-1类,再从中找出最接近的2类加以合并变成n-2类,直到所有的元素全聚在一类之中。 三、主要分析指标 1、粘合力 用以衡量类团内各主题词对聚类成团的贡献程度 , 表达每个主题在类团的聚集过程中所起作用的程度,在类团中 , 粘合力最大的词称为中心词。 2、密度:用来量度使字词聚合成一类的这种联系的强度 , 也就是该类的内部强度。 3、向心度:向心度用来量度一个类团与学科其它类团的联系程度 。 四、类团的可视化分析方法 为进一步将聚类的结果以更直观的可视化方法显示出来 , 可视化方法可分为类团关系图与战略坐标图两种 。 1、类团关系图 类团关系图主要用于明确类团间的关系 , 类团间的关系强弱以连接线的粗细来表示 , 两个类团的关系越强 , 连接它们间的线条越粗 。 两个类团间的关系强度 , 由这个两类团中的所有成员间所组成的词对 , 这些词对在同一篇文献中出现的频率的总和即为两个类团间系联的强度值 。 2、战略坐标图 主要用来描述某一研究领域内部联系情况和领域间相互影响情况,在战略坐标中 , X 轴为向心度 , 表示领域间相互影响的强度 , Y 轴为密度 , 表示某一领域内部联系强度 。 以向心度和密度为参数绘制成的二维坐标即为战略坐标 , 它可以概括地表现一个领域内亚领域的结构 。

交换机的堆叠与级联

当单一交换机所能够提供的端口数量不足以满足网络计算机的需求时,必须要由2个以上的交换机提供相应数量的端口,这也就要涉及到交换机之间连接的问题。从根本上来讲,交换机之间的连接不外乎两种方式,一是堆叠(stack),一是级联(uplink)。 一、堆叠 交换机的堆叠就是交换机用堆叠线通过堆叠模块把两台或多台交换机连接起来,每台交换机的母板总线连接在一起,将它们作为一个交换机使用和治理,实现高速连接。不同交换机任意二端口之间的延时是相等的,就是一台交换机的延时。堆叠是同级关系,每台交换机的性能是一样的。 交换机上的堆叠模块有两个口:一个进口(UP向上线),一个出口(DOWN向下线),用厂商提供的专用连接电缆(堆叠线),从一台交换机的UP堆叠端口直接连接到另一台交换机的DOWN堆叠端口。 堆叠是把所有堆叠的交换机的背板带宽共享。例如一台交换机的背板带宽为2G,那么3台交换机堆叠的话,每台交换机在交换时就有6G的背板带宽。 二、级联 所谓级联,是指使用普通的线缆(双绞线、光纤)将交换机连接在一起,实现相互之间的通讯。级联式结构化网络有利于综合布线,易理解,安装,不用考虑交换机的性能和端口属性,可以方便的实现大量端口的接入。交换机不能无限制级联,超过一定数量的交换机进行级联,最终会引起广播风暴,导致网络性能严重下降。 级联可分为以下三种: 用普通端口级联用Uplink端口级联光纤端口的级联 三、堆叠与级联的区别 虽然级联和堆叠都可以实现端口数量的扩充,但是级联后每台集线器或交换机在逻辑上仍是多个被网管的设备,而堆叠后的数台集线器或交换机在逻辑上是一个被网管的设备。 对设备要求不同 级联可通过一根双绞线在任何网络设备厂家的交换机之间,或者交换机与集线器之间完成。而堆叠只有在自己厂家的设备之间,并且该交换机必须具有堆叠功能才可实现。 对连接介质要求不同 级联时只需一根跳线,而堆叠则需要专用的堆叠模块和堆叠线缆,当然堆叠模块是需要另外订购的。 最大连接数不同 交换机间的级联,在理论上没有级联数的限制。但是,叠堆内可容纳的交换机数量,各厂商都会明确地进行限制。 管理方式不同 堆叠后的数台交换机在逻辑上是一个被网管的设备,可以对所有交换机进行统一的配置与管理。而相互级联的交换机在逻辑上是各自独立的,必须依次对其进行配置和管理每台交换机。 设备间连接带宽不同 多台交换机级联时会产生级联瓶颈,并将导致较大的转发延迟。例如,4台百兆位交换机通过跳线级联时,彼此之间的连接带宽也是100Mbps。当连接至不同交换机上的计算机之间通信时,也只能通过这条百兆位连接,从而成为传输的瓶颈。同是,随着转发次数的增加,网络延迟也将变得很大。而4台交换机通过堆叠连接在一起时,堆叠线缆将能提供高于1Gbps的背板带宽,从而可以实现所有交换机之间的高速连接。尽管级联时交换机之间可以借助链路汇聚技术来增加带宽,但是,这是以牺牲可用端口为代价的。 网络覆盖范围不同 交换机可以通过级联成倍地扩展网络覆盖范围。例如,以双绞线网络为例,一台交换机所覆盖的网络直径为100m,2台交换机级联所覆盖的网络直径就是300m,而3台交换机级联时的直径就可达400m。而堆叠线缆通常只有0.5~1m,仅仅能够满足交换机之间互联的需要,不会对网络覆盖范围产生影响。

51单片机八路抢答器proteus仿真

 51单片机八路抢答器 由于51单片机小板,按键比较少,还有一些功能上的缺陷,所以说无法完成八路抢答器,所以我们用proteus仿真,代码与实验结果如下: /******************************** Function: 八路抢答器 Date: Sep 20,2017 By:Third Group Bolanche L **************************/ #include<reg52.h> #define uint unsigned int #define uchar unsigned char uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; sbit Start=P3^7; sbit Indecator=P3^6; //指示灯 sbit Interrupt=P3^3; //中断1 sbit KEY1=P2^0; //第一位LED sbit KEY2=P2^1; sbit KEY3=P2^2; sbit KEY4=P2^3; sbit KEY5=P2^4; sbit KEY6=P2^5; sbit KEY7=P2^6; sbit KEY8=P2^7; uchar n; //声明全局无符号字符变量n //延时毫秒 void delayms(uint c) { uchar a,b; for(;c>0;c--) for(a=142;a>0;a--) for(b=2;b>0;b--); } //数码管显示 void SMG_dis(uchar m)

从0开始的Vue全栈项目(仿网易云音乐App)

转行前端一年多,之前一直忙于写业务代码,刚好近期不忙,就想写一个完全属于自己的项目。原本打算用react来做的,但是估计边翻api边写可能会花特别长的时间,所以打算这个项目完成后写个react的项目。 本项目因为时间关系暂时只做了部分功能,但是有空会继续更新的。 运行项目 将代码克隆到本地:git clone https://github.com/chenging/vue.git; 安装依赖:进入项目根目录,命令行工具输入npm install; 运行前端服务器:命令行工具输入npm start,打开http://localhost:8888即可预览项目; 安装数据库:可以直接到mongodb官网下载,安装完在C盘目录下新建文件夹data,进入data文件夹再新建一个db文件夹,此为mongodb默认存放数据目录; 开启mongodb数据库:进入mongodb安装目录,找到mongod.exe文件,双击打开; 运行node.js后台服务器:进入项目根目录,命令行工具输入node server,第一次运行会存入初始数据。 一、目录结构 二、主要技术栈 前端:vue+vue-router+axios+es6+webpack+canvas;后端:node.js+koa;数据库:mongodb+mongoose 三、目前已完成的功能 音乐播放:包括播放进度条、播放动画、歌曲切换视频播放:播放视频时暂停音乐播放,结束后会继续音乐播放;登录注册:登录、注册、修改资料歌曲搜索:通过歌曲名称、演唱者名字、歌词模糊查询。图片轮播:自动切换图片及手动切换图片 四、参考资料 webpack官方文档:https://webpack.js.org/guides... 廖老师nodejs教程https://www.liaoxuefeng.com/w... mongoose官方文档:http://mongoosejs.com/docs/ap... 五、在线演示及项目地址 在线演示地址:https://chenging.github.io/vu... github地址:https://github.com/chenging/vue 项目截图和代码部分就不放了,里面有详细的注释(主要是怕自己给忘了。。。) 第一次写文章,也是第一个个人项目,包括后台和数据库都是第一次。。。。 更多的是对自己的一个总结吧,也欢迎大家对代码或者项目部分提出意见和建议。 项目未完成的部分后续会逐渐完成。

多态的执行究竟是父类的还是子类的?

首先Java实现多态有三个必要条件:继承、重写、向上转型。 继承:在多态中必须存在有继承关系的子类和父类。 重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。 向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。 然后就是多态中的执行问题了,我们可以用一句话来理解,反正我觉得是挺好用的."成员变量,静态方法看左边;非静态方法:编译看左边,运行看右边。" 简单的理解意思就是.比如Animal a = new Cat(); 定义了一个Animal类型的引用,指向新建的Cat类型的对象. 这个时候他的成员变量和静态方法与父类是一致的,他的非静态方法,在编译时是与父类一致的,运行时却与子类一致(发生了重写)。

详解数组--sort()方法原理上

sort()方法在适当的位置对数组进行排序,并且返回数组。 对于sort()方法,W3school给的定义是 arrayObject.sort(sortby) 可知参数是可选的,也就是有两种情况,一是不加参数,另外一种是加函数参数,参数必须是函数。函数就是比较函数。 先看第一种不加参数的情况: var arr=[1,3,10,4,2]; arr.sort(); alert(arr); //1,10,2,3,4 默认排序顺序是升序,在上面的例子当中,我们感觉排序的结果是:1,2,3,4,10。怎么出来10反而在前面呢?那是因为sort()排序是按照字符串的Unicode码,10的比后面的小,则他在前面,但是这个结果不是我们想要的,那怎么办?此时我们就要用到第二种情况:加函数参数。 第二种加函数参数的情况: var arr=[1,3,10,4,2]; function compare(value1,value2) { if(value1<value2){return -1;} else if(value1>value2){return 1;} else {return 0} } arr.sort(compare); alert(arr) //1,2,3,4,10 按照我的理解是,在对于一个数组使用sort()方法时,会逐项的将数组中的元素传入到compare函数中作为参数,也就是说在上面 var arr=[1,3,10,4,2]使用sort()方法时,按照顺序先把1,3分别传给value1和value2,再比较1和3的大小,显然1<3,那么根据判断函数返回-1;sort()方法在接受到函数返回的-1时,就做出按照升序的原理不换位置,现在虽然数组位置没有变,但是数组是刷新过一边的,sort()返回了一个新的数组,所以在第二次传入参数的时候,是传入的第二项3和第三项10(第一次换位置的话,那么第二项就是换过后的第二项)按着同样的原理进行比较返回-1;后面的步骤就一样了,在第三次比较的时候要注意,如果前面的返回值为-1,那么新数组的第一项和第二项不用再比较(升序,-1就不比较,因为-1表示大数本来就在后面 ),如上面所示:1<3,3<10,那么1<10;如果为1,比如,2<5,5>1第二个返回值是1,则排完的新数是:2,1,5;所以接下来就是2和1比较,最终的1,2,5……所以上面的结果是1,2,3,4,10 接下来我用一个例子来说明这个过程: var arr=[1,3,10,4,2,5]; function compare(value1,value2) { console.log(value1,value2,arr); if(value1<value2){return -1;} else if(value1>value2){return 1;} else {return 0} } arr.sort(compare); alert(arr); //1,2,3,4,5,10 这段代码在第三行加了console.log(value1,value2,arr);为了更好理解参数传入和比较的过程,下面图是输出结果,可能上面讲的那段话,有的人觉得繁琐,那么接下来我用段代码逐行分析。 (我本来是想在控制台输出数组,结果出现这种重复以及丢失的排序,目前还没有解决,提出来让大家知道,以下排序过程是对的,只是控制台输出有误。) 我们定义的数组是这样的 arr=[1,3,10,4,2,5] 第一行:传入的是value1=1,value2=3,比较大小返回-1,数组的位置不变。 第二行:传入的是value1=3,value2=10,比较大小返回-1,数组的位置不变。 第三行:传入的是value1=10,value2=4,比较大小返回1,两项交换位置,现在的数组是arr=[1,3,4,10,2,5] 第四行:现在不是继续往后面比较,由于返回值为1(这是升序,1的时候往前面比较),则在第三行操作交换位置后,这传入的参数是value1=3,value2=4,比较大小,返回-1,位置不变,数组还是arr=[1,3,4,10,2,5] 第五行:这才继续向后比较,传入value1=10,value2=2,比较大小,返回1,交换位置,数组为arr=[1,3,4,2,10,5] 第六行:前面的返回值又是1,则又比较前面的,value1=4,value2=2,比较大小,返回1,数组变为arr=[1,3,2,4,10,5] 第七行:第六行结果返回值是1,所以这个地方也不能往后面比较,value1=3,value2=2;比较大小,返回1,数组为arr=[1,2,3,4,10,5] 第八行:同理,value1=1,value2=2,比较大小返回-1,数组不变。 第九行:继续往后面比较,value1=10,value2=5,比较大小,返回1,改变位置,数组是arr=[1,2,3,4,5,10] 最后一行:前面返回值是1,则向前比较,value1=4,value2=5,比较大小,返回-1,数组不变,(因为前面4前面的数是排好序的,只要5>4,就会比前面都大,则前面不用比较。) 传参的详细过程就是这样,所以最后得到的数组是:arr=[1,2,3,4,5,10],上面是谷歌测试。 这是火狐的,结果是一样的,传参是一样的,但是控制台输出的数组没有变过 这是IE的,IE给value1,value2传值的顺序和谷歌,火狐是相反的,并且它的控制台不输出arr数组,但是它的结果还是一样的。 我又把上述代码里的数组改了:var arr=['a','C','b','D','d']; 再改成:var arr = ['réservé', 'premier', 'cliché', 'communiqué', 'café', 'adieu'];

python中头文件的声明

可以见到这种写法:# -*- coding: UTF-8 –*- 这是用来说明你的Python源程序文件用使用的编码。缺省情况下你的程序需要使用ascii码来写,但如果在其中写中文的话,python解释器一般会报错,但如果加上你所用的文件编码,python就会自动处理不再报错。 但是我非常讨厌写这么长,因为本来就因为这个编码问题要记N种声明方式了,比如在html中,在css文件中,那么怎么简单怎么来吧, 上述格式还可以写成: #coding=utf-8 或 #coding:utf-8

python中pow的用法

Python pow() 函数 Python 数字 描述 pow() 方法返回 xy(x的y次方) 的值。 语法 以下是 math 模块 pow() 方法的语法: import math math.pow( x, y ) 内置的 pow() 方法 pow(x, y[, z]) 函数是计算x的y次方,如果z在存在,则再对结果进行取模,其结果等效于pow(x,y) %z 注意:pow() 通过内置的方法直接调用,内置方法会把参数作为整型,而 math 模块则会把参数转换为 float。 参数 x -- 数值表达式。 y -- 数值表达式。 z -- 数值表达式。 返回值 返回 x y (x的y次方) 的值。 实例 以下展示了使用 pow() 方法的实例: #!/usr/bin/python # -*- coding: UTF-8 -*- import math # 导入 math 模块 print "math.pow(100, 2) : "

[特斯拉组件]iOS 高性能 PageController

1.组件介绍 Page是企鹅FM研发的分页组件,包括支持分页非交互切换(通过方法调用导航切换)和交互切换(屏幕的手势滑动),多个分页Controller和View的管理。 1.1需求背景 为什么弃用UIPageViewController,首先介绍一下UIPageViewController,这是系统为开发者定制的分页组件,提供了两种分页切换的效果,一是滑动 二是翻页。且提供了前后切换的回调。 a) UIPageViewController在iOS8以下的系统运行是有问题的,可以参考stackFlow上的症状描述https://stackoverflow.com/questions/12939280/uipageviewcontroller-navigates-to-wrong-page-with-scroll-transition-style/12939384#12939384 This is actually a bug in UIPageViewController. It occurs only with the scroll style (.Scroll) and only after calling setViewControllers:direction:animated:completion: with animated:YES. Thus there are two workarounds: Don’t use UIPageViewControllerTransitionStyleScroll. Or, if you call setViewControllers:direction:animated:completion:, use animated:NO. To see the bug clearly, call setViewControllers:direction:animated:completion: and then, in the interface (as user), navigate left (back) to the preceding page manually. You will navigate back to the wrong page: not the preceding page at all, but the page you were on when setViewControllers:direction:animated:completion: was called.

python字符串搜索与匹配

本文和大家分享的主要是python中字符串搜索与匹配相关内容,一起来看看吧,希望对大家学习python 有所帮助。 字符串是python中常见的一种对象,使用的方法也很简单,只需要用引号引起来就可以看做是一个字符串。 字符串的搜索和匹配在编程中很容易见到,这里我就简单的总结一下: 1. 字符串自带方法匹配开头和结尾str.startswith(string)和str.endswith(string)或切片 在start和end后面都有个s,这个很容易拼写错误。这两个函数返回值是布尔值,也就是True或False,用来判断字符串是否是以某某开头或结尾 >>> filenames = 'files.txt' >>> filenames.startswith('file') True >>> filenames.endswith('.txt') True >>> filenames.endswith('.exe') False 这两个方法还可以传入一个元组类型的参数 >>> filenames.endswith(('.txt','.exe','.bat')) True 当然上述方法,用切片也很容易做到 >>> filenames[:4] == 'file' True >>> filenames[-4:] == '.txt' True >>> filenames[-4:] == '.txt' or filenames[-3:] == 'exe' True 2. 使用shell通配符匹配字符串 shell通配符 * 匹配所有 ? 匹配单个字符[seq] 匹配任意在seq中的字符[!seq] 匹配任意不在seq中的字符 需要使用到fnmatch模块,该模块提供三个方法来匹配字符串,fnmatch、fnmatchcase、filter >>> fnmatch('file.txt','*.txt') True >>> fnmatch('file.txt','?ile.txt') True >>> fnmatch('file0.txt','file[0-9]*') True >>> [name for name in names if fnmatch(name,'file*.

从 iOS Basecamp 3 探索混合应用开发的最佳实践

原文:Basecamp 3 for iOS: Hybrid Architecture 作者:Zach Waugh 翻译:陈冬 审校:苏宓 Basecamp 是 37signals 公司旗下的一款非常流行的基于云服务的项目管理软件。以简单易用和颠覆性的创新而出名。 笔者曾写过很多篇关于如何构建混合移动应用的文章。Basecamp3 项目代表了混合移动架构的最新版本,并且它从过去的版本中吸收了很多精华。 Basecamp 2 项目的第一个 App 仅仅适用于 iPhone,它是利用 RubyMotion 作为 UIWebView 的封装器来进行编写的。之后,我们又通过 Xcode+Objective-C、UIWebView 以及更多原生代码的方式去构建一个通用型的 App。对于 Basecamp 3,我们使用 Swift 和 WKWebView 代替 Objective-C 和 UIWebView,新增了 Turbolinks,并且使用了更多的原生代码。这是原生 App 和 Web App 的一次更加深入的融合。 Hybrid 的定义 首先,我们需要清楚理解什么是”hybrid”。这个词在很多不同的场合中被使用,但这对于我们而言几乎没有任何意义。在我们的开发中,我们所指的”混合”是具有大量 web 渲染内容的标准原生应用。我们没有使用通过 HTML/CSS 来模拟原生控件的框架,也没有使用将另一种编程语言编译成原生开发语言的框架,亦或者是通过一份代码库开发一个跨平台的 App 的框架。 对于我们而言,这意味着我们需要使用 Xcode+Swift,并且要遵守开发平台关于导航和展示的所有规范。在 App 中构建的内容大多由 UINavigationController、UIViewController、UITabViewController、UISplitViewController 等组成。在这些容器中,有很多内容是通过 UITableView 或 UICollectionView 组建的,当然了更多的是通过 WKWebView。 深入理解 在 iOS 版本的 Basecamp 3 App 中我们使用的全部是 Swift 3.

Ajax常用参数类型解析

Ajax 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址。可以加参数进行传递例如 "localhost:8080/getUser?username="+$("#user_id").val(); 2.type: 要求为String类型的参数,请求方式(post或get)默认为get。注意其他http请求方法,例如put和delete也可以使用,但仅部分浏览器支持。 3.timeout: 要求为Number类型的参数,设置请求超时时间(毫秒)。 4.async: 要求为Boolean类型的参数,默认设置为true,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为false。注意,同步请求将锁住浏览器,用户其他操作必须等待请求完成才可以执行。 PS:如果设置async:false 如果请求过大过多的数据造成时间较长的话 会出现网页崩溃的情况 不介意使用。 5.cache: 要求为Boolean类型的参数,默认为true(当dataType为script时,默认为false),设置为false将不会从浏览器缓存中加载请求信息。 cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。 6.data: JSON数据类型:data:{ name:$("#name"), age:$("#age"), grade:$("#grade") } Formate数据类型:var fd = new FormData(document.querySelector("form")); fd.append( "CustomField" , "This is some extra data" ); $.ajax({ url: "stash.php" , type: "POST" , data: fd, processData: false , // 不处理数据 contentType: false // 不设置内容类型 }); HTML、XML 7.dataType: 要求为String类型的参数,预期服务器返回的数据类型。如果不指定,JQuery将自动根据http包mime信息返回responseXML或responseText,并作为回调函数参数传递。可用的类型如下: xml:返回XML文档,可用JQuery处理。 html:返回纯文本HTML信息;包含的script标签会在插入DOM时执行。 script:返回纯文本JavaScript代码。不会自动缓存结果。除非设置了cache参数。注意在远程请求时(不在同一个域下),所有post请求都将转为get请求。 json:返回JSON数据。 jsonp:JSONP格式。使用SONP形式调用函数时,例如myurl?callback=?,JQuery将自动替换后一个“?”为正确的函数名,以执行回调函数。 text:返回纯文本字符串。 8.beforeSend: 要求为Function类型的参数,发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义HTTP头。在beforeSend中如果返回false可以取消本次ajax请求。XMLHttpRequest对象是惟一的参数。 function(XMLHttpRequest){ this; //调用本次ajax请求时传递的options参数 } 9.

JAVA程序员的堕落:只知框架不懂底层原理

我曾在多个场合撰文说过,现在培训出来的企业Java开发兵团只知道使用某种框架,但完全不知道这些框架的底层原理。今天早上,在依次对三个职位的应聘者面试中,我又再次见到了这种情形。 我们的顾问公司收到了一个客户的招聘需求,要一个经验丰富并通晓SQL的Java开发人员。我们公司在这个客户那里享有非常好的声誉,于是我们从招聘代理公司要来了一批简历,开始搜寻合适的目标。 首先,关于他们的简历——每份简历都有数页,详细的描述了在各个公司干过的各种工作。每份简历上都有一个技术列表,表面上看这些都是应聘者懂得的技术。下面这个清单是一个真实的简历上记载的各种技术: Core Java, J2EE, JSP, JDBC, Servlets, AJAX, XML, HTML, XSLT, Web Services, CSS, JavaScript, SQL, Oracle 10g, MySQL 5.0., JMS,Eclipse, Adobe Flex Builder 3.x,UML, JDBC, SVN, JUnit, VSS, Jira, HTML, DHTML, CSS, AJAX, JavaScript, XML, MXML, Action Script, Servlet, JSP, JSTL, Hibernate 3.x, Spring 2.x, IBatis, SOAP, UDDI, WSDL, Apache Axis, Web logic Server 8.x, Apache Tomcat 5.0, Struts Framework, MVC, ANT, Maven. 相当的让人印象深刻…——对于那些从来没有面试过Java程序员的人来说。我并不想说这些应聘者在撒谎,只是这些人跟你的谈话坚持不到三分钟就会在80%的这些技术上露馅。他们可能听说过或者是试过这些技术或工具,这对于他们来说已经足够可以把它们列入简历了。那剩余的他们能说清楚的20%是什么?框架。基本上他们都会向你解释如何配置Struts或Spring,甚至如何让Spring和Hibernate通信。顺便说一句,他们全都喜欢Hibernate,因为它能让你省去了写SQL,而他们对SQL查询语言的知识知之甚少。 每当我看到简历上写满了这些Struts,Springs,Hibernates等东西,我就会这样问,“假设,你不允许使用任何框架。你要从数据库中的客户表和订单表中取出数据,把它们放到Web页面上,请详细完整的解释一下这整个过程。”对大部分人来说,让他们写出一些纯SQL将是一种致命请求… 有个人在简历上写了JQuery。我问她,“你为什么要用JQuery”…20秒钟的停顿…“我喜欢它,它很好呀!”这就是所有我能从她那挖掘出的关于JQuery的信息。

maven项目test报错Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin

今天导入一个原来的maven项目,项目上右键运行JUnit Test,可以通过测试,但是运行mvn test时,报错: Results : Failed tests: twm.camera.core.OutPutStringTest.testPrint(): org/junit/Assert Tests run: 2, Failures: 1, Errors: 0, Skipped: 0 [INFO] ———————————————————————— [INFO] BUILD FAILURE [INFO] ———————————————————————— [INFO] Total time: 2.729 s [INFO] Finished at: 2017-09-17T09:54:47+08:00 [INFO] Final Memory: 7M/19M [INFO] ———————————————————————— [ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test (default-test) on project firstexm: There are test failures. [ERROR] [ERROR] Please refer to D:\workspace\mars\core\target\surefire-reports for the individual test results. [ERROR] -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.

C++/C++11中头文件functional的使用

<functional>是C++标准库中的一个头文件,定义了C++标准中多个用于表示函数对象(function object)的类模板,包括算法操作、比较操作、逻辑操作;以及用于绑定函数对象的实参值的绑定器(binder)。这些类模板的实例是具有函数调用运算符(function call operator)的C++类,这些类的实例可以如同函数一样调用。不必写新的函数对象,而仅是组合预定义的函数对象与函数对象适配器(function object adaptor),就可以执行非常复杂的操作。 std::bind:将一个或多个参数绑定到函数对象,更详细的用法可参考 http://blog.csdn.net/fengbingchun/article/details/52613910 ; std::is_bind_expression:用于判断指定表达式是否为std::bind函数返回的结果类型; std::reference_wrapper:类模板,用于包装对一个实例的引用,它是可拷贝和可赋值的; std::ref:构造一个适当的std::reference_wrapper类型的对象来保存对elem(实例对象)的引用; std::cref:构造一个适当的std::reference_wrapper类型的对象来保存对elem(实例对象)的const 引用; std::mem_fn:将成员函数转换为函数对象; std::not1:返回一个对谓词(一元函数)的结果取反的函数对象; std::not2:返回一个对二元谓词(二元函数)的结果取反的函数对象; std::unary_negate:一元谓词对象类,其调用时把另一个一元谓词的返回值取反; std::binary_negate:二元谓词对象类,其调用时把另一个二元谓词的返回值取反; std::function:类模版,是一种通用、多态的函数封装。std::function的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作,这些目标实体包括普通函数、Lambda表达式、函数指针、以及其它函数对象等,更详细的用法可参考 http://blog.csdn.net/fengbingchun/article/details/52562918 ; std::and:二元谓词对象类, x& y; std::or:二元谓词对象类, x |y; std::xor:二元谓词对象类, x ^y; std::plus:二元谓词对象类, x +y; std::minus:二元谓词对象类, x -y; std::multiplies:二元谓词对象类, x *y; std::divides:二元谓词对象类, x /y; std::modulus:二元谓词对象类, x %y; std::negate:一元谓词对象类, -x; std::equal_to: 二元谓词对象类, x ==y; std::not_equal_to:二元谓词对象类, x != y; std::greater: 二元谓词对象类, x >y; std::less: 二元谓词对象类, x <y; std::greater_equal:二元谓词对象类, x >= y; std::less_equal:二元谓词对象类, x <= y;

c++ 静态库与动态库

1.库的文件格式 库分为静态库,动态库,在不同系统下后缀不同。 2.库的调用与生成 2.1库的调用 2.1.1 在链接和执行阶段都涉及库的调用(访问)。.h文件(头文件)是库的接口。.h文件提供给库的使用者,使用者通过.h来调用库中的API。 2.1.2 库中包含的是函数的实现(一堆函数的实现),这些函数在编写的时候同样要包含1中的头文件,然后生成库。 2.1.3 有了接口,函数就知道去包含这些接口的库中寻找实现的代码,找这些库就需要知道库的名字,所在的位置(路径),否则程序只能通过编译,在链接的时候会出现问题。这些信息都是在makefile中给出的。-L 后面跟的是库的路径 -l后边跟的是库的“核心”名字。完整的库名字,比如libtest.so(动态库)、libtest.a(静态库),其核心名字为test、test,即在makefile中链接库的时候需要去掉完整名字的首尾部。 2.2 库的生成 2.2.1 Makefile生成库的指令: (1)静态库(生成libtest.a) add_static: ar -rcs libtest.a add.o add.o: gcc -c -fPIC -ggdb add.cpp # (debug调模式) gcc -c -fPIC -Os add.cpp # (release发布模式) 中间文件是add.o,最后生成的静态库名字是libtest.a (2)动态库(libtest.so) add_share: gcc -shared -o ../bin/libtest.so ../project_makefile/*.o # (*.o 包含了 add.o) add.o: gcc -c -fPIC -ggdb add.cpp # (debug调模式) gcc -c -Os -fPIC add.cpp # (release发布模式) 中间文件是add.o,最后生成的静态库名字是libtest.so 2.2.2 由库生成可执行文件的过程 (1)由静态库生成 test_static: g++ -o teststatic test.

关于MD5验签失败 同一字符串 调用相同的加密方法 出现加密的值不一样的问题

废话不多说直接上代码 public static String getMD5Str(String str) { byte[] msg = str.getBytes(); MessageDigest messageDigest = null; try { messageDigest = MessageDigest.getInstance("MD5"); messageDigest.reset(); messageDigest.update(msg); } catch (NoSuchAlgorithmException e) { } byte[] b = messageDigest.digest(); return new String(Base64.encodeBase64(b)); } 修改之后的代码 public static String getMD5Str(String str) { byte[] msg = null; try{ msg =str.getBytes("UTF-8"); }catch(UnsupportedEncodingException e1){ } MessageDigest messageDigest = null; try { messageDigest = MessageDigest.getInstance("MD5"); messageDigest.reset(); messageDigest.update(msg); } catch (NoSuchAlgorithmException e) {

产品经理成长三五事儿:搭建自己的成长模型

产品经理这个物种作为伴随互联网行业蓬勃发展起来的产物带有一定的偶然性,丛林法则的特性决定了看似美好的一切背后充满很多艰辛。今天我们聊一聊在产品经理成长过程中需要思考什么,学会什么。 前言 借用钱钟书老先生在围城中最有名的那句话来说,产品经理是一座围城,城外的人想进来,城内的人想出去。这些年随着互联网行业的蓬勃发展,越来越多人开始进入这个行业,进入到产品经理的行当里面。可进来才发现现实与理想的差异,才发现成长过程越发困难、迷茫。 我遇到过很多同学问我产品经理应该怎么做,有的是初入职场,有的是半路转行。市面上也有不少此类的文章讲述产品的思路、逻辑。前两天我对外做了一个分享,我这里把PPT整理了下也说下我这些年的经验。 成长的体系模型 在成长过程中有很多的问题和难处,但总体看来还是围绕这一个固有的体系去思考解决方案的。这里我总结了一个成长模型。包括四个部分:定位、学知、认识、明断。 定位:思考方向,定位对其他三个方面产生影响,对未来发展的轨迹起到了决策的作用。没有定位就意味着你的高度不会太高。学知:作为基础,就像数学语文一样,也许未来使用的越来越少,但不会一定是不行的。认识:打造自我的价值观,学会看到更多有价值的信息。明断:在具备基础和认识以后,学会根据现有信息判断决策问题。脱离执行层面,进入更高阶段。 在我看来每个人进入一个职业岗位都有几个阶段,不同阶段需要具备的能力也有所不同,要求的标准也有高有低。 初入职场:入门阶段,对于行业各方面不太熟悉,一切都需要了解或者重头学习。这个阶段要明确定位,学习知识。渐入佳境:业务成熟期,对于所负责的产品线比较了解熟悉,执行任务游刃有余。但同时也遇到了一些瓶颈,希望能够有所突破。此阶段除了上述内容,要开始慢慢学会了解更多思维方法观点上的信息,形成一定的思维意识和体系,并不断完善。决策决断:开始对一些重要的问题或者方向进行决策处理。开始遇到很多人依赖你的决策进行执行。判断因素不局限于一块的范畴。这时就需要有判断的能力和主动导向期望结果的能力。以后:这是更高的要求,掌握更多资源,更多的话语权。已经脱离了产品经理的范畴进入经营管理的概念。这部分不是我们本次讨论的目标,可以作为一个美好的理想。 不是每个人都能完整的走完几个阶段,很多人会停滞不前。下面我们来看下各个维度下到底是什么。 定位:确定方向 这里我们说的定位不仅仅是行业定位,还包括岗位定位、工作职责定位、价值定位以及各阶段目标。 现如今对于人员的定位都是价值结果导向,所以明确你当前的价值点和你希望到达的价值点是你成长发展的核心。学会建立从你当前价值点过渡到期望价值点的高效改进方法就是你的阶段性定位。而这些定位应该始终围绕这一个方向或者结果,这个方向或结果叫做发展定位。从另一个方面来说,定位也可以叫做自知。 很多同学会对定位这个概念产生一些混淆的概念,认为定位只是代表你选择的行业是否热门,选择的岗位是否核心,公司是否BAT。在我看来定位更多是阶段性的,多样性的、持续改进的。 让我们来看下如下的对话场景: 问:我刚转到产品岗位,目前领导让我负责一个不重要的模块,我总觉得没有什么成长,而且没什么核心价值。 答:那你觉得你想要什么? 问:我想要到一个核心的岗位、有人能够带我,待遇能够提高balabala。。。 答:那你感觉应该如何去做才能得到你想要的? 问:我平时会看产品咨询,大牛的文章分享,听沙龙讲座。 答:效果怎么样 问:不太好,感觉没什么进展 从上面可以看到。问问题的同学陷入了一个怪圈:工作不开心->学习补强->进步缓慢->机会少->工作更不开心。而往往这样的同学感觉已经用尽全力却还是没法改变,所以只能寄希望于上文我提到的公司,行业、岗位这些平台的依托来提高自我的价值和水平,可往往会事与愿违。 上面讲到的定位的概念中包含几个元素:个人价值、持续改进、高性价比、期望价值。 个人价值:当前自己可以产生的价值(对公司、对部门、对产品线、对自己等)。这里面价值不等于能力,当今社会所谓怀才不遇的情况是很多的。持续改进:为达到目标需要观察当前情况,不断调整修正方式方法,最终达到目标高性价比:方式方法的改进要追寻高性价比的原则,不能本末倒置,比如工作后看到有些公司需要高学历,为了有个高学历在当前无法负担的情况下去考MBA,有可能反而会影响整体的发展。期望价值:也就是目标,这个期望到达的自我价值水平。这里不限于职位升迁、工资调整,个人短板补充、业务能力提升,沟通提升等也可以作为阶段性的目标来看待。 我们将这些元素细化后总结出一个公式: 个人价值(VR) 个人价值(V):个人水平客观条件/资源(R):部门资源、公司资源、行业情况等 性价比(CT) 人员成本(C):完成目标需要的耗费的成本,包括精力,资源等持续时间(T):完成目标需要持续的时间长短。 持续改进(IO) 改进方法(I):如何去改进观察改进/优化(O):如何去优化 现在我们在看下上述对话中同学的问题。为什么会没有进展达不到他的期望价值目标呢? 首先,期望价值过多,阶段性的目标应该聚焦在一到两个点上,期望很多就容易定位不清晰。其次对于自我的分析定位不够透彻(没有考虑个人能力情况和当前情况这些因素),改进方式性价比低(产品咨询,大牛的文章分享,听沙龙讲座缺乏重点,不够聚焦)。所以导致最终迟迟不能满足期望。 在我看来,这位同学更应该先定一个小目标:比如熟练掌握当前产品线的业务知识,并自学上下游信息。做到熟练后再进行方法论的总结归纳,提高水平。 学知:打牢根基 明确了定位和方向,接下来我们要先打好根基。互联网行业严格意义上来说不是一个独立的行业,他具有强大的包装和改造能力。这也就是为什么现在很多传统行业和互联网结合后可以产生新的火花。在互联网行业从事工作的人们除了需要具备IT的专业知识外,还需要具备所属行业的业务知识。只有这样你才能在面对繁杂的问题时做到游刃有余。 知识学习方法因为很多地方都有讲到,这里不做详细描述,主要提两个方面: 知识维度: 业务知识:所属行业的业务知识逻辑知识:定义边界、判断、推理等逻辑思维的建立相关领域知识:主要是关联职能上下游,比如开发的上下游是产品、测试、运维。产品的上下游是开发、测试、运营等等。 学习渠道: 书籍:基础知识,归纳总结沙龙、分享会:关注思路、价值观百度百科:查缺补漏知识点自我总结:汇总融合 认识:建立认知价值观 当执行做到一定阶段时,人们往往会感觉遇到瓶颈,归根到底还是认识出现了瓶颈。 场景1 A问:业务提的需求方案,可开发总是说有问题不合理。怎么办? 答:你知道业务真正想要的是什么,或者说业务的问题在哪里吗? A问:业务说感觉用着不习惯,想在界面上加一个按钮,一点可以弹出balabala。。。 场景2: A问:领导问我产品线下半年的计划是什么,我不知道该怎么写? 答:你产品线下半年重点什么,把重点规划写下就行 A问:我这就有业务反馈的一些问题,还有看竞品也有的功能没做,罗列下应该就行了。 上面两个场景是很多同学经常遇到的情景,真正出现的问题不是方案、内容的不清楚,而是意识上的模糊导致认知偏差。意识的进一步提升就需要建立认知的价值观,修正以往的一些错误理解和想法,建立更为系统的方法论和思维模式。 按照从小维度到大维度来看。意识的升级主要包括三个阶段: 分辨核心认知升级结构思维认知升级业态认知升级 分辨核心认知 快速分辨问题核心是在日常工作中需要具备的能力。互联网公司日常节奏快,会议多,大一些的公司多头交流的情况也是不少。每件事情、每个邮件能够留下的处理时间都非常有限,为了避免浪费大量时间需要有能够快速抓住问题关键提供核心解决方案的能力。 这里提供一些方法: 思路 思考问题时一定是业务流程->实现方案->细化优化。最忌直接套用别人提供的方案进行。比如业务告诉你说想在界面上加个导出的按钮,可能聊完以后发现只是现有表格无法满足只能导出人工编辑,需要增加字段。那他要解决的核心问题不是他表述的导出功能,而是字段缺失。 关键点需求按照MVP(Minimum Viable Product –最简化可实行产品)的概念去分解解决。 不同角色的同时参与的场景下要考虑优先级,即用户问题大于业务运营问题大于技术问题大于资源问题。这里指的是思考时要按这个思考。而是否可以执行需要看实际资源,客观因素等情况。 沟通技巧 交流时,如果对方迟迟表达不出问题的关键或者逻辑混乱。需要及时打断对方,从某个节点开始逐步梳理。当不熟悉问题业务时,一定需要让相关熟悉的同学讲解下基础流程后再进行分析判断。不要直接答复只能回答是和否的问题,这种问题往往带有主观引导,容易让你思路混乱。 结构思维认知升级 结构化思维相信大家也会经常性听到这个概念,我查了下百度百科上的定义是:

Ubuntu

0.修改root密码和用户名密码 重启按shift选高级进入 下拉到底部在Linux行把ro改为rw 1、重启系统 2、长按Shift键,直到出现菜单。选择recovery mode,即恢复模式 2.5、按”e”键进入编辑页面;将ro single替换为rw single init=/bin/bash;按ctrl+x进入单用户模式,当前用户即为root 3、选择root 4、# 后面敲入 cat /etc/shadow 查看用户名 5、# passwd “用户名” 之后再敲两次密码就可以了。(直接输入passwd修改的是root密码) 6、重启 reboot 注意: 出现 authentication token manipulation error 是因为模式为只读,改为可写: 输入:mount -o rw,remount / sudo uname –m可查看32(i686)还是64位(x86_64) 终端运行 chmod 777 + 文件名 就可以把文件变成可执行状态,再(sudo )./+文件 就可以了

TCP的三次握手

TCP握手协议 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认; SYN:同步序列编号(Synchronize Sequence Numbers)第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态; 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手.完成三次握手,客户端与服务器开始传送数据 A与B建立TCP连接时:首先A向B发SYN(同步请求),然后B回复SYN+ACK(同步请求应答),最后A回复ACK确认,这样TCP的一次连接(三次握手)的过程就建立了! 一、TCP报文格式 TCP/IP协议的详细信息参看《TCP/IP协议详解》三卷本。下面是TCP报文格式图: 图1 TCP报文格式 上图中有几个字段需要重点介绍下: (1)序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。 (2)确认序号:Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。 (3)标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下: (A)URG:紧急指针(urgent pointer)有效。 (B)ACK:确认序号有效。 (C)PSH:接收方应该尽快将这个报文交给应用层。 (D)RST:重置连接。 (E)SYN:发起一个新连接。 (F)FIN:释放一个连接。 需要注意的是: (A)不要将确认序号Ack与标志位中的ACK搞混了。 (B)确认方Ack=发起方Req+1,两端配对。 二、三次握手 所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发,整个流程如下图所示: 图2 TCP三次握手 (1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。 (2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。 (3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。 SYN攻击: 在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将产时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行: #netstat -nap | grep SYN_RECV三、四次挥手 三次握手耳熟能详,四次挥手估计就,所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发,整个流程如下图所示: 图3 TCP四次挥手 由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。 (1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。 (2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。 (3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。 (4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。 上面是一方主动关闭,另一方被动关闭的情况,实际中还会出现同时发起主动关闭的情况,具体流程如下图: 图4 同时挥手 流程和状态在上图中已经很明了了,在此不再赘述,可以参考前面的四次挥手解析步骤。四、附注 关于三次握手与四次挥手通常都会有典型的面试题,在此提出供有需求的XDJM们参考: (1)三次握手是什么或者流程?四次握手呢?答案前面分析就是。 (2)为什么建立连接是三次握手,而关闭连接却是四次挥手呢? 这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。

Linux 中出现的-bash: syntax error near unexpected token `

版权声明:本文为博主原创文章,未经博主允许不得转载。 在Linux 5中导入数据时,出现下面的错误。 -bash: syntax error near unexpected token `(' 检查了脚本没有错误: imp mzl/mzl fromuser=dpcsys touser=mzl tables=(PC_PRJ_PLAN,PC_PRJ_MASSCONTROL,PC_PRJ_FACT) file=/data2/databackup/expbackup/TuesdayBackup.dmp log=/data2/databackup/expbackup/20101125Imp.log 原来在Linux 5中需要在括号加上双引号才可以。 如: imp mzl/mzl fromuser=dpcsys touser=mzl tables="(PC_PRJ_PLAN,PC_PRJ_MASSCONTROL,PC_PRJ_FACT)" file=/data2/databackup/expbackup/TuesdayBackup.dmp log=/data2/databackup/expbackup/20101125Imp.log

不用框架,python实现卷积神经网络

最近学习了卷积神经网络,推荐一些比较好的学习资源 1: https://www.zybuluo.com/hanbingtao/note/485480 2: http://blog.csdn.net/u010540396/article/details/52895074 对于网址,我大部分学习的资源和数学公式都是来源于此,强烈推荐学习。 对于网址2,我下面的代码就是在其基础上改写的,作者是用matlab实现的,这对于不会matlab的同学而言,会比较费时,毕竟, 我们要做的是搞懂卷积神经网络,而不是某一个编程语言。 而且最重要的是,我自己想弄明白CNN的前向网络和误差反向传播算法,自己亲自实现一遍,更有助于理解和记忆,哪怕是看着别人的代码学会的。 A:下面代码实现是LenNet-5的代码,但是只有一个卷积层,一个mean-pooling层,和一个全连接层,出来经过softmax层。 B:使用的数据集是MNIST,你可以到http://yann.lecun.com/exdb/mnist/ C:MNIST的数据解析,可以从我下面的analysisMNIST.py中修改路径,谢谢(http://blog.csdn.net/u014046170/article/details/47445919)然后取得到数据如下情况: D:在C解析完之后,我把label文件的内容转置了,开始的时候是一行,我改成了一列。 注:代码里面的TODO是很多公式推导,我有空会敲出来,然后也作为超链接给弄出来,怕自己下次又给忘了。 我的总共有三个文件: 这是我定义的全局变量的文件 gParam.py #! /usr/bin/env python # -*- coding: utf-8 -*- TOP_PATH = '/media/autumn/Work/data/MNIST/mnist-png/' LAB_PATH = '/media/autumn/Work/data/MNIST/mnist-png/label1.txt' C_SIZE = 5 F_NUM = 12 P_SIZE = 2 FILE_TYPE = '.png' MAX_ITER_NUM = 50 这是我测试的文件myCnnTest.py #! /usr/bin/env python # -*- coding: utf-8 -*- from numpy import * import numpy as np from myCnn import Ccnn import math import gParam # code cLyNum = 20 pLyNum = 20 fLyNum = 100 oLyNum = 10 train_num = 800 myCnn = Ccnn(cLyNum, pLyNum, fLyNum, oLyNum) ylabel = myCnn.

php账号唯一登录思路

第一步,将 session_id存进数据库用户表。 第二步,当用户登陆更新 session_id 的时候,就处理删除 session_save_path下的旧 session_id ,旧的被删了就等于挤下去了。

C#HttpClient返回乱码的解决方案

试试为HttpClient的构造函数传入参数 HttpClient httpClient = new HttpClient(new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip });

java中+=详解 a+=b和a=a+b的区别

short a=10; a+=4; System.out.println(a); 1.第一段代码的输出结果为14.执行流程是首先声明变量,判断赋给变量的初始值是否在short类型范围内,如果在则进行强制类型转换,将10强转为short类型 然后通过+=赋值运算符将a+b的和赋给a变量,因为+=是一个特殊的运算符,会自动进行类型转化,所以第二行的赋值操作不会报错 short a=10; a=a+4; System.out.println(a); 2.第二段代码的赋值操作,因为a是变量,无法确定大小,可能会超出short的取值范围,所以会编译报错, 可能会丢失精度。 当然可以同过手动强转 a=(short)(a+4); 转载于:https://www.cnblogs.com/Chestnuts/p/7478878.html

java中a++和++a的区别详解

java中的++操作无论在前还是在后,都是在变量自身的值加1,接下来将具体描述两者的区别 int a =5; int b =a++; System.out.println(b); 1.通俗易懂的理解是如果有其他运算则先把值赋给b,然后自增. 2.其实内存当中,有一点不一样.实际上是如果在a++时牵扯到其他的运算,比如上面代码块的赋值操作,会把a的值先保留,然后进行+1操作,最后把保留的a的值也就是5赋给b。 int a =5; int b =++a; System.out.println(b); 1.而++a 因为++运算在前,所以先进行+1操作,然后把值临时存放,最后再把临时存放的赋值到b,也就是6 转载于:https://www.cnblogs.com/Chestnuts/p/7478755.html

PS将红底证件照改为白底

本人就一个老实巴交的程序猿,但是朋友觉得程序猿是应该会修电脑、修手机、还会PS处理照片的。这个就十分让人家尴尬了。但是好朋友让你帮忙,想想自己动手能力肯定比对方好,那接吧。于是就开始找教程。幸好大学有选修过PS,不至于开了PS一脸茫然。言归正传如题: 将照片红底的换成白底的。 操作步骤: 1 先上效果,照片来自网络反正不认识,法律问题找度娘 2 下面开始操作,打开图片进入通道面板,选择照片底色的那个通道,复制并调整色阶,确保黑白分明 3 回到图层面板新建图层, 执行 菜单-图像-应用图像 命令,得到一个黑白图层 4 用魔棒选取白色背景,添加图层蒙板 5 前景色白色,用柔性笔刷涂抹头发以及衣服边缘,注意眼镜腿的反光也要涂抹 ==============完成========== 感谢:http://tieba.baidu.com/p/1762808211 http://tieba.baidu.com/p/2614099401

php 过狗一句话木马的编写

我们都知道 这个是php一句话 <?php assert($_POST['mima']); ?> 可是服务器的安全狗会识别到,我们要经过一些处理, 让安全狗不能认出我们的代码是一句话木马。 好多小白只会用一句话,但是不知道原理,我先大概说一下一句话木马的原理 assert是一个php的函数 assert(这里写代码) 这个函数会执行括号里的代码,(eval 的一句话木马类似 区别不细说) $_POST['mima']; 这句的意思是 接收表单的name为 "mima"的数据 怎么接收?通过POST请求,例如我们post mima=1234,那么$_POST['mima']的值就是1234 如果我们语句构造成这个 assert($_POST['mima']); 然后再post mima = system("whoami") 等等神奇的代码呢?会不会执行? 我们看看效果,我用我的过狗一句话试试 我用的是火狐的 hackbar插件。 命令成功执行了,我们再试试其他的 phpinfo成功执行。 原理就讲到这里吧,接下来直播写过狗的一句话。 思路:让assert执行我们post的数据,但是要让狗看不明白我们的代码 我刚学php,只清楚一点点函数,但是过狗足够了。 我们用想到的方法,用几个简单的函数组合拼凑,然后脑洞大开,写出神奇的代码,写的自己看都要费劲,这样安全狗可能就不会认识了 我们可能会用到的函数: base64_encode() 这是base64加密函数 base64_decode() 这个解密 str_replace(a,b,c) 把字符串c里面的a字符串用b代替 为了避免等下写的不过狗,我就用我的过狗来讲吧,太晚了就不再开脑洞了。 之前只是介绍过狗常用的简单函数,不一定用到哦 拿出我的Dreamweaver,写上最初的一句话 这肯定被认出。 为了方便先拆开写,把post的数据先赋值给变量 $aa 如果没有狗的话,效果跟一句话木马一样,可是狗肯定还是看得出,再改改。 狗不允许我们用assert执行我们post 过来的代码,但是我们用assert执行其他的代码。 我们把post过来的数据假装改成了其他的数据,这样就骗过狗狗了。 看**作 我们再加一个post的数据,接收的变量名叫什么都行,我这里叫xxx 然后再赋值给变量$bb 再创建一个变量$cc,它等于 字符串 $aa 连上字符串 $bb, 例如$aa ="我是" ,$bb = "father", 那么$cc=$aa.$bb 之后,$cc 就是 “我是father”这个字符串。