在网上了解到,存在这种问题是因为IE8/9并不支持console的方式。
解决方法有两种:
1.按F12开启IE Dev Tools才能存取console;
2.在调用之前,先进行一下判断:
if(window.console && console.log){ console.log('xx');
}
题目:输入一个整数和一棵二元树。
从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。
打印出和与输入整数相等的所有路径。
例如 输入整数22和如下二元树
10 / \ 5 12 / \ 4 7
则打印出两条路径:10, 12和10, 5, 7。
先序遍历树即可得到结果。
void FindPath ( BSTreeNode* pTreeNode, // a node of binary tree int expectedSum, // the expected sum std::vector<INT>& path, // a path from root to current node int& currentSum // the sum of path ) { if(!pTreeNode) return; currentSum += pTreeNode->m_nValue; path.push_back(pTreeNode->m_nValue); //判断是否满足条件 if(currentSum == expectedSum && !pTreeNode->m_pLeft && !pTreeNode->m_pRight) { std::vector<INT>::iterator iter = path.
问题现象 最近两个月碰到三次,莫名的 PG (PostgreSQL) 无法连接的情况,具体错误信息如下:
psql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"? 前两次,自己瞎鼓捣,后面就好了,然后也没在意。然后今天早上 Mac 死机重启后,这个问题又出现了,然后各种重装 PG, 重启系统依然无解。
解决方案 无奈之下,开始老实地去 Google, 最后找到一篇 SO 的文章,彻底解决了问题。问题的原因是 Mac 突然死机时原来的进程没有正常关闭,重启后又被启动了。当再次启动 PG 时,PID 文件就无法正常工作了,因为记录的是系统死机前的进程信息。
这些信息都在 PG 的日志文件里看到,/usr/local/var/postgres 目录里面,有一个 server.log 文件可以看到所有的日志。
在我的日志里面看到有很多行
FATAL: lock file "postmaster.pid" already exists HINT: Is another postmaster (PID 403) running in data directory "/usr/local/var/postgres"? 这行日志就告诉我们 postmaster.
Struts 2详细工作流程 Struts2工作原理及流程
Struts2框架的基本思想是采用MVC设计模式,即将应用设计成模型(Model)、视图(View)和控制器(Control)三个部分;
那么Struts2框架中是如何实现MVC模式的呢?控制部分由DispatchFilter承担,模型部分是由一系列的拦截器(Interceptors)、Action组件和ActionContext组件组成,视图组件则是由Result组件组成;
那么Struts2框架是怎么工作的呢?
如当我们在浏览器的地址栏中输入:http://localhost:8080/Struts/TestMvc/add.action,浏览器就会把这个请求发送给tomcat,tomcat接收到这个请求后,会检查一下应该交给哪个web程序处理,现在是交给Struts去处理,然后Struts会去参考此程序下的配置文件web.xml,在web.xml中找到过滤器(Filter),如(ActionContextCleanUp、其他过滤器(SiteMesh等)、 FilterDispatcher),注意这里是有顺序的,先ActionContextCleanUp,再其他过滤器(SiteMesh等)、最后到FilterDispatcher;
FilterDispatcher是控制器的核心,就是mvc中c控制层的核心,FilterDispatcher进行初始化并启用核心 doFilter。FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action, 如果 ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给 ActionProxy ,ActionProxy通过struts.xml询问框架的配置文件,找到需要调用的Action类和方法来处理这请求;
Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应页面,最后返回HTTP响应到客户端浏览器;
其实用最简单的七个步骤:
1:客户端在浏览器中输入一个url地址;
2:这个url请求通过http协议发送给tomcat;
3:tomcat根据url找到对应项目里面的web.xml文件;
4:在web.xml里面会发现有struts2的配置;
5:然后会找到struts2对应的struts.xml配置文件;
6:根据url解析struts.xml配置文件就会找到对应的class;
7:调用完class返回一个结果result,根据struts.xml返回到对应的jsp;
Struts2框架由三部分构成:核心控制器、业务控制器和用户实现的业务逻辑组件。在这三部分中,struts2框架提供了核心控制器StrutsPrepareAndExecuteFilter,而用户需要实现业务控制层和业务逻辑层。
一、核心控制器 StrutsPrepareAndExecuteFilter
StrutsPrepareAndExecuteFilter与struts2以前版本中的FilterDispatcher一样。它是struts2框架的核心控制器,该控制器作为一个Filter运行在web应用中,它负责拦截所有的用户请求,当用户请求到达时,该Filter会过滤用户请求,如果用户请求以action结尾,该请求就会被转入struts2框架来处理。
Struts2框架获取*.action请求后,将根据*.action请求的前面部分决定调用那个业务逻辑组件,例如:对于login.action请求,Struts2调用名为login的Action来处理该请求。
Struts2用户处理请求的Action实例,并不是用户实现的业务控制器,而是Action代理--因为用户实现的业务控制器并没有与ServletAPI耦合,显示无法处理用户请求,而struts2框架提供了系列拦截器,该系列拦截器负责将HttpServletRequest请求中的桉树解析出来,传入Action中,并huidiaoAction的execute方法来处理用户请求。
上面的处理过程是典型的AOP(面向切面编程)处理方式,如图所示的处理模型:
从图看出,用户实现的Action仅仅是struts2的Action代理的代理目标,用户实现的业务控制器Action则包含了对用户请求的处理,用户的请求数据包含在HttpServletRequest对象中, 而用户Action类无需访问HttpServletRequest对象,拦截器会将请求数据解析出来并传给业务逻辑组件Action实例
二、业务控制器
简述:左右项目开发中action控制层,用户接受数据,封装数据,调用业务逻辑层
业务控制器组件就是用户Action类的实例,Action类通常包含了一个excute方法,该方法返回一个字符串-----该字符串就是一个逻辑视图名,当业务控制器处理完用户请求后,根据处理结果不同,excute方法返回不同字符串。
每个字符串对应一个视图名
在写完控业务制器后,需要配置Action的如下三个部分定义
●Action所处理的URL
●Action组件所对应的实现类
●Action里包含的逻辑视图和物理资源之间的对应关系
每个Action都要处理一个用户请求,而用户请求总是包含了指定URL,当StrutsPrepareAndExecuteFilter拦截到用户请求后,根据请求的URL和Action处理URL之间的对应关系来处理转发
三、struts2的模型组件
Java EE 应用里的模型组件,通常指系统的业务逻辑组件,而隐藏在系统逻辑组件下面的,可能还包含了DAO,领域对象等组件。
MVC框架里的业务控制器会调用模型组件的方法来处理用户请求,也就是说,业务控制器不会对用户请求进行实际处理,用户请求最终由模型组件负责处理,业务控制器只是中间负责调度器,这也是称Action为控制器的原因
四、Struts2的视图组件
Struts2已经改变了struts1只能使用JSP作为视图技术的现状,允许使用其他模版技术。
当struts2的控制器返回逻辑视图名时,逻辑视图并未与任何的视图技术关联,仅仅是返回一个字符串,该字符串作为逻辑视图名。
当我们在struts.xml文件中配置Action时,要为Action元素指定系列result子元素,每个result子元素定义一个逻辑视图和物理视图之间的映射,如果没有指定type属性,默认使用JSP左右视图资源。也可以指定很多类型 chain 转发到指定action中,redircter,重定向。
五、运行流程
Struts2框架的运行流程非常相似于WebWork框架的流程,struts2其实就是WebWork2.2的升级版,因此,struts2的运行流程与WebWork运行流程完全相同,如图WebWork的运行流程:
当用户向Web应用发送请求时,该请求经过ActionContextCleanUp、SiteMesh等过滤器过滤。由WebWork的核心控制器拦截,如果用户请求需要WebWWork的业务逻辑控制器处理,该控制器则调用Action映射器,该映射器将用户请求转发到对应的业务逻辑控制器。值得注意的是,测试的业务逻辑控制器并不是开发者实现的控制器,而是WebWork创建的控制器代理,创建控制器代理时,WebWork需要得到开着定义的xwork,xml配置文件,控制器代理以用户实现的控制器作为目标,以拦截器链中的拦截器作为处理。
业务逻辑控制器只是WebWork控制器的目标-----这就是为什么开发者自己实现的Action可以与servletAPI分离的原因,当Action处理完HTTP请求后,该结果只是一个普通的字符串,该字符串将对应到指定的视图资源。 指定的视图资源经过拦截器链处理后,生成对客户端的响应输出
Struts2是Struts社区和WebWork社区的共同成果,我们甚至可以说,Struts2是WebWork的升级版,他采用的正是WebWork的核心,所以,Struts2并不是一个不成熟的产品,相反,构建在WebWork基础之上的Struts2是一个运行稳定、性能优异、设计成熟的WEB框架。
本章主要对Struts的源代码进行分析,因为Struts2与WebWork的关系如此密不可分,因此,读者需要下载xwork的源代码,访问http://www.opensymphony.com/xwork/download.action即可自行下载。
下载的Struts2源代码文件是一个名叫struts-2.1.0-src.zip的压缩包,里面的目录和文件非常多,读者可以定位到struts-2.1.0-src"struts-2.0.10"src"core"src"main"java目录下查看Struts2的源文件,如图14所示。
(图14)
主要的包和类 Struts2框架的正常运行,除了占核心地位的xwork的支持以外,Struts2本身也提供了许多类,这些类被分门别类组织到不同的包中。从源代码中发现,基本上每一个Struts2类都访问了WebWork提供的功能,从而也可以看出Struts2与WebWork千丝万缕的联系。但无论如何,Struts2的核心功能比如将请求委托给哪个Action处理都是由xwork完成的,Struts2只是在WebWork的基础上做了适当的简化、加强和封装,并少量保留Struts1.x中的习惯。
以下是对各包的简要说明:
包名
说明
org.apache.struts2. components
该包封装视图组件,Struts2在视图组件上有了很大加强,不仅增加了组件的属性个数,更新增了几个非常有用的组件,如updownselect、doubleselect、datetimepicker、token、tree等。
Java代码
public interface Executor {
/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
* thread, at the discretion of the <tt>Executor</tt> implementation.
*
* @param command the runnable task
* @throws RejectedExecutionException if this task cannot be
* accepted for execution.
* @throws NullPointerException if command is null
RMI(即Remote Method Invoke 远程方法调用)。在Java中,只要一个类extends了java.rmi.Remote接口,即可成为存在于服务器端的远程对象,供客户端访问并提供一定的服务。JavaDoc描述: Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在“远程接口”(扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用 。 注意: extends了Remote接口的类或者其他接口中的方法若是声明抛出了RemoteException异常,则表明该方法可被客户端远程访问调用。 同时,远程对象必须实现java.rmi.server.UniCastRemoteObject类,这样才能保证客户端访问获得远程对象时,该远程对象将会把自身的一个拷贝以Socket的形式传输给客户端,此时客户端所获得的这个拷贝称为“存根”,而服务器端本身已存在的远程对象则称之为“骨架”。其实此时的存根是客户端的一个代理,用于与服务器端的通信,而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。 RMI 框架的基本原理大概如下图,应用了代理模式来封装了本地存根与真实的远程对象进行通信的细节。 下面给出一个简单的 RMI 应用,其中类图如下:其中IService接口用于声明服务器端必须提供的服务(即service()方法),ServiceImpl类是具体的服务实现类,而Server类是最终负责注册服务器远程对象,以便在服务器端存在骨架代理对象来对客户端的请求提供处理和响应。 各个类的源代码如下: IService接口: import java.rmi.Remote; import java.rmi.RemoteException; public interface IService extends Remote { //声明服务器端必须提供的服务 String service(String content) throws RemoteException; } ServiceImpl实现类: import java.rmi.RemoteException; //UnicastRemoteObject用于导出的远程对象和获得与该远程对象通信的存根。 import java.rmi.server.UnicastRemoteObject; public class ServiceImpl extends UnicastRemoteObject implements IService { private String name; public ServiceImpl(String name) throws RemoteException { this.name = name; } @Override public String service(String content) { return "
/** * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告. * * @author user */ public class CrashHandler implements UncaughtExceptionHandler { /** tag */ public static final String TAG = "CrashHandler"; // CrashHandler实例 private static CrashHandler instance = new CrashHandler(); private final int sleepDuration = 3000; // 系统默认的UncaughtException处理类 private Thread.UncaughtExceptionHandler mDefaultHandler; // 程序的Context对象 private Context mContext; // 用来存储设备信息和异常信息 private Map<String, String> infos = new HashMap<String, String>(); // 用于格式化日期,作为日志文件名的一部分 private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); /** 保证只有一个CrashHandler实例 */ private CrashHandler() { } /** * 获取CrashHandler实例 ,单例模式 * * @return CrashHandler实例 */ public static CrashHandler getInstance() { return instance; } /** * 初始化 * * @param context * 上下文 */ public void init(Context context) { mContext = context; // 获取系统默认的UncaughtException处理器 mDefaultHandler = Thread.
在js中将变量进行两次转码 parentName = encodeURI(encodeURI(parentName)); 在java中将变量再次转码: parentName = java.net.URLDecoder.decode(parentName,”UTF-8”);
第一篇:概念篇 Netem 是 Linux 2.6 及以上内核版本提供的一个网络模拟功能模块。该功能模块可以用来在性能良好的局域网中,模拟出复杂的互联网传输性能,诸如低带宽、传输延迟、丢包等等情况。使用 Linux 2.6 (或以上) 版本内核的很多发行版 Linux 都开启了该内核功能,比如Fedora、Ubuntu、Redhat、OpenSuse、CentOS、Debian等等。tc 是 Linux 系统中的一个工具,全名为traffic control(流量控制)。tc 可以用来控制 netem 的工作模式,也就是说,如果想使用 netem ,需要至少两个条件,一个是内核中的 netem 功能被包含,另一个是要有 tc 。
第二篇:原理
TC用于Linux内核的流量控制,主要是通过在输出端口处建立一个队列来实现流量控制。接收包从输入接口(Input Interface)进来后,经过流量限制(Ingress Policing)丢弃不符合规定的数据包,由输入多路分配器(Input De-Multiplexing)进行判断选择:如果接收包的目的是本主机,那么将该包送给上层处理;否则需要进行转发,将接收包交到转发块(Forwarding Block)处理。转发块同时也接收本主机上层(TCP、UDP等)产生的包。转发块通过查看路由表,决定所处理包的下一跳。然后,对包进行排列以便将它们传送到输出接口(Output Interface)。一般我们只能限制网卡发送的数据包,不能限制网卡接收的数据包,所以我们可以通过改变发送次序来控制传输速率。Linux流量控制主要是在输出接口排列时进行处理和实现的。
第三篇:应用篇
工具可完成如下功能:(故障模拟) 模拟时延,丢包,重复包,乱序。
1、模拟延迟传输 # tc qdisc add dev eth0 root netem delay 100ms 该命令将 eth0 网卡的传输设置为延迟100毫秒发送。 更真实的情况下,延迟值不会这么精确,会有一定的波动,我们可以用下面的情况来模拟出带有波动性的延迟值: # tc qdisc add dev eth0 root netem delay 100ms 10ms 该命令将 eth0 网卡的传输设置为延迟 100ms ± 10ms (90 ~ 110 ms 之间的任意值)发送。 还可以更进一步加强这种波动的随机性: # tc qdisc add dev eth0 root netem delay 100ms 10ms 30% 该命令将 eth0 网卡的传输设置为 100ms ,同时,大约有 30% 的包会延迟 ± 10ms 发送。 2、模拟网络丢包 # tc qdisc add dev eth0 root netem loss 1% 该命令将 eth0 网卡的传输设置为随机丢掉 1% 的数据包。 也可以设置丢包的成功率: # tc qdisc add dev eth0 root netem loss 1% 30% 该命令将 eth0 网卡的传输设置为随机丢掉 1% 的数据包,成功率为 30% 。 3、模拟包重复 # tc qdisc add dev eth0 root netem duplicate 1% 该命令将 eth0 网卡的传输设置为随机产生 1% 的重复数据包 。 4、模拟包损坏 # tc qdisc add dev eth0 root netem corrupt 0.
经常遇到初学者,对单片机串行通讯出了问题不知道如何办的情况。其实最有效的调试方法是用示波器观察收发数据的波形。通过观察波形可以确定以下情况:
是否有数据接收或发送;
数据是否正确;
波特率是否正确;
一、串行数据的格式
异步串行数据的一般格式是:起始位+数据位+停止位,其中起始位1 位,数据位可以是5、6、7、8位,停止位可以是1、1.5、2位。
起始位是一个值为0的位,所以对于正逻辑的TTL电平,起始位是一位时间的低电平;停止位是值为1的位,所以对于正逻辑的TTL电平,停止位是高电平。线路路空闲或者数据传输结束,对于正逻辑的TTL电平,线路总是1。对于负逻辑(如RS-232电平)则相反。
例如,对于16进制数据55aaH,当采用8位数据位、1位停止位传输时,它在信号线上的波形如图1(TTL电平)和图2(RS-232电平)所示。 (先传第一个字节55,再传第二个字节aa,每个字节都是从低位向高位逐位传输)
图1 TTL电平的串行数据帧格式(55aah)
图2 RS-232电平的串行数据帧格式(55aah)
二、根据波形图计算波特率
如图3是图1在示波器中的显示示意,其中灰色线是示波器的时间分度线,此时假设是200us/格。
图3 波特率计算示意图
可以看了,第一个字节的10位(1位起始位,8位数据位和1位停止位)共占约1.05ms,这样可计算出其波特率约为:
10bit / 1.05ms X 1000 ≈ 9600 bit/s
如果上图中的时间轴是100us/格,同样可以计算出波特率应是19200bit/s。
当通讯不正常,又能观察到波形时,就可根据上述方法,从波形图计算一下波特率是否正确。
三、根据波形图判断RS-485收发数据的正确与否
RS-485是一种半双工的串行通讯方式(RS-422为全双工),485电平芯片所以要正确接收和发送数据,必需保证控制信号和数据的同步,否则要么发送数据丢失,要么接收数据可能丢失。
RS-485发送数据时的正确时序如图4所示。
图4 RS-485的正确发送数据时序
在图4中,发送控制信号的宽度基本与数据信号的宽度一致,所以能保证发送数据的正确和发送后及时转为接收。
图5 和图6 分别是控制信号太短和控制信号太长
图5 RS-485控制信号太短时的时序
图6 RS-485控制信号太短时的时序
在图5中,由于控制信号关闭过早,则第二个字节的后两位将发送错误;在图6中,由于控制信号关闭过迟,使485芯片在发送数据后,不能及时转到接收状态,此时总线若有数据过来,则本单元将不能正确接收。
总结:只要掌握上述波形分析方法,任何异步串行数据的接收和发送问题,基本都可以得到解决。
相关滤波跟踪(MOSSE) 在信号处理中,有这么一个概念——相关性(correlation),用来描述两个因素之间的联系。而相关性又分为cross-correlation(互相关,两个信号之间的联系)和auto-correlation(自相关,本身在不同频域的相关性)。
2010年CVPR,David S.Bolme在文章《visual object tracking using adaptive correlation filters》中首次将相关滤波用在了跟踪领域,在其文章的基础之上,很多改进的算法相继出现,跟踪的效果也越来越好。 在介绍作者的算法之前,先介绍一下相关滤波的原理。 假设有两个信号f和g,则两个信号的相关性(correlation)为: (f⊗g)(τ)=∫−∞∞f∗(t)g(t+τ)dt (f⊗g)(n)=∑−∞∞f∗[m]g(m+n) 其中 f∗ 表示 f 的复共轭。correlation的直观解释就是衡量两个函数在某个时刻相似程度。 而将correlation filter应用与跟踪最简单的想法就是:两个信号越相似,其相关值越高。在跟踪,就是找到与跟踪目标响应最大的项。 作者提出的滤波器叫做Minimum Output Sum of Squared Error filter(MOSSE)(误差最小平方和滤波器)。按照前面的思路,我们需要找到一个滤波器,使其在目标上的响应最大,则如下公式: g=f⊗h其中g表示响应输出,f表示输入图像,h表示滤波模板。 显然,我们要是想获得比较获得响应输出,只需确定滤波器模板h即可。上式的计算是进行卷积计算,这在计算机中的计算消耗时很大的,因此作者对上式进行快速傅里叶变换(FFT),这样卷积操作经过FFT后就变成了点乘操作,极大的减少了计算量。上式变成如下形式: F(g)=F(f⊗g)=F(f)⋅F(h)∗ 为了方便描述,将上式写成如下形式: G=F⋅H∗ 有了上面的式子,那么后面跟踪的任务就是找到 H∗ 了: H∗=GF 但是在实际跟踪的过程中我们要考虑到目标的外观变换等因素的影响,所以需要同时考虑目标的m个图像作为参考,从而提高滤波器模板的鲁棒性,所以作者就提出了MOSSE这个模型,其模型公式入下: minH∗=∑i=1m|H∗Fi−Gi|2 因为上式的操作都是元素级别的,因此要想找到,只要使其中的每个元素(w和v是H中每个元素的索引)的MOSSE都最小即可。因此上式可转换为如下形式: minH∗wv∑i=1m|H∗wvFwvi−Gwvi|2 要想得到最小的 H8wv ,只需要对上式求偏导,并使偏导为0即可。即: 0=∂∂H∗wv∑i|FiwvH∗wv−Giwv|2 复数域求导和实数域求导时不一样的,其求导过程如下: 0=∂∂H∗wv∑i(FiwvH∗wv−Giwv)(FiwvH∗wv−Giwv)∗ 0=∂∂H∗wv∑[(FiwvH∗wv)(FiwvH∗wv)∗−(FiwvH∗wv)G∗iwv−Giwv(FiwvH∗wv)∗+GiwvG∗iwv] 0=∂∂H∗wv∑iFiwvF∗iwvHwvH∗wv−FiwvG∗iwvH∗wv−F∗iwvGiwvHwv+GiwvG∗iwv 0=∑i[FiwvF∗iwvHwv−FiwvG∗iwv] Hwv=∑iFiwvG∗iwv∑iFiwvF∗iwv 上面得到是H中每个元素的值,最后得到H为: H=∑iFi⋅G∗i∑iFi⋅F∗i 上式就是滤波器的模型公式。 但是在跟踪中该怎么得到滤波器H呢? Fi 和 Gi 又该怎么获取? 在作者的文章中,其对跟踪框(groundtruth)进行随机仿射变换,获取一系列的训练样本 fi ,而 gi 则是由高斯函数产生,并且其峰值位置是在 fi 的中心位置。获得了一系列的训练样本和结果之后,就可以计算滤波器h的值。注意:这里的f,g,h的size大小都相同。 作者为了让滤波器对与形变、光照等外界影响具有更好的鲁棒性,采取了如下的模板更新策略: Ht=AtBt At=ηFt⋅G∗t+(1−η)At−1 Bt=ηFt⋅F∗t+(1−η)Bt−1 作者将滤波器的模型公式分为分子和分母两个部分,每个部分都分别的进行更新,更的参数为 η 。其中 At 和 At−1 分别表示的是当前帧和上一帧的分子。
似乎有很久都没有写博客了,有工作的一些原因,也有个人的一些原因,今天刚好下雨,也没有地方可去,于是就窝在家里倒腾了下,本篇文章主要是简单介绍一下如何在Mac OS系统下搭建java的开发环境,做java开发工作,当然首先是得有一个java环境,所以接下来主要是简单介绍一下Mac环境下java环境变量的一些配置工作。
鄙人的电脑配置:
打开终端,查看10.9.5版本的系统用的是什么shell命令:
大家可以看到,控制台输出地bash,说明系统用的是Bourbe shell,是默认的Unix Shell命令。
然后在命令行中输入java -version 查看当前系统的java版本,有的系统默认是没有安装jdk的,当你在控制台输入java -version之后,如果系统没有安装jdk环境,会自动提示你安装之后才能使用这个命令,这个时候可以到Oracle官网去下载一个mac版本的jdk然后进行安装即可。
http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html
鄙人下载的是jdk1.7版本的,目前官方最新版本的jdk1.8。
如果系统先前已经成功安装过jdk,那这个时候通过输入java -version之后,命令行会输出相应地jdk版本安装的信息。
接下来,开始配置java的环境变量
在终端中输入命令:
sudo vim /etc/profile 我们可以使用vi 来编辑profile文件
然后输入i,进行insert插入模式
在文件的最尾部,添加java的路径
JAVA_HOME=“Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/” CLASS_PATH=“$JAVA_HOME/lib” PATH=“.;$PATH:$JAVA_HOME/bin” 添加完之后,按住esc键退出插入模式,之后输入wq!或者wq或者x保存退出文件。
到这里,整个配置工作就已经完成了。这里配置的是全局的java的path和classpath环境变量。虽然内容很简单,但是还是想记录一下。
一、Kafka简介 本文综合了我之前写的kafka相关文章,可作为一个全面了解学习kafka的培训学习资料。 转载请注明出处 : 本文链接
1.1 背景历史 当今社会各种应用系统诸如商业、社交、搜索、浏览等像信息工厂一样不断的生产出各种信息,在大数据时代,我们面临如下几个挑战:
如何收集这些巨大的信息如何分析它如何及时做到如上两点 以上几个挑战形成了一个业务需求模型,即生产者生产(produce)各种信息,消费者消费(consume)(处理分析)这些信息,而在生产者与消费者之间,需要一个沟通两者的桥梁-消息系统。从一个微观层面来说,这种需求也可理解为不同的系统之间如何传递消息。
1.2 Kafka诞生 Kafka由 linked-in 开源 kafka-即是解决上述这类问题的一个框架,它实现了生产者和消费者之间的无缝连接。 kafka-高产出的分布式消息系统(A high-throughput distributed messaging system)
1.3 Kafka现在 Apache kafka 是一个分布式的基于push-subscribe的消息系统,它具备快速、可扩展、可持久化的特点。它现在是Apache旗下的一个开源系统,作为hadoop生态系统的一部分,被各种商业公司广泛应用。它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于hadoop的批处理系统、低延迟的实时系统、storm/spark流式处理引擎。
二、Kafka技术概览 2.1 Kafka的特性 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒可扩展性:kafka集群支持热扩展持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)高并发:支持数千个客户端同时读写 2.2 Kafka一些重要设计思想 下面介绍先大体介绍一下Kafka的主要设计思想,可以让相关人员在短时间内了解到kafka相关特性,如果想深入研究,后面会对其中每一个特性都做详细介绍。
Consumergroup:各个consumer可以组成一个组,每个消息只能被组中的一个consumer消费,如果一个消息可以被多个consumer消费的话,那么这些consumer必须在不同的组。消息状态:在Kafka中,消息的状态被保存在consumer中,broker不会关心哪个消息被消费了被谁消费了,只记录一个offset值(指向partition中下一个要被消费的消息位置),这就意味着如果consumer处理不好的话,broker上的一个消息可能会被消费多次。消息持久化:Kafka中会把消息持久化到本地文件系统中,并且保持极高的效率。消息有效期:Kafka会长久保留其中的消息,以便consumer可以多次消费,当然其中很多细节是可配置的。批量发送:Kafka支持以消息集合为单位进行批量发送,以提高push效率。push-and-pull : Kafka中的Producer和consumer采用的是push-and-pull模式,即Producer只管向broker push消息,consumer只管从broker pull消息,两者对消息的生产和消费是异步的。Kafka集群中broker之间的关系:不是主从关系,各个broker在集群中地位一样,我们可以随意的增加或删除任何一个broker节点。负载均衡方面: Kafka提供了一个 metadata API来管理broker之间的负载(对Kafka0.8.x而言,对于0.7.x主要靠zookeeper来实现负载均衡)。同步异步:Producer采用异步push方式,极大提高Kafka系统的吞吐率(可以通过参数控制是采用同步还是异步方式)。分区机制partition:Kafka的broker端支持消息分区,Producer可以决定把消息发到哪个分区,在一个分区中消息的顺序就是Producer发送消息的顺序,一个主题中可以有多个分区,具体分区的数量是可配置的。分区的意义很重大,后面的内容会逐渐体现。离线数据装载:Kafka由于对可拓展的数据持久化的支持,它也非常适合向Hadoop或者数据仓库中进行数据装载。插件支持:现在不少活跃的社区已经开发出不少插件来拓展Kafka的功能,如用来配合Storm、Hadoop、flume相关的插件。 2.3 kafka 应用场景 日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、Hbase、Solr等。消息系统:解耦和生产者和消费者、缓存消息等。用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。流式处理:比如spark streaming和storm事件源 2.4 Kafka架构组件 Kafka中发布订阅的对象是topic。我们可以为每类数据创建一个topic,把向topic发布消息的客户端称作producer,从topic订阅消息的客户端称作consumer。Producers和consumers可以同时从多个topic读写数据。一个kafka集群由一个或多个broker服务器组成,它负责持久化和备份具体的kafka消息。
topic:消息存放的目录即主题Producer:生产消息到topic的一方Consumer:订阅topic消费消息的一方 Broker:Kafka的服务实例就是一个broker 2.5 Kafka Topic&Partition 消息发送时都被发送到一个topic,其本质就是一个目录,而topic由是由一些Partition Logs(分区日志)组成,其组织结构如下图所示:
我们可以看到,每个Partition中的消息都是有序的,生产的消息被不断追加到Partition log上,其中的每一个消息都被赋予了一个唯一的offset值。 Kafka集群会保存所有的消息,不管消息有没有被消费;我们可以设定消息的过期时间,只有过期的数据才会被自动清除以释放磁盘空间。比如我们设置消息过期时间为2天,那么这2天内的所有消息都会被保存到集群中,数据只有超过了两天才会被清除。 Kafka需要维持的元数据只有一个–消费消息在Partition中的offset值,Consumer每消费一个消息,offset就会加1。其实消息的状态完全是由Consumer控制的,Consumer可以跟踪和重设这个offset值,这样的话Consumer就可以读取任意位置的消息。 把消息日志以Partition的形式存放有多重考虑,第一,方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了;第二就是可以提高并发,因为可以以Partition为单位读写了。
三、Kafka 核心组件 3.1 Replications、Partitions 和Leaders 通过上面介绍的我们可以知道,kafka中的数据是持久化的并且能够容错的。Kafka允许用户为每个topic设置副本数量,副本数量决定了有几个broker来存放写入的数据。如果你的副本数量设置为3,那么一份数据就会被存放在3台不同的机器上,那么就允许有2个机器失败。一般推荐副本数量至少为2,这样就可以保证增减、重启机器时不会影响到数据消费。如果对数据持久化有更高的要求,可以把副本数量设置为3或者更多。 Kafka中的topic是以partition的形式存放的,每一个topic都可以设置它的partition数量,Partition的数量决定了组成topic的log的数量。Producer在生产数据时,会按照一定规则(这个规则是可以自定义的)把消息发布到topic的各个partition中。上面将的副本都是以partition为单位的,不过只有一个partition的副本会被选举成leader作为读写用。 关于如何设置partition值需要考虑的因素。一个partition只能被一个消费者消费(一个消费者可以同时消费多个partition),因此,如果设置的partition的数量小于consumer的数量,就会有消费者消费不到数据。所以,推荐partition的数量一定要大于同时运行的consumer的数量。另外一方面,建议partition的数量大于集群broker的数量,这样leader partition就可以均匀的分布在各个broker中,最终使得集群负载均衡。在Cloudera,每个topic都有上百个partition。需要注意的是,kafka需要为每个partition分配一些内存来缓存消息数据,如果partition数量越大,就要为kafka分配更大的heap space。
Installation msysGit is a windows version of Git client. Download this installation package and install it:https://github.com/msysgit/msysgit/releases/download/Git-1.9.5-preview20141217/Git-1.9.5-preview20141217.exe
use default configuration is OK. Just click "Next" button all the way to the end.
Configuration Set user name and email Open Git Bash from desktop (or any folder) by right click:
config your user name and email: (They should be the same with your git profile settings)
git config --global user.name "Shishang, Yilin"
http://wenku.baidu.com/link?url=24avA5O5Z2IxrDb7WqSuK1Rtha1xuWldttLrAJlWnNg5Fu_ROjGw8q_QEym1KMHJ0mg5KBDa5usplBsP96ecCM6G6iMMcllN_W6zj4lr36m
1、var testuuid = replace(Packages.java.util.UUID.randomUUID(),"-","");
2、选择兼容模式
同一字符串,MD5加密后出现不同的结果 背景 公司数据采用MD5加密和ssl双向认证,最近把项目部署到服务器进行测试,结果MD5验证总是通不过,服务器在请求过来的加密32位串和本地加密32位串作对比时,总是返回false,那么问题来了,加密之前的明文是相同的,为何同样的加密方法却得到了不同的结果?
问题分析 首先考虑到的是操作系统的不同,win下运行正常的代码为何到linux下就不行了,但是MD5加密并不会受到不同系统的影响,这个原因被否决了。 最终问了下技术经理,问题原因才定位出来,问题就出在编码上,我们的项目的默认编码是GBK的编码,win下的默认编码也是GBK的编码,而linux一般情况下默认编码是UTF-8的编码,查看项目中确实有字段包含中文且没有对编码作出处理,传输字段理的不够清楚。
解决方案 对传输的数据指定编码即可解决问题:
String "处理后字符串" = URLEncoder.encode("处理前字符串", "utf-8"); 思考 一定要找准自己的位置,切勿自以为是,简单的会用一些技术,通了,搞定了,就意味自己掌握了,这是一个非常大的误区。要对技术的真正实现原理清楚,只有了解真正的原理,代码的效率才会高,遇到问题就不会没头没脑,浪费宝贵的时间。这种简单的解决方案可能存在不足,以后需要多了解编码方面的知识。 ©版权归Peiel所有,转载请注明出处。
1.webview 显示中文乱码
loadDataWithBaseURLwebview加载url时不会乱码,但是加载自己拼接的html代码会乱码,用loadDataWithBaseURL解决
webview.loadData(contentHtml.toString(), "text/html","utf-8");此方法显示中文乱码 webview.loadDataWithBaseURL(null, contentHtml.toString(), "text/html", "utf-8", null); 2.webview加载网页时支持LocalStorage 默认WebView没有开启LocalStorage存储。开启方法如下
webSettings.setDomStorageEnabled(true); webSettings.setDatabaseEnabled(true); webSettings.setAllowFileAccess(true); webSettings.setAppCacheEnabled(true); webSettings.setAppCacheMaxSize(1024*1024*8); webSettings.setDatabasePath(this.getCacheDir().getAbsolutePath()); 注:setDatabasePath在API19时已经废弃,原因是因为在4.4WebView的内核已经换为了Chrome的内核,存储路径有WebView控制。
传说这个方法可以生成20亿以内不重复long数值
public long GetCode(string shardField) { uint code = 0; shardField = shardField.Trim(); for (int i = 0; i < shardField.Length; i += 2) { code *= 16777619; code ^= shardField[i]; } var ss = code; return ss; }
float是单精度浮点型,占用4字节. 用%f打印. int是整型,占用4字节. 用%d打印. double 双精度浮点型,占用八字节. 用%.xd打印. char 字符型,占用1字节. 用%c打印. long长整型,占用4或8字节. 用%ld打印. short是短整型,占用2字节. 用%d打印. sizeof函数可以计算定义的类型占用几个字节.用%lu打印. 变量 由三部分组成,分别为类型修饰符,变量名和初始值.变量只能由字母,数字,下划线组成,且不能以数字开头.变量不能重复命名,不能与系统保留字重复.对于任何一个变量,都要先定义再使用. 简单的四则运算 在自加(减)算法中,++再前面直接自加1,++在后的先执行语句再加1. 表达式是由常量,变量,运算符组成的,并且表达式都有返回值.最好定义一个变量,讲表达式的值进行接收. 语句是执行程序的最小单位,以分号为结尾. 几种简单的交换变量的方法 第一种:利用 第三方变量.引入第三个值.将第一个值赋给第三方,再将第二个赋给第一个,最后将第三方的值赋给第二个. c=a; a=b; b=c; 第二种,利用 异或. a=a^b; b=a^b=(a^b)^b=a^b^b=a; a=a^b=(a^b)^b=(a^b)^a=a^a^b=a^b=b; 第三种,利用 赋值. a=a+b; b=(a+b)-b; a=a+b-((a+b)-b);
项目分阶段开发不可避免的存在迭代现象,可能下一版会在上一版源码基础上做很多改动,为了不影响原来版本的正常使用,这时需要复制原来的java web项目到新的项目,使用maven管理spring mvc项目在复制粘贴到新项目以后,要区别原来的项目,需要修改以下几个地方:
1.pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyName</groupId> <artifactId>oldproject</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>oldproject Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.3.4</version> </dependency> 将以上<artifactId>和<name>标签内容的oldproject替换为新的项目名称。
2.web.xml
只需要更改显示名称为新的项目名称。
<display-name>oldproject</display-name> 3.org.eclipse.wst.common.component
这个文件位于项目展开的.settings目录下,
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0"> <wb-module deploy-name="oldproject"> <wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/> <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/> <property name="context-root" value="oldproject"/> <property name="java-output-path" value="/oldproject/target/classes"/> </wb-module> </project-modules> 将以上部署名<wb-module deploy-name="oldproject">,
context-root属性<property name="context-root" value="oldproject"/>以及
java-output-path属性 <property name="
数据传送指令详解 前言 上一章我们说了汇编语言的基础,包括数据格式,寄存器以及操作数的标识方式,接下来我们就应该去认识一下hiU币按语言当红真难过的格各个指令了.这些指令大部署很简单,但是组合在一起却能模拟出我们程序当中香烟的任何效果,确实很神奇.
数据传送指令 数据传送指令的目的是我了将一个数据从一个位置复制到另一个位置.既然如此,那么数据传送至零就会包含一个源操作数和一个目的操作数,指令会将源操作数的值复制到目的操作数并覆盖.
数据传送指令一共可以分为5种,分别是mov,movs,movz,push以及pop.如果你多少懂一点编程语言的话,看名字就能知道一个大概,不过在这里我还是说一下各个指令的作用.
mov指令 mov指令的作用是将源操作数S中的数据复制到目的操作数D中,mov指令有一个数据格式和两个操作数,因此一般的形式为[movx S D].其中x为数据格式,S为源操作数,D为目的操作数.
举个简单的案例,比如我们有一条指令为movl %edx %eax.那么他的执行过程如下图所示:
可以看到,在指令执行之后,%edx寄存器当中的内容就会被复制到%eax寄存器.需要一提的是,mov指令可以在后面加上任何数据格式,比如上面这一过程中,数据格式为4个字节,也就是双字.因此不难推断出,我们还可以使用movb和movw去复制一个字节或两个字节.
movs指令 movs指令的作用是将源操作数S中的数据做符号扩展后,再复制到目的操作数D中,movs指令有两个数据格式和两个操作数,因此一般的形式为[movsxy S D].其中x,y位数据格式,S为源操作数,D为目的操作数.其中x,y的组合一共有三种,分别是bw,bl,wl,这三个组合代表的意思分别是单字节到双字节,单字节到双字以及双字节到双字.
还是举个例子,对于指令
movswl %dx %eax 来说 , 它的作用如下图 : 这里为了看出来符号位的扩展,因为我们在这里使用了十六进制的整数表示方式.可以看到,movs指令将0x8FFF扩展以后存入%eax寄存器,其中%dx为寄存器%edx的后16位表示.
movz指令 movz指令的作用是将源操作数S做零扩展后,再复制到目的操作数中.它与movs指令十分相似,也有两个数据格式和两个操作数,因此一般形式为[movzxy S D].各个字母代表的含义和movsxy代表的一样.
还是看案例,对于指令
movzwl %dx %eax 来说 , 他的作用和上面的 movs 有何不同 . 可以看出,movs和movz指令十分相似,只是这里扩展后,目标寄存器%eax的前16位是0而不是1.
push指令 push指令与上面的mov族的指令不同,他的目的是操作数被固定为栈顶,因此他的指令当中没有目的操作数另外友谊县需要注意,他在进行复制操作之前,需要移动栈顶指针(-4).push指令的一般形式为[pushl S],其中l代表数据格式为双字,S为源操作数,目的操作数默认为栈顶
案例,比如
pushl %edx 这条指令 , 他的任务是将 %edx 寄存器的值复制到栈顶 . 我们首先来看一下命令执行前 , 寄存器以及存储器的状态 . 可以看到,寄存器%ebp和%esp分别指向帧指针和栈指针,而%esp实际上就是指向栈顶.由于现在栈顶位于-16的位置,因此若要将%dex压入栈,则现需要将栈顶移动到-20的位置,然后再进行赋值,移动后的状态如下所示:
可以看到,这里的栈指针的位置已经发生了变化,向下移动了四位,并且将%edx寄存器的值放入新的栈顶,因此pushl %edx指令就相当于下面两条指令:
subl $4,%esp movl %edx,(%esp) 这里可以看出,其实push指令做了一个隐藏操作,就是移动栈指针(-4),这一点希望能引起大家的注意.
坚持住,还有最后一个命令!
pop指令 pop指令与push指令的做的相反的操作,一个是入栈一个是出栈.对于pop指令来说,他的源操作数背负定位栈顶,相反,它会先进行复制操作,然后再移动栈指针.pop指令的一般形式为[popl D],其中l代表数据类型,D为目的操作数,源操作数默认为栈顶.
此前就已经注册成为insider会员,自己电脑里面装的是很久以前的预览版10130,因为是会员版本,所以是自动激活的(装完之后因为还是有很多bug所以放在那里没管它,顺便提一下,我的是10跟7的双系统),然后今天直接通过msdn的win10正式版,通过虚拟光驱直接加载镜像,双击setup之后,没有需要输入密匙的环节,直接十分顺利的一路next直至装好win10。
此前曾经尝试过在另一台电脑上先安装win10预览版(我的尝试版本为101667,并且依然选择安装双系统),然后登陆会员,然而预览版并非激活状态,然后再升级win10正式版的时候,提示需要输入密匙,输入密匙之后(以前泄露出来的专业版批量安装密匙),安装成功,然而依然是未激活状态。此路不通之后,再第三台电脑上,存在已经激活的win7旗舰版(工具激活),依然选择安装双系统安装win10,同样是输入密匙之后非激活状态。
然后继续折腾,选择在双系统先安装上win7旗舰版,并通过激活工具激活(状态为永久激活),然后再通过win10正式版镜像,直接解压,通过硬盘安装双击setup,惊喜的是同样没有输入密匙的环节,一路安装下来,安装成功后即显示激活状态(cmd输入slmgr.vbs -xpr回车显示永久激活)。也就是说,盗版win7能洗白装上正版win10。
最后,并未尝试成功升级后重新全新安装win10。但网友们说是激活信息已经保存在微软服务器中,相信,成功升级为win10的电脑之后重新安装win10也是毫无激活压力的。
PostgreSQL有3种日志,分别是pg_log(数据库运行日志)、pg_xlog(WAL 日志,即重做日志)、pg_clog(事务提交日志,记录的是事务的元数据) pg_log默认是关闭的,需要设置参数启用此日志。pg_xlog和pg_clog都是强制打开的,无法关闭。 1.启用pg_log并配置日志参数 log_destination = 'csvlog' logging_collector = on log_directory = 'pg_log' log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' log_rotation_age = 1d log_rotation_size = 100MB log_min_messages = info # 记录执行慢的SQL log_min_duration_statement = 60 log_checkpoints = on log_connections = on log_disconnections = on log_duration = on log_line_prefix = '%m' # 监控数据库中长时间的锁 log_lock_waits = on # 记录DDL操作 log_statement = 'ddl' 2.重启PostgreSQL即可在$PGDATA/pg_log/ 下看到新生成的日志。 pg_ctl restart -m fast
--日志文件目录 日志的目录可以通过参数 log_directory 来设置,下面是我的参数设置。
log_directory = '/var/applog/pg_log' [postgres@pg_log]$ ll /var/applog/pg_log -rw------- 1 postgres postgres 4.
1. 类中的封装性不光体现在对属性的封装上,实际上方法也是可以被封装的,当然在方法封装中也包含了对构造方法的封装。
举例:
public class GzPrivate2 {
public static void main(String[] args) {
//声明对象,不会报错
Singleton s = null;
//实例化对象,调用了私有化的构造方法,程序报错
s = new Singleton();//错误,无法实例化对象
}
}
class Singleton{
private Singleton(){
//将构造方法进行了封装,私有化,这时候此构造方法只能在本类中可见!
}
public void prit(){
System.out.println("nishuibaichuan");
}
}
以上程序运行报错!因为此类Singleton中的构造方法被私有化了,只能在本类Singleton中可见,不能再外部直接实例化!
既然再外部不可用,那么我们就在内部使用!
举例:
public class GzPrivate {
public static void main(String[] args) {
//声明对象,不会报错
Singleton1 s = null;
}
}
class Singleton1{
//在内部产生本类的实例化对象
Singleton1 singleton1 = new Singleton1();
private Singleton1(){
//将构造方法进行了封装,私有化,这时候此构造方法只能在本类中可见!
}
#include<stdio.h> //用指向二维数组元素的指针实现 int main() { int a[3][4]={{1,2,3,4},{5,6,7,8,},{0,1,2,3}}; int *p; p=a[0]; for(p=a[0];p<a[0]+12;p++)//a[0]与*a,&a[0]a[0]等价 { if((p-a[0])%4==0) printf("\n"); printf("%d ",*p); } return 0; } #include<stdio.h> //用指向二维数组行的指针实现 int main() { int a[3][4]={{1,2,3,4},{5,1,6,7},{0,1,2,3}}; int i,j; int (*p)[4];//定义p为指针变量,指向含有4个int型元素的一维数组 p=a;//p指向二维数组a的行a[0] for(i=0;i<3;i++) { for(j=0;j<4;j++) printf("%d ",p[i][j]);//可用(*(p+i))[j], *(p[i]+j) ,*(*(p+i)+j)替换 printf("\n"); } return 0; }
今天分析了一下__main的流程,和大家分享一下
在进入__main之间打下断点, 当前命令“LDR r0 , [pc, #24]“ 将PC+24=0x080001E0地址处的数据加载到 r0 中,因为 CM4 内部
使用了指令流水线,读 PC 时返回的值是当前指令的地址+4。所以当前命令后,R0等于0x080001E0地址处的数据,如下图所示:R0=0x080001AD。
然后运行0x080001C6处的指令 “BX R0”,CM3 中的指令至少是半字对齐的,所以 PC 的 LSB 总是读回 0。然而, 在分支时,无论是直接写 PC 的值还是使用分支指令,都必须保证加载到 PC 的数值是奇数(即 LSB=1),用以表明这是在Thumb 状态下执行。倘若写了 0,则视为企图转入 ARM 模式,CM3 将产生一个 fault 异常。所以当前指令后,PC会跳转到0x080001AC处的地址。如下图所示
然后运行”BL.W __scatterload“ 跳转到0x080001e4地址的__scatterload函数中去。
接着向下运行,由于刚开始R4 = 0X08000CD4 R5=0X08000D04。每次循环R4+0X10,所以__scatterload中需要循环3次。
LDM R4,{R0-R2} 从R4指向的地址取3个4字节的数据,保存到R0,R1,R2中
第一次循环:给给定初值的全局变量赋初值。
然后跳转到R3=0X08000B5D 指向的地址中,通过查看工程生成的.map文件可以得知R3指向的地址是__scatterload_copy 函数,形参是R0,R1,R2 __scatterload_copy 0x08000b5d Thumb Code 14 handlers.o(i.__scatterload_copy)
LDM R0!,{R3} 从R0指向的地址中的数据加载R3中,然后将R0+4 。如下图所示R0的值比上图加4了
STM R1!,{R3} 将R3中的数据保存到R1指向的地址中,然后将R1+4。如下图所示R1的值比上图加4了 这样循环9次=0x24/4。将内存中0XD0000000地址开始的,长度为0x24=36字节的区域的有初值的全局变量给赋值了。
map文件中
SDRAM_Register 0xd0000004 Data 4 sdram.
目的:使用JMeter做接口测试,输入参数格式为JSON
步骤:
1.添加线程组、HTTP请求默认值、察看结果树等参考《JMeter实现bugfree登录接口测试》。这里不再赘述。
2.添加HTTP请求
在Body Data中写上输入的参数。参数的格式为JSON。
3. 此时如果直接运行会出现如下报错。这是因为,JMeter中传递JSON格式的参数时,需要在“HTTP信息头管理器”中添加信息头。
4. 添加“HTTP信息头管理器”。
5.再次运行,结果正确。
1、流程
代码编写 =》 作业配置 =》 作业提交 =》 Map任务的分配和执行 =》 处理中间结果 =》 Reduce任务的分配和执行 =》 作业完成
在每个任务的执行过程中,又包含输入准备 =》 任务执行 =》 输出结果
MapReduce作业的执行可以分为11个步骤,涉及4个独立的实体:
客户端(client):编写MapReduce代码,配置作业、提交作业。
JobTracker:初始化作业,分配作业,与TaskTracker通信、协调整个作业的执行
TaskTracker:保持JobTracker的通信,在分配的数据片段上执行Map或Reduce任务。
HDFS:保存作业的数据、配置信息等,保存作业结果。
2、作业提交
一个MapReduce作业在提交到hadoop上之后,会进入完全的自动化执行过程。在这个过程中,用户除了监控程序的执行和强制中止作业之外,不能对作业的执行过程进行任何干扰。所以,在作业提交之前,用户需要将所有应该配置的参数按照自己的意愿配置完毕。需要配置的主要参数如下:
程序代码、Map和Reduce接口的配置、输入/输出路径、其他类型设置
整个提交过程包含以下步骤:
(1) 通过调用JobTracker对象的getNewJobId()从JobTracker处获取当前作业的id号
(2) 检查作业相关路径。
(3) 计算作业的输入划分,并将划分信息写入Job.split文件,如果写入失败就会返回错误。
(4) 将运行作业所需要的资源—包括作业JAR文件、配置文件和计算所得的输入划分等—复制到作业对应的HDFS上。
(5) 调用JobTracker对象的submit()方法来真正提交作业,告诉JobTracker作业准备执行。
3、初始化作业
在客户端用户作业调用JobTracker对象的submitJob()方法后,JobTracker会把此调用放入内部的taskScheduler变量中,然后进行调试。
初始化过程主要有以下步骤:
(1) 从HDFS中读取作业对应的job.split。
(2) 创建并初始化Map任务和Reduce任务。
(3) 最后就是创建两个初始化任务,根据Map和Reduce个数及输入分片中已经配置的信息,分别初始化Map和Reduce
4、分配任务
TaskTracker和JobTracker之间通过心跳通信汇报状态和分配任务。TaskTracker首先发送自己的状态(主要是Map任务和Reduce任务的个数是否小于上限),并根据自己的条件选择是否向JobTracker请求新的任务,最后发送心跳。JobTracker接收到TaskTracker的心跳后首先分析心跳信息,如果发现TaskTracker在请求一个新任务,那么任务调试器就会将任务和任务信息封装起来返回给TaskTracker。
针对Map任务和Reduce任务,TaskTracker有固定数量的任务槽(Map任务和Reduce任务的个数都有上限)。当TaskTracker从JobTracker返回的心跳信息中获取新的任务信息时,会将Map任务或者Reduce任务加入对应的任务槽中。需要注意的是,在JobTracker为TaskTracker分配Map任务时,为了减小网络带宽会考虑将Map任务数据本地化。它会根据TaskTracker的网络位置,选取距离最近的输入划分文件分配给些TaskTracker。最好情况是,划分文件就在TaskTracker本地。
5、执行任务
在TaskTracker申请到新的任务之后,就要在本地运行任务了。通过调用localizeJob()方法来完成本地化。
(1) 将job.split复制到本地。
(2) 将job.jar复制到本地。
(3) 将job的配置信息定稿job.xml
(4) 创建本地任务目录,解压job.jar
(5) 调用launchTaskForJob()方法发布任务。
本地化后,调用launchTaskForJob()真正启动起来,调用launchTask()方法启动任务。launchTask()方法先会为任务创建本地目录,然后启动TaskRunner,在启动TaskRunner后,对于Map任务,会启动MapTaskRunner;对于Reduce任务则启动ReduceTaskRunner。
6、更新任务执行进度和状态
TaskTracker每隔5s发送给JobTracker的心跳中封装任务状态,报告自己的任务执行状态。通过心跳通信机制,所有TaskTracker的统计信息都会汇总到JobTracker处。JobTracker将这些统计信息合并起来,产生一个全局作业进度统计信息,表明正在运行的所有作业及其中所含任务的状态。最后,JobClient通过每秒查看JobTracker来接收作业进度的最新状态。
7、完成作业
所有TaskTracker任务的执行进度信息都会汇总到JobTracker处,当JobTracker接收到最后一个任务已完成的通知后,便把作业的状态设置为“成功”。然后,JobClient也将及时得知任务已成功完成,它便会显示一条信息告知用户,最后从runJob()方法处返回(在返回后,JobTracker会清空作业的工作状态,并指示TaskTracker也清空作业的工作状态,如删除中间输出等)。
1. 下载eclipse
因为安装了64位的jdk,所以eclipse版本也为64位:eclipse-jee-mars-R-linux-gtk-x86_64.tar.gz
2. 解压缩文件到/opt目录下
sudotar -xsvf ~/下载/ eclipse-jee-mars-R-linux-gtk-x86_64.tar.gz -C /opt/
3. 下载eclipse支持对应hadoop版本的插件包(我将提供)
hadoop-eclipse-plugin-2.6.0.jar
4. 将插件包复制到eclipse解压目录下的plugins中
5. 启动eclipse
6. 配置eclipse
(1) 打开windowàpreferencesàHadoop Map/Reduce,引入hadoop的安装目录
(2) 打开window-->show view-->other,选择Map/Reduce Location ,点击OK
(3) 右击选择New Hadoop location
location name:名字随意
Map/Reduce(V2) Maste中的配置与mapred-site.xml一致,
DFS Master的配置与core-site.xml一致
7. 下面就可以创建Map/Reduce工程进行编程开发了
我们可用从Kinect的官方文件知道,Kinect的视锥是这个样子的。图中A,B和小人的脚是处于同一平面的,那么kincet获取到的
世界坐标中A,B的y轴坐标是相等的?还是如在RGB图中看到的一样,A,B,一上一下,y轴坐标不相等呢?
因此我抓获了Kinect的RGB,depth图像,对其后并转换成世界坐标,通过鼠标的点击来查看A,B的坐标。
最后结论如我所期待的一样:A,B在同一平面,A,B点y轴坐标相等。
这对小车室内定位和运作有重大意义。
获取到的RGB图像
获取到的depth图像
坐标排列(x, y, z)
opencv 2.3后有了获取世界坐标方法,大大减少了工作量
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_highgui.html
capture.retrieve(depthMap,CV_CAP_OPENNI_POINT_CLOUD_MAP);//XYZ in meters (CV_32FC3),以米为单位的XYZ点云 (CV_32FC3) 获取世界坐标数据
cout<<"mouse location:"<<"("<<cvGet2D(Image,y,x).val[0]<<"," \ <<cvGet2D(Image,y,x).val[1]<<"," \ <<cvGet2D(Image,y,x).val[2]<<")"<<endl;
CPN神经网络的一些资料:
http://wenku.baidu.com/link?url=JIhrQ5tpegz_KfBEV6TT9nPL6SYBq-Msc8GzHJYgAi2rM462hTZy2QU4G7qUQYXlOdVxxHKn-FRKS5Ok9Jkc02gM2B72ySRrf9SM-mqZrT7
CPN神经网络设计步骤如下:
C代码如下:(本代码按照步骤完成,同时也对照MATLAB代码修改,但是并没有预测功能,只能判断已输入的样本属于哪一类。贴出代码,希望大牛能帮帮忙)
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#include "vector"
using namespace std;
#define INF 99999
#define dimIn 4 //输入样本维数
#define dimOut 1 //期望输出样本维数 #define competeNum 40 //竞争神经元数
#define maxLoop 6000 //训练次数
#define alpha 0.41 //输入层到竞争层的学习率
#define delta 0.32 //竞争层到输出层的学习率
typedef vector<double> doubleVector;
vector<doubleVector> dataIn; //输入训练样本
vector<doubleVector> dataOut; //期望输出样本
vector<doubleVector> W; //输入层到竞争层的权值
vector<doubleVector> V; //竞争层到输出层的权值
doubleVector B; //二值输出向量
vector<doubleVector> Y; //输出层输出向量
void getFileData(char *File1, char *File2); //获取样本
LZ4 (Extremely Fast Compression algorithm) 项目:http://code.google.com/p/lz4/ 作者:Yann Collet 本文作者:zhangskd @ csdn blog
简介
LZ4 is a very fast lossless compression algorithm, providing compression speed at 400MB/s per core, scalable with multi-cores CPU. It also features an extremely fast decoder, with speed in multiple GB/s per core, typically reaching RAM speed limits on multi-core systems. A high compression derivative, called LZ4_HC, is also provided. It trades CPU time for compression ratio.
#include<stdio.h> #include<string.h> #include<algorithm> #include <vector> #include <iostream> using namespace std; int a[10] = {0,1,5,3,6,9}; vector<int> v; int main() { v.clear(); v.push_back(a[1]); for(int i=2;i<5;i++) { if(a[i] > v.back()) { v.push_back(a[i]); } else { *lower_bound(v.begin(),v.end(),a[i]) = a[i]; } } cout << v.size() << endl; } #include<stdio.h> #include<string.h> #include<algorithm> #include <vector> #include <iostream> using namespace std; int a[10] = {0,1,5,3,3,6,9}; vector<int> v; int main() { v.clear(); v.push_back(a[1]); for(int i=2;i<6;i++) { if(a[i] >= v.
为ListView添加炫酷的Item中带侧滑的删除,原理是利用item布局中的padding(Left和Right)属性为负值,来把删除的按钮隐藏在屏幕外。然后通过自定义ListView重写其中的OnTouchEvent通过手指坐标点的计算来处理事件,实现itemView的滚动,达到滑动出现删除菜单,本例中仅实现右向左滑出现删除按钮,大家可以根据自己需求,参照自定义ListView中事件处理做出左侧滑,右侧滑出现菜单,当然不仅仅局限于删除。更多灵活用法期待发觉。
首先上自定义的ListSlideView代码,其中有有详细注释,我就不废话了!(该ListView参考以前项目里面的事件分发处理判断,具体参考了哪位大神的写法已无法考究,感谢最原先的作者的同时也请见谅,如见可联系博主,把参考出处加上)
ListSlideView:
/** * ListSlideView.java * 2015 下午3:00:24 */ package com.example.slideviewtest; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.widget.AdapterView; import android.widget.ListView; import android.widget.Scroller; /** * @note 自定义的listView,集成自系统的ListView,对list的OnTouchEnvent事件分发进行了拦截处理(最关键的地方, * 也是通过该方式实现了控制屏幕外布局的拖拽) 需要配合Item的布局文件来实现 * @author blank * @time 下午3:00:24 * @version V1.0 */ public class ListSlideView extends ListView { /** 禁止侧滑模式 */ public static int MODE_FORBID = 0; /** 从右向左滑出菜单模式 */ public static int MODE_RIGHT = 1; /** 当前的模式 */ private int mode = MODE_FORBID; /** 右侧菜单的长度 */ private int rightLength = 0; /** * 当前滑动的ListView position */ private int slidePosition; /** * 手指按下X的坐标 */ private int downY; /** * 手指按下Y的坐标 */ private int downX; /** * ListView的item */ private View itemView; /** * 滑动类 */ private Scroller scroller; /** * 认为是用户滑动的最小距离 */ private int mTouchSlop; /** * 判断是否可以侧向滑动 */ private boolean canMove = false; /** * 标示是否完成侧滑 */ private boolean isSlided = false; public ListSlideView(Context context) { this(context, null); } public ListSlideView(Context context, AttributeSet attrs) { this(context, attrs, 0); TypedArray a = context.
#include<stdio.h> int main() { int m,k,xx[100],cnt=0,i; scanf("%d%d",&m,&k); while(k>cnt) { m++; for(i=2;i<=m;i++)//i<=m与i<m都可 if(!(m%i)) break; if(i==m) xx[cnt++]=m;//注意:先算出xx[0],然后cnt++ } for(i=0;i<cnt;i++) printf("%d ",xx[i]); return 0; }
系统环境:CentOS + Keepalived + HAProxy + MariaDB + Galera + MongoDB
当我们在架设高可用服务器环境时会遇到来自于系统级别的连接数限制问题,这是因为CentOS根据系统硬件信息自己默认初始了一个限制连接数量,往往这个数量是我们遇到的问题,所以今天我们需要修改系统的默认值来达到我们需要的要求,解决一定的高并发产生的连接数问题。
使用以下命令查看当前最大连接数:
[root@HA ~]# ulimit -n 1024 修改以下配置文件: 编辑/etc/security/limits.conf
[root@HA ~]# vi /etc/security/limits.conf * soft nofile 65535 * hard nofile 65535 * soft nproc 65535 * hard nproc 65535 在配置文件中添加以上内容 编辑/etc/pam.d/login
[root@HA ~]# vi /etc/pam.d/login session required pam_limits.so在配置文件中添加以上内容 将以上保存好,然后重启服务器,再使用 ulimit -n [root@HA ~]# ulimit -n 65535
@implementation NSString (Number) - (int)numCount { int count = 0; for(int i = 0; i < self.length; i++) { unichar c = [self characterAtIndex:i]; if (c > '0' && c < '9') { count++; } } return count; } @end int main() { int count =[@"ddjee8228jdjujwwuw8w" numCount]; NSLog(@"%d",count); return 0; }
#import <Foundation/Foundation.h> @interface NSString (Number) + (int)numCountOfNSString:(NSString *)str; @end @implementation NSString (Number) + (int)numCountOfNSString:(NSString *)str { int count = 0; for(int i = 0; i < str.length; i++) { unichar c = [str characterAtIndex:i]; if (c > '0' && c < '9') { count++; } } return count; } @end int main() { int count =[NSString numCountOfNSString:@"sjji32m223jf33i445e"]; NSLog(@"%d",count); return 0; }
转载请注明出处: http://blog.csdn.net/lb377463323/article/details/47170441 1,首先注册成为一名开度开发者,登录你的到百度账号,打开http://developer.baidu.com/user/info,在此填写注册信息
2,登录百度地图首页,右上角有地图API选项,点进去
3,网页往下拉可以看到“申请密钥”,点进去
4,点创建应用
5,填写内容
6,重点讲下如何获取Android studio的安全码
首先打开AS中的Terminal,定位到debug.keystore文件(一般路径是C:\Users\Administrator\.android\debug.keystore)
其次在Terminal命令行输入 keytool -list -v -keystore "C:\Users\Administrator\.android\debug.keystore" ,注意“-v"可以去掉,然后Enter键会显示输入密钥库口令(如下图),口令默认为android,注意你输入的时候不显示,直接输就好了
显示结果如下图
7,在Android studio的mainfests中找到自己的包名
8,安全码就是:64:03:9A:98:C5:E0:3E:EA:5B:6B:7B:8C:93:70:C4:DA:BF:96:34:A9;com.brian.locationtest
9,申请结果为
AK就是APIkey
介绍2中字符串的定义方式,及其注意的地方
1.利用数组
char array = "hello";
*特点: 字符串里面的字符可以修改
*使用场合:字符串里面的字符需要经常修改
2.利用指针
char *array = "hello";
*特点: 字符串里面的字符不能被修改
*使用场合:字符串里面的字符不需要修改,而且经常使用
void reverseArray(int a[],int n)
{
for(int i = 0; i < (n/2); i++)
{
int temp = a[i];
a[i] = a[n-1-i];
a[n-1-i] = temp; }
}
int main()
{
printf("请输入5个整数\n");
int array[5];
for(int i=0;i<5;i++)
{
scanf("%d",&array[i]);
if(getchar()=='\n')break;
}
reverseArray(array,5);
for(int i = 0;i < 5; i++)
{
printf("%d\t", array[i]);
}
return 0;
}
最近项目涉及到较多设备批量管理的需求,发现一工具,可以批量对大量设备进行WEB端管理,工具主页:https://openstf.github.io/ 工具名STF(Smartphone Test Farm)
STF (or Smartphone Test Farm) is a web application for debugging smartphones, smartwatches and other gadgets remotely, from the comfort of your browser.
上个主页上的效果图吧:
它的github页面为: https://github.com/openstf/stf 下面简单记录下在Ubuntu上搭建它的步骤(windows暂时没尝试过,应该类似) 环境:Ubuntu15.04(desktop-64bit) 浏览器:firefox 1、Linux一些基本包的安装: 在控制台分别运行
sudo apt-get update sudo apt-get install git sudo apt-get install lib32stdc++6 sudo apt-get install yum 2、SDK环境安装 这里我偷了个懒直接拷贝已经下载好的JDK和Android SDK环境过来,当然如果没有的同学估计要重新慢慢下载和安装了。 拷贝SDK目录到HOME目录中,打开控制台命令运行:
sudo gedit ~/.bashrc 配置环境变量并保存退出(wang为用户名,需要根据实际路径来填写)
export JAVA_HOME=/home/wang/SDK/jdk1.8.0_45 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export ANDROID_HOME=/home/wang/SDK/android-sdk-linux export PATH=$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$PATH 在控制台执行命令使之生效:
SQL SERVER指定更新数据影响行数:
Update Top (10)A_Message set IsRead=1 where MsgCode='201403026'; SQL SERVER中 Top (10)表示每次只更新10条数据。
MYSQL指定更新数据影响行数:
UPDATE A_Message set IsRead=1 LIMIT 10; MySQL 中 LIMIT 10表示每次只更新10条数据。
希望以上分享对初学朋友有些帮助,谢谢! 更多关注付义方技术博客:http://blog.csdn.net/fuyifang 或者直接用手机扫描二维码查看更多博文:
int main()
{
// 正确写法
// 第一种
int group1[5] = {1, 2, 3, 4, 5};
// 第二种
int group2[5] = {1, 2};
// 第三种
int group3[5] = {[3] = 4, [4] = 5};
// 第四种
int group4[5] = {1, 2, 3, 4, 5};
// 第五种
int a = 5;
int group8[5];
group8[0] = 1;
group8[1] = 2;
// 错误写法
// 第一种--数组元素不确定
int group5[];
// 第二种--在定义数组以后,才进行初始化 int group6[5];
group6 = {1, 2, 3, 4, 5};
//---------------------前言唠叨废话-------------------------------------------
本文的目标:让不是很了解DSP的小伙伴会用FFT(快速傅里叶变换),并知道怎么用代码实现FFT,不求甚解,但求works。
最近做项目用到FFT, 之前学的一直就不是很明白,现在用到了决定好好的把它搞懂。在中文网站上找了一些资料,发现讲的都不是很清楚,或者是我水平太低看不懂。后来还是在国外网站上找到了一篇讲深入浅出浅显易懂很接地气的文章。这里把它翻译过来,又加了一些自己的见解。方便国内的小伙伴们学习~
为啥要说是‘准零基础‘呢,就是说你需要了解一些基本的信号学和数学知识(至少听说过傅里叶变换,离散数字信号,频域分析这些概念!!),如果你真的是连这些都没听说过,那好吧,这篇文章帮不了你,出门左转祝你成功~
差点忘了~感谢alwatslearn 网站,作者是哪位没找到,不好意思啦。
废话就说到这里啦~ 下面进入正题
//-----------------------------------前言唠叨废话结束----------干货开始---------
想要透彻的掌握FFT,在看code之前,首先要先了解FFT的数学原理,本文先从数学原理开始介绍FFT,然后再来讨论实现FFT的code。
有过一些信号处理方面基础的小伙伴们可能知道,FFT(傅里叶变换)是建立在DFT(离散傅里叶变换)基础上的。FFT 可以说是DFT的另一种版本,是在DFT的基础上更快速,更适合计算机运算的一种傅里叶变换。所以,我们先从DTF开始。
DTF主要实现的功能是将时域的数据转换为频域的数据。DFT意味着对一个无限周期限号进行无限分割。其最基本的公式如 公式1 所示。
公式1
x(k) 是将要被转换到频域的时域信号(以时间为横轴的波形)
下面是DFT中需要用到的基本概念:
(下列概念可能稍微有些抽象,不好理解,先看一下有些印象,稍后结合例子讲解之后应该就可以理解了)
1. 采样率(sampling rate,sr). 其意义为在一个时间周期内所采样次数。为了学习的简单,我们姑且认为采样 时间间隔(sample interval,si)是相等的。
2. 基础时间(fundamental period,T). 全部采样所需的时间。也称为 窗口(window)。
3. 基础频率 (fundamental frequency,f0). 也就是1/T, 第一个波的频率为f0,第二个播的频率 2*f0,第 三个波的频率为 3*f0,以此类推
4. 采样数量N
5. 奈奎斯特频率fc. fc是依据奈奎斯特采样定律所得出的可以被正确采样的信号的最大频率,如果信号超过这个 频率,那么采样后的信号将会失真。奈奎斯特采样定律是信号理论里最进本的定律(即采样频率至少应为原 信号的两倍),在这里不做过多的讲解,详情可以参阅维基,定律本身十分简单容易理解。
6. 欧拉公式(Euler's formula),复数概念最基本的公式。相信大家都会,详情可参阅维基百科。
7. 将要进行DFT的时域信号,x(t). 8. 为了让指数表达更简洁,采用Wn 代替。 有些地方也将它称为 twiddle fatctor(旋转因子)。
了解完基本的定义,下面我们结合一个简单的例子来了解一下DFT 到底是干啥的。
为了简便,我们将对一个正弦信号进行采样,采样点的个数为 N(number of points),然后对其进行DFT。在DFT的过程中上面所介绍的概念将会被用到。在现实生活中,DFT的信号一般远比正弦信号复杂。
图 1
如图 1 所示,被采样的信号时一个正弦信号,横轴为时间,纵轴为振幅,红点为采样点(sampled point),基础时间为T,采样间隔(sampling interval)为2*pi/4。 从图可以看出,原始信号可以通过这四个采样点被还原,换句话说虽然只从无限多个点中采了4个点,但是原始正弦信号的属性可以从这四个点中反映出来。
有时候我们在定义了一个结构体之后,想将其中的字符串元素赋值为空,如果直接赋值为0或者null,结果是会报错的,下面给出一种方法,仅供学习参考!
int main()
{
struct Student
{
int age; char name[10]; } ;
struct Student str[2] =
{
{20, "jack"},
{21, "jake"},
};
/* str[0].name = null; 直接赋值为空,是会报错的 */
strcpy(str[0].name, ""); // 赋值为空
strcpy(str[0].name, "jim"); // 赋值为空后,重新赋值,也可以直接用此方法直接重新赋值
printf("%s\n", str[0].name);
return 0;
}
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。
该方法的基本思想是:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
之前提到过,Array的Sort()方法采用的是快速排序方法,通过使用.NET Reflector对程序集mscorlib进行解析,分析源码。
首先安装.NET Reflector,打开VS2010,新建一个项目,键入如下代码: string [] names = {"wang", "li", "liu", "zhao"}; Array.Sort(names); 在Sort上右键,选择“Open in .NET Reflector Desktop”,便会自动打开.NET Reflector: public static void Sort(T[] array) { if (array == null) { throw new ArgumentNullException("array"); } Sort(array, array.GetLowerBound(0), array.Length, null); }
点击Sort(array, array.GetLowerBound(0), array.Length, null): public static void Sort(T[] array, int index, int length, IComparer comparer) { if (array == null) { throw new ArgumentNullException("array"); } if ((index < 0) || (length < 0)) { throw new ArgumentOutOfRangeException((length < 0) ?
什么意思AndroidManifest.xml file missing!
import java.util.*; class Nnumber { public static void main (String args[ ]){ double sum=0; int n=0,b=0; System.out.println("请输入n的值:"); Scanner reader = new Scanner(System.in); n = reader.nextInt(); System.out.println("请输入n个数,每个数字用回车结束"); int a= reader.nextInt(); sum=a; for(int i=1;i<n;i++){ b= reader.nextInt(); sum = sum+b; if(a>b){ a=b;} } System.out.println("一共"+n+"个数,最小值是:"+a); System.out.println("平均值是:"+sum/n); } }