Quantcast
Channel: CSDN博客推荐文章
Viewing all 35570 articles
Browse latest View live

蚂蚁感冒

$
0
0

                 nyoj990 和蓝桥杯都有这道题。

                  由于数据很水,模拟应该也能过。

            主要说一下O(n)算法,两只蚂蚁相遇可以看做互相穿过,那么向右走的蚂蚁数量和向右走的蚂蚁数量都不会变。假设第一只感冒的蚂蚁向右走,那么在它右边向左走的蚂蚁都会感冒,如果它的右边存在向左走的蚂蚁,那么它的左边向右走的蚂蚁也会和他们相遇,总的感冒蚂蚁就算出来了。

AC代码

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000") 
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int> 
typedef long long LL;
const int maxn = 50 + 5;
int pos[maxn];
bool cmp(int a, int b) {
	return abs(a) < abs(b); 
}
int main() {
	int n;
	while(scanf("%d", &n) == 1) {
		for(int i = 0; i < n; ++i) scanf("%d", &pos[i]);
		int fir = pos[0]; //第一只蚂蚁的位置 
		sort(pos, pos+n, cmp);
		int b = 0, c = 0;
		int tpos;
		for(int i = 0; i < n; ++i) {
			if(pos[i] == fir) {
				tpos = i;
				break;
			}
			if(pos[i] > 0) ++b;
		}
		for(int i = tpos+1; i < n; ++i) {
			if(pos[i] < 0) ++c;
		}
		int ans = 1;
		if(fir < 0) { //向左 
			ans += b;
			if(b) ans += c;
		}
		else if(fir > 0) { //向右 
			ans += c;
			if(c) ans += b;
		}
		printf("%d\n", ans);
 	}
	return 0;
} 

如有不当之处欢迎指出!
作者:flyawayl 发表于2017/3/20 19:09:28 原文链接
阅读:79 评论:0 查看评论

【PMP】PMBOK 笔记 第2章 组织影响和项目生命周期

$
0
0

第2章 组织影响和项目生命周期

总结

本章主要讲了

  • 事业环境因素
  • 组织过程资产
  • 项目类型
  • 干系人
  • 项目生命周期

以上内容会成为之后的组织过程的重要的输入和输出,算是给以后的知识做铺垫。

2.1 组织对项目管理的影响

2.1.1 组织文化与风格

文化规范,包括既有的项目启动规划方法、可接受的工作执行手段,以及公认的决策制定者或决策者

组织文化是一种事业环境因素

2.1.2 组织沟通

2.1.3 组织结构

组织结构是一种事业环境因素,它可能影响资源的可用性和项目的执行方式。

表 2-1 组织结构对项目的影响

典型的职能型组织是一种层级结构,每个雇员都有一位明确的上级。

在职能型组织中,各个部门相互独立地展开各自的项目工作。

根据职能经理和项目经理之间的权力和影响力的相对程度,矩阵型组织可分为弱矩阵平衡矩阵强矩阵

项目联络员作为工作人员的助理和沟通协调员,不能亲自制定或推行决策。项目协调员有权力做一些决策,有一定的职权,向较高级别的经理汇报。

在项目型组织中,项目经理拥有很大的自主性和职权。这种组织中也经常采用虚拟协同技术来获得集中办公的效果。

很多组织在不同的组织层级上用到上述所有的结构,这种组织通常被称为复合型组织。

组织结构中,会有三个层级

  • 战略层
  • 中级管理层
  • 操作层

2.1.4 组织过程资产

组织过程资产是执行组织所特有并使用的计划、流程、政策、程序和知识库,包括来自任何(或所有)项目参与组织的,可用于执行或治理项目的任何产物、实践或知识。

组织过程资产是大部分规划过程的输入。

2.1.4.1 流程与程序

组织用于执行项目工作的流程与程序

  • 启动和规划
    • 指南和标准,用于裁剪组织标准流程和程序以满足项目的特定要求
    • 特定的组织标准,例如政策(如人力资源政策、健康与安全政策、职业道德政策、项目管理政策)、产品项目生命周期、质量政策与程序(如过程审计、改进目标、核对单、组织内使用的标准化的过程定义)
    • 模板(如风险登记册、工作分解结构、项目进度网络图及合同模板)
  • 执行和监控
    • 变更控制程序
    • 财务控制程序
    • 问题与缺陷管理程序
    • 组织和沟通的要求
    • 确定工作优先顺序、批准工作与签发工作授权的程序
    • 风险控制程序
    • 标准化的指南、工作指示、建议书评价准则和绩效测量准则。
  • 收尾
    • 项目收尾指南或要求,(如经验教训、项目终期审计、项目评价、产品确认和验收标准

2.1.4.2 共享知识库

配置管理知识库,包括执行组织的所有标准、政策、程序和任何项目文件的各种版本与基准。

2.1.5 事业环境因素

事业环境因素是指项目团队不能控制的,将对项目产生影响、限制或指令作用的各种条件。

事业环境因素是大多数规划过程的输入。

重点包括
- 公司的工作授权系统
- 商业数据库,(如标准化的成本估算数据、行业风险研究资料和风险数据库)
- 项目管理信息系统(如自动化工具,包括进度计划软件、配置管理系统、信息收集与发布系统或进入其他在线自动系统的网络界面)

2.2 项目干系人和治理

干系人是指能影响项目决策、活动或结果的个人、群体或组织,以及会受或自认为会受项目决策、活动或结果影响的个人、群体或组织

不同的干系人可能有相互竞争的期望,因而会在项目中引发冲突。

2.2.1 项目干系人

干系人包括所有项目团队成员,以及组织内部或外部与项目有利益关系的实体。

图 2-7 干系人与项目的关系

不同干系人在项目中的责任和职权各不相同,并且可随项目生命周期的进展而变化。他们参与项目的程度可能差别很大。

在整个项目生命周期中,识别干系人是一个持续的过程。

正如干系人可能积极或消极地影响项目目标,干系人也可能认为项目会产生积极或消极的结果。

  • 发起人。发起人是为项目提供资源和支持的个人或团体,负责为成功创造条件。发起人可能来自项目经理所在组织的内部或外部。对于那些超出项目经理控制范围的事项,将向上汇报给发起人。
  • 客户和用户。客户是将要批准和管理项目产品、服务或成果的个人或组织。用户是将要使用项目产品、服务或成果的个人或组织。客户和用户可能来自项目执行组织的内部或外部,也可能是多层次的。在另一些领域,客户是指项目产品的购买者,用户则指项目产品的直接使用者。
  • 卖方
  • 业务伙伴
  • 组织内的团体
  • 职能经理
  • 其他干系人

2.2.2 项目治理

项目治理是一种符合组织治理模式的项目监管职能,覆盖整个项目生命周期。项目治理框架向项目经理和团队提供管理项目的结构、流程、决策模式和工具,同时对项目进行支持和控制,以实现项目的成功交付。

项目治理给项目团队提供了一个工作框架。

2.2.3 项目成功

项目经理和高级管理层批准的范围、时间、成本、质量、资源和风险等目标,来考核项目的成功。

2.3 项目团队

项目团队包括项目经理,以及为实现项目目标而一起工作的一群人,以及其他执行项目工作但不一定参与项目管理的团队成员。

项目经理作为团队领导者的角色是固定不变的,无论项目经理对团队成员有多大的职权。

项目团队中的角色有:

  • 项目管理人员
  • 项目人员
  • 支持专家
  • 用户和客户代表
  • 卖方
  • 业务伙伴成员
  • 业务伙伴

2.3.1 项目团队的组成

两种基本的组成方式:

  • 专职团队,职权关系清楚,团队成员专注于项目目标,项目型组织
  • 兼职团队,职能型组织

项目团队的组成会因组织结构而发生变化

项目团队的组成也会因成员所处的地理位置而发生变化,例如虚拟项目团队。

虚拟团队使用协同工具(如共享在线空间、视频会议等)来协调项目活动,传递项目信息。虚拟团队可以采用任何一种组织结构和团队组成方式。

2.4 项目生命周期

项目生命周期指项目从启动到收尾所经历的一系列阶段。项目阶段通常按顺序排列。

2.4.1 项目生命周期的特征

  • 启动项目
  • 组织与准备
  • 执行项目工作
  • 结束项目

不应该和项目管理过程组相混淆

图 2-8 通用项目生命周期结构中典型的成本与人力投入水平

通用的生命周期结构具有以下特征

  • 成本与人力投入在开始时较低,在工作执行期间达到最高,并在项目快要结束时迅速回落
  • 成本和人力投入的典型走势可能并不适用于所有项目
  • 风险与不确定性在项目开始时最大,并在项目的整个生命周期中随着决策的制定与可交付成果的验收而逐步降低
  • 在不显著影响成本的前提下,改变项目产品最终特性的能力在项目开始时最大,并随项目进展而减弱

图 2-9 随项目时间而变化的变量影响

2.4.2 项目阶段

一个项目可以划分为任意数量的阶段

如果待执行的工作具有某种独特性,就可以把它们当做一个项目阶段。项目阶段通常都与特定的主要可交付成果的形成相关。

阶段的结束以作为阶段性可交付成果的工作产品的转移或移交为标志,被称为阶段关口、里程碑、阶段审查、阶段门或关键决策点

尚没有适用于所有项目的最佳结构。

2.4.2.1 阶段与阶段的关系

两种基本类型

  • 顺序关系。
  • 交叠关系。进度压缩的一种技术,被称为快速跟进

2.4.2.2 预测型生命周期

预测型生命周期(也称为完全计划驱动型生命周期),在项目生命周期的尽早时间,确定项目范围及交付此范围所需的时间和成本。

项目启动时,项目团队专注于定义产品和项目的总体范围,然后制定产品(及相关可交付成果)交付计划,着通过各阶段来执行计划。应该仔细管理项目范围变更。如果有新增范围,则需要重新计划和正式确认。

2.4.2.3 迭代和增量型生命周期

随着项目团队对产品的理解程度逐渐提高,项目阶段(也称为迭代)有目的地重复一个或多个项目活动。

每次迭代中,项目团队都综合考虑反馈意见,对可交付成果进行增量修补,直到符合阶段出口标准。

2.4.2.4 适应型生命周期

适应型生命周期(也称为变更驱动方法或敏捷方法),其目的在于应对大量变更,获取干系人的持续参与。

以下情况优先选择适应型方法:

  • 需要应对快速变化的环境,需求和范围难以事先确定
  • 能够以有利于干系人的方式定义较小的增量改进
作者:diandianxiyu 发表于2017/3/20 19:49:45 原文链接
阅读:115 评论:0 查看评论

iOS遍历打印所有子视图

$
0
0

有时候搞研究啊,需要找找一个View有哪些子View,主要是分别是什么类型的,这种事情用递归来做比较好。

我稍微将这个打印做的更友好了一点,效果大致是这样的:

前面的序号表示所在的层级,同时还有一个缩进,让人对层级看得更清楚,序号后面的就是子View的类型了。

实现

其实实现起来很简单,用递归,我们通过 [UIView subviews] 方法就可以获取一个 view 的所有子view,对于每一个子view,我们又去递归调用这个方法看看他有没有子view,有就继续调用,继续对每一个子view判断,没有才往下走打印下一个同层级的子view。

这样可以保证打印出来的顺序就是每个子view下紧跟着打印他的所有子view。

至于序号、空格缩进这些,就是一些更人性化的做法了,实现起来也很简单,直接看代码:

// 递归获取子视图
- (void)getSub:(UIView *)view andLevel:(int)level {
    NSArray *subviews = [view subviews];

    // 如果没有子视图就直接返回
    if ([subviews count] == 0) return;

    for (UIView *subview in subviews) {

        // 根据层级决定前面空格个数,来缩进显示
        NSString *blank = @"";
        for (int i = 1; i < level; i++) {
            blank = [NSString stringWithFormat:@"  %@", blank];
        }

        // 打印子视图类名
        NSLog(@"%@%d: %@", blank, level, subview.class);

        // 递归获取此视图的子视图
        [self getSub:subview andLevel:(level+1)];

    }
}

我们在想知道一个view的所有子view层级的时候只需要直接调用这个方法就可以了:

// 打印所有子视图
[self getSub:self.navigationController.navigationBar andLevel:1];

需要注意的是,我的level设置是从1开始的,这与方法中加空格时变量 i 起始的值是相呼应的,要改就要都改。

这里我只打印了子view的类型,其实还可以知道它们的frame等信息,只需要在打印时将 subview.class 改成直接打印 subview 就可以了,就能得到这个 subview 的所有信息。

虽然递归打印网上的方法很多,但简单的东西也可以做的更人性化一点~


示例工程:https://github.com/Cloudox/ViewSubViewsDemo
版权所有:http://blog.csdn.net/cloudox_

作者:Cloudox_ 发表于2017/3/20 20:09:46 原文链接
阅读:68 评论:0 查看评论

Ext基础

$
0
0

本章简介

Ext JS是用于开发 RIA (富客户端)的Ajax应用,是使用JavaScript编写的、与后台技术无关的前端Ajax框架,主要用于创建前端用户界面。因此,可以将 Ext JS用于.NETJavaPHP等各种语言开发的应用中。最初,Ext JS基于YUI技术,从UI界面中 CSS样式的应用到数据解析中的异常处理,它都是一款不可多得的 JavaScript客户端技术精品。

本章将讲解Ext JS的发展及其特点,了解Ext JS的含义、熟悉 Ext JS开发环境,并在此基础上实现Ext绚丽效果。然后,详细讲解 Ext表格。在整个Ext 中,表格控件在界面和功能上都是最重要的,包括排序、缓存、拖动、隐藏列、显示行号以及编辑单元格等功能。通过Ext表格可以实现选择一条或多条记录、高亮显示选择行、显示行号、支持复选框以及支持本地和远程分页等特性。

 

核心技能部分

1.1 Ext简介

1.1.1 Ext发展史

Ext最早是在YUI库的基础上扩展开来的,因此Ext早期被称为 Yui-Ext。2005 年,Jack Slocum(杰克·洛克姆)选择YUI库作为底层库来维护一个Ajax项目,此后的一段时间他都围绕 YUI进行开发。但随着YUI越来越大、功能需求越来越多,他逐渐发现维护 YUI并不容易。在工作中,Jack Slocum又接触了 Swing—Java平台上的 UI库,并使用了极少的时间研究、改写YUI,使之呈现较先进的 Swing UI理念。这样,Jack Slocum在写技术博客的同时以 Yui-Ext的形式开放自己编写的 UI,包括 Grid、Tree等UI组件。在 Jack 的开发和社区氛围的营造下,Yui-Ext 已经成为一个成熟的 Ajax UI框架,且此框架是独立的,不受 YUI 的影响并兼容 JQuery、Prototype 等多种JS库。此时,Yui-Ext改名为 ExtJS。

2006年初,Jack Slocum为将一套公用设施扩建为 Yahoo!User Interface(YUI)库而工作。这些扩展很快组织成一个独立的库代码并以“Yui-Ext”的名义发布。2006 年秋,Jack发行Yui-Ext 0.33 版本,此版本被证明为最终版本。在2006年年底之前,该库已大受欢迎,其名称被简化为Ext,反映了该技术作为框架的成熟性和独立性。

2007 年 4月1日,Ext发布了 1.0 正式版;2007 年 2 月,Ext 获得某个新成立的公司的财务支持,增加了许多强大的功能。Ext 2.0 已经具备了很多 Swing 的特性,components、containers、layouts等概念都应用在内。Ext 2.0是一个真正成熟的框架,各方面的完善程度较高,升级到 Ext3.0 时,底层结构和配置代码均无须较大改动。Ext 3.0增加了 Ext Direct、DataWriters等强功能。

2008 年 4 月 1 日,Ext JS 已经涵盖了美国、日本、法国、德国、中国等全球范围的用户,版本为 Ext-3.O。

官方在2009 年 4月l4-16日的首次Ext 发布会中,发布了 Ext 3.0 RC版本。

 

1.1.2 Ext简介

Ext JS可以用于开发RIA (富客户端)的 Ajax应用,是使用 JavaScript编写的、与后台技术无关的前端Ajax框架,主要用于创建前端用户界面。因此,可以将 Ext JS用于.NET、Java、PHP 等各种语言开发的应用中。最初,Ext JS 基于 YUI技术,由 Jack Slocum开发。该框架参考 Java Swing等机制组织可视化组件,从UI界面中 CSS样式的应用到数据解析中的异常处理,它都是一款不可多得的 JavaScript客户端技术精品。Ext的 UI组件模型和开发理念脱胎成形于Yahoo组件库YUI和 Java平台上 Swing,并为开发者屏蔽了大量跨浏览器的处理。相对而言,Ext 比直接针对DOM、W3C对象模型开发 UI组件更为轻松。

Ext JS初期仅是对Yahoo!UI的对话框扩展,后来逐渐形成自己的特色,深受网友的喜爱。如今,除了 YUI外,Ext还支持JQuery、Prototype 等多种JS底层库,以供用户自由选择。该框架完全基于纯HTML/CSS+JS 技术,提供丰富的跨浏览器UI组件,可以灵活地采用 JSON数据源开发,真正减轻服务端表示层的负荷,从而实现客户端的 MVC应用。Ext JS支持多平台下的主流浏览器 Internet Explorer 6+、Firefox 1.5+、Safari 2+、Opera 9+。使用该技术的厂家包括IBM、Adobe、Cisco等。

JQuery、Prototype 和 YUI都属于核心的 JS 库。虽然 YUI、JQuery 各自构建了一系列 UI 器件(Widget),但没有一个真正整合良好、完整的程序开发平台。在实际开发环境中,开发者需要通过大量的工作来完善开发环境。使用 Ext可以填补这些缺陷。目前,主流开源框架中只有 DOJO与Ext在尝试提供整合的开发平台。与DOJO工具包相比,Ext可以提供粘合度更高的应用程序框架,其各个组件在设计之时就要求与其他Ext组件一起工作,进行无缝对接。这种流畅的互通性需要团队的紧密合作,并时刻强调设计和开发目标的统一。从构建每个Ext组件开始,始终都强调组件的外观、性能、互通性和可扩展性。

Ext完全可以单独使用。实际上,除了特定要求外,推荐单独使用 Ext,使文件占位更小、支持和整合更加紧密。同样,Ext 支持与 JQuery、YUI 或 Prototype整合使用,作为底层库的角色出现,提供处理各种核心的服务,如 DOM和事件处理、Ajax连接和动画特效。使用整合方式的原因之一是它们已具备了一些特定的组件,而Ext并没有原生支持。例如,YUI 的 History控件便是一个典型的应用。此时,Ext需要依赖YUI库的底层实现History控件,从而免去 Ext 自身底层库,减少整个程序的内存占用。另外,使用整合方式时,许多已在使用其他底层库的程序可以逐步加入 Ext。总之,如果程序中已经存在其他库,则 Ext可以通过利用它们为用户提供各种可能性和性能上的优化。只要实现了对应的底层库接口,可以为任意一个框架添加适配器。用户可以轻松地将 DOJO、Moo、Ajax.NET或其他JS库转变为 Ext的底层。

1.1.3 Ext类库

使用 ExtJS需要首先获得Ext JS库文件,该框架是开源的,可以直接从官方网站 http://www.sencha.com/下载


下载后的 ext-3.0.0.zip文件后解压 

2-1-1 Ext 3 的目录

名称

说明

adapter

负责将提供的第三方底层库 (包括 Ext 白带的底层库)映射为 Ext 支持的底层库

docs

API 帮助文档

exmaples

提供使用 Ext JS技术实现的实例

pkgs

新的工具包

resources

Ext UI资源文件目录,CSS、图片文件等都存放在此目录

src

无压缩 Ext 全部的源码

ext-all.js

压缩后的 Ext 全部源码

ext-all-debug.js

无压缩的 Ext 全部的源码 (用于调试)

Ext JS由一系列类库组成,一旦页面成功加载了 Ext JS库,就可以在页面中通过JavaScript调用Ext JS的类及控件实现需要的功能。

1)底层 API (core):底层API 中提供了对DOM操作、查询的封装、事件处理、DOM查询器等基础功能,如图 2.1.3 所示。

 

2.1.3    Ext底层 API

2)控件 (widgets):可以直接在页面中创建的可视化组件,如面板、选项板、表格、树、窗口、菜单、工具栏、按钮等。在应用程序中,可以直接通过应用这些控件实现友好、交互性强的应用程序的 UI

 


3)实用工具(util):Ext提供了许多的实用工具,可以方便地实现数据内容格式化、JSON数据解码反解码、对 Date 和 Array 发送 Ajax请求、Cookie 管理、CSS 管理等扩展功能

 


Ext应用需要在页面中引人Ext 的样式及 Ext库文件,样式文件为 resources/css/ext-all.css,Ext 的JS库文件主要包含 adapter/ext/ext-base.js 和 ext-all.js。其中,ext-base.js 表示框架基础库,ext-all.js是 Ext JS 的核心库。因此,使用 Ext JS框架的页面中一般包含以下代码:

<link rel="stylesheet" type="text/css" href="${ext目录}/resources/css/ext-all.css"/>

<script type="text/javascript" src="${ext目录}/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="${ext目录}/ext-all.js"></script>

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>helloworld</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

<script language="javascript">

Ext.onReady(

function(){

var win = new Ext.Window(  {title:'hello', width:200, height:200,  html:'<h1>hello my first Ext</h1>'}  );

win.show();

}

);

</script>

</head>

<body>

</body>

</html>

示例 2.1 是一个简单的Ext示例,运行结果如图 2.1.6所示。

 

2.1.6    Ext 的 hello 示例

由示例 2.1 中的 JS 代码可知,Ext JS 一般的程序入口为“Ext.onReady();”,然后可以创建 window对象。该对象中有很多属性,具体可以查看下载包中 doc文件夹下的 API。

 

Ext的样式及Ext库文件需要找到相应的文件,所以可以直接在Ext解压包examples下创建实例,或者从解压的目录中提取需要的文件到使用者的工程中。

1.1.4 Ext组件

Ext具有结构、层次分明的组件体系,这些组件形成了 Ext 的控件。Ext组件由 Component类定义,每种组件都有一个指定的 xtype 属性值,通过该值可以得到组件的类型或定义指定类型的组件。

一般而言,组件可以分为 3 类,即基本组件、工具栏组件、表单及元素组件,分别见表 2-1-2、表 2-1-3、表 2-1-4。

9-1-2  基本组件

   xtype

    Class

  解  释

   box

  Ext.BoxComponent

  具有边框属性的组件

   button

  Ext.Button

  按钮

   color palette

  Ext.ColorPalette

  调色板

   component

  Ext.Component

  组件

   container

  Ext.Container

  容器

   cycle

  Ext.CycleButton

  切换按钮

   dataview

  Ext.DataView

  数据显示视图

   datepicker

  Ext.DatePicker

  日期选择面板

   editor

  Ext.Editor

  编辑器

   editorgrid

  Ext.grid.EditorGridPanel

  可编辑的表格

   grid

  Ext.grid.GridPanel

  表格

   paging

  Ext.PagingToolbar

  工具栏中的间隔

   progress

  Ext.ProgressBar

  进度条

   splitbutton

  Ext.SplitButton

  可分裂的按钮

   tabpanel

  Ext.TabPanel

  选项面板

   treepanel

  Ext.tree.TreePanel

  树

   viewport

  Ext.ViewPort

  视图

   window

  Ext.Window

  窗口

9-1-3    工具栏组件

    xtype

    Class

   解  释

    toolbar

    Ext.Toolbar

   工具栏

    tbbutton

Ext.Toolbar.Button

   按钮

    tbfill

Ext.Toolbar.Fill

   文件

    tbitern

Ext.Toolbar.Item

   工具条项目

    tbseparator

Ext.Toolbar.Separator

   工具栏分隔符

    tbspacer

Ext.Toolbar.Spacer

   工具栏空白

    tbsplit

Ext.Toolbar.SplitButton

   工具栏分隔按钮

    tbtext

Ext.Toolbar.TextItem

   工具栏文本项

9-1-4    表单及元素组件

   xtype

    Class

  解  释

   form

    Ext.FormPanel

    Form面板

   checkbox

    Ext.form.Checkbox

    checkbox 录入框

   combo

    Ext.form.ComboBox

   Combo选择项

   datefield

    Ext.form.DateField

   日期选择项

    field

    Ext.form.Field

   表单字段

    fieldset

    Ext.form.FieldSet

   表单字段组

   hidden

    Ext.form.Hidden

   表单隐藏域

    htmleditor

    Ext.form.HtmlEditor

   html 编辑器

    numberfield

    Ext.form.NumberField

   数字编辑器

    radio

    Ext.form.Radio

   单选按钮

    textarea

    Ext.form.Text Area

   区域文本框

    textfield

    Ext.form.TextField

   表单文本框

    timefield

    Ext.form.TimeField

    时间录入项

    trigger

    Ext.form.TriggerField

    触发录入项

 

组件可以直接通过new关键字创建。例如,示例 2.1 使用 new Ext.Window 创建窗口,使用 new Ext.GridPanel()创建表格。除了一些普通的组件外,一般都会在构造函数中通过传递构造参数创建组件。组件的构造函数中一般都可以包含一个对象,该对象包含创建组件需要的配置属性及值,组件根据构造函数中的参数属性值进行初始化。

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>无标题文档</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

<script language="javascript">

Ext.onReady(

function(){

var panel = new Ext.Panel({ title:"hello", width:300, height: 150, html: "<h1>Hello</h1>" } );

panel.render("hello");

}

);

</script>

</head>

<body>

<div id="hello"></div>

</body>

</html>

示例 2.2 中使用了 Panel面板,运行结果如图2.1.7所示。

 

2.1.7    Ext 的 Panel 的构造函数

1.1.5 Ext事件

ExtJS提供了一套强大的事件处理机制,用于响应用户的动作、监控控件状态变化、更新控件视图信息、与服务器进行交互等。事件统一由 Ext.EventManager对象管理,与浏览器W3C 标准事件对象 Event对应。Ext封装了一个 Ext.EventObject事件对象。支持事件处理的类或接口为 Ext.util.Observable,凡是继承该类的组件或类都支持向对象中添加事件处理及响应功能。

某按钮的点击事件代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>无标题文档</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

<script language="javascript">

Ext.onReady(function(){

Ext.get('myButton').on('click',function(){

alert('你点击到我了');

});

});

</script>

</head>

<body>

<input type="button" id="myButton" value="myButton"/>

</body>

</html>

 

1.2 Ext表格控件 Grid

1.2.1 Grid特性

Ext的表格功能非常强大,包括排序、缓存、拖动、隐藏列、显示行号以及编辑单元格等。表格由类 Ext.grid.GridPanel定义,它继承自 Panel。在 Ext 中,Grid控件和其他显示数据的控件能够支持多种数据类型 (二维数组、JSON数据和 XML数据等)甚至自定义的数据类型。Ext提供了一个桥梁 Ext.data.Store,通过它可以将任何格式的数据转化成 Grid能够使用的形式,不需要为每种数据格式编写一个 Grid 的实现。另外,表格控件Grid还必须包括列定义信息,表格的列信息由类Ext.grid.ColumnModel定义,而表格的数据存储器由 Ext.data.Store定义,数据存储器根据解析的数据不同分为 JsonStore、SimpleStore、GroupingStore等。

Ext Grid的功能包括选择一条或多条记录、高亮显示选择行、调整列宽、显示行号、支持复选框以及支持本地和远程分页。另外,Grid可以编辑表格、添加行、删除一行或多行、拖动改变表格大小,这些功能都在Ext表格控件中实现。

1.2.2 简单的 Grid

查看 Ext解压包的 examples 目录中的示例制作 Grid,加深对 Grid 的了解。

(1)表格是二维表格,与设计数据库的表相同,需要首先设置表的列数、列名、列的类型及显示方式,搭建表格框架。Grid的结构和数据库中的表非常相似。

2)在Ext 中,列的定义称为 ColumnModel,简称 cm。作为整个表格的列模型,列必须首先建立。创建一个 6列的 Grid,按顺序分别为编号(empId)、姓名(userName)、性别 (sex)、出生日期(birthday)、地址(address)和备注(remark),代码如下:

var cm = new Ext.grid.ColumnModel( [

{header:'编号', dataIndex:'empId'},

{header:'姓名', dataIndex:'empName'},

{header:'性别', dataIndex:'sex'},

{header:'出生日期', dataIndex:'birthday'},

{header:'地址', dataIndex:'address'},

{header:'备注', dataIndex:'remark'}

]);

上述代码中,var cm = new Ext.grid.ColumnModel()用于创建表格列信息。表格包含的列由 columns配置,每列的header表示该列的名称,dataIndex表示列对应的记录集字段。另外,sortable表示是否可以排序,renderer表示列的渲染函数,width表示宽度,format表示格式化信息等。

定义表格的结构后,就可以向其中添加数据。此处,数据也是二维的。直接添加静态数据的代码如下:

var data = [

['0001', '张三', 'boy', '9/1 12:00am', '建设路', '0001remark'],

['0002', '李四', 'boy', '9/1 12:00am', '人民路', '0002remark'],

['0003', '王五', 'boy', '9/1 12:00am', '大学路', '0003remark'],

['0004', '赵六', 'girl', '9/1 12:00am', '南京路', '0004remark']

];

上述代码中,“var data =…”用于定义表格中的数据,共包含4条记录,是一个二维数组,在页面上显示为4行,每行6列,分别对应 empId、userName、sex、birthday、address 和 remark。另外,在页面上显示这些数据时需要对原始数据进行转换,代码如下:

var store = new Ext.data.Store({

proxy:new Ext.data.MemoryProxy(data),

reader:new Ext.data.ArrayReader({},[

{name:'empId'},

{name:'empName'},

{name:'sex'},

{name:'birthday'},

{name:'address'},

{name:'remark'}

])

});

上述代码中,“var store = new Ext.data.Store()” 用于创建数据的存储对象,负责将各种原始数据(如二维数组、JSON对象数组、文本等) 转换成Grid可以使用的形式,避免为每种数据格式都编写对应的实现。此外,store包含 proxy和reader两个部分,前者指获取数据的方式,后者指解析数据的方式。

Ext.data.MemoryProxy用于解析JavaScript变量,只要将已定义的 data作为参数传入即可。Ext.data.ArrayReader用于解析数组,说明数组将按照定义的规范进行解析。

上述代码定义了名称 empId、userName、sex、birthday、address 和 remark,与表格 cm 的 dataIndex一一对应。

 

    为了使数据可以显示,需要通过“store.load();”对数据进行初始化。

定义列模型并完成原始数据和数据转换后,可以进行装配。创建Grid,代码如下:

var grid = new Ext.grid.GridPanel({

store:store,

height:350,

width:700,

cm:cm

});

创建了 Grid之后,需要使用 grid.render()方法使Grid开始渲染,才能显示数据。完整的 Grid实例代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>表格</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

</head>

<body>

<div id="gridCm" style="height:300px;"></div>

 

<script type="text/javascript">

var cm = new Ext.grid.ColumnModel( [

{header:'编号', dataIndex:'empId'},

{header:'姓名', dataIndex:'empName'},

{header:'性别', dataIndex:'sex'},

{header:'出生日期', dataIndex:'birthday'},

{header:'地址', dataIndex:'address'},

{header:'备注', dataIndex:'remark'}

]);

var data = [

['0001', '张三', 'boy', '9/1 12:00am', '建设路', '0001remark'],

['0002', '李四', 'boy', '9/1 12:00am', '人民路', '0002remark'],

['0003', '王五', 'boy', '9/1 12:00am', '大学路', '0003remark'],

['0004', '赵六', 'girl', '9/1 12:00am', '南京路', '0004remark']

];

var store = new Ext.data.Store({

proxy:new Ext.data.MemoryProxy(data),

reader:new Ext.data.ArrayReader({},[

{name:'empId'},

{name:'empName'},

{name:'sex'},

{name:'birthday'},

{name:'address'},

{name:'remark'}

])

});

var grid = new Ext.grid.GridPanel({

store:store,

height:350,

width:700,

cm:cm

});

store.load();

grid.render('gridCm');

</script>

</body>

</html>


1.2.3 Grid 常用功能

2.2.2小节中演示了如何创建简单的 Grid表格,本节将对该Grid进行完善。

1. 互换列位置

互换姓名和性别的位置,最直接的方法是互换两列的所有信息,但此操作比较繁琐。使用 Ext.data.AnayReader解析数组时,可以使用 mapping指定列的位置,代码变化如下:

var store = new Ext.data.Store({

proxy:new Ext.data.MemoryProxy(data),

reader:new Ext.data.ArrayReader({},[

{name:'empId',mapping:0},

{name:'empName',mapping:2},

{name:'sex',mapping:1},

{name:'birthday',mapping:3},

{name:'address',mapping:4},

{name:'remark',mapping:5}

])

});


 

mapping的索引号从0开始。

2. 自定义列宽

2.2.2 小节的 Grid 中,所有的列宽都相同。当列不够宽时,用户必须手动调整其宽度。cm支持设置列宽,不设置时会取默认的列宽 lOOpx。

var cm = new Ext.grid.ColumnModel( [

{header:'编号', dataIndex:'empId',width:40}, //指定列宽

{header:'姓名', dataIndex:'empName',width:60},

{header:'性别', dataIndex:'sex', width:40},

{header:'出生日期', dataIndex:'birthday', width:120},

{header:'地址', dataIndex:'address', width:200},

{header:'备注', dataIndex:'remark', width:200}

]);

上述代码对列宽进行了适当调整,运行效果如图 2.1.11 所示。

 


使用这种方式必须在每次应用时都计算列宽,依然比较繁琐。程序需要使每列自动填满 Grid,以减少工作量。通过viewConfig的 forceFit进行配置,可以重新计算所有列宽后填充Grid表格,代码如下:

viewConfig:{forceFit:true}  //自适应列宽



3. 支持按列排序

JSP 中,实现排序比较复杂;而在Ext中,只要添加 sortable的属性,就可以方便地进行排序。

var cm = new Ext.grid.ColumnModel( [

{header:'编号', dataIndex:'empId',sortable:true}, //指定列宽,排序

{header:'姓名', dataIndex:'empName',sortable:true},

{header:'性别', dataIndex:'sex',sortable:true},

{header:'出生日期', dataIndex:'birthday',sortable:true},

{header:'地址', dataIndex:'address', sortable:true},

{header:'备注', dataIndex:'remark', sortable:true}

]);


当为列标题添加的 sortable 属性为 true 时,标题上会出现一个向上或向下的小箭头,分别表示按标题的升序或者降序排列。

标题的右侧有一个可下拉的、类似于Extl.x 的右键功能菜单

除了可以按照升序或降序排序外,此功能菜单还可以隐藏或显示列。

4. 格式化数据

表格中的“出生日期”的值没有经过格式化,所以并不直观。在实际显示时,需要对特定列的数据进行格式化,步骤如下:

1)确定“出生日期”属于日期格式的数据。

2)在 reader 中增加配置,除了设置name属性外,还需要设置type 和 dateFormat属性。其中,type说明解析时将该列作为何种类型处理,dateFormat说明将字符串转换成相应的日期格式。在Ext 中,日期格式有相应的约定:Y表示年、m表示月、d表示日期、H表示小时、i表示分钟、S表示秒。改动后的代码如下:

var cm = new Ext.grid.ColumnModel( [

{header:'编号', dataIndex:'empId',sortable:true}, //指定列宽,排序

{header:'姓名', dataIndex:'empName',sortable:true},

{header:'性别', dataIndex:'sex',sortable:true},

{header:'出生日期', dataIndex:'birthday',renderer:Ext.util.Format.dateRenderer('Y-m-d H:i:s')},

{header:'地址', dataIndex:'address', sortable:true},

{header:'备注', dataIndex:'remark', sortable:true}

]);

运行上述代码,查看运行结果,如图 2.1.17所示。

 

2.1.17    日期格式化

5. 自动显示行号

Ext 中,自动显示行号非常简单,只要在cm中添加RowNumberer对象即可。

var cm = new Ext.grid.ColumnModel( [

new Ext.grid.RowNumberer(), //自动显示行号

{header:'编号', dataIndex:'empId',sortable:true},

{header:'姓名', dataIndex:'empName',sortable:true},

{header:'性别', dataIndex:'sex',sortable:true},

{header:'出生日期', dataIndex:'birthday',sortable:true,

renderer:Ext.util.Format.dateRenderer('Y-m-d H:i:s')},//格式化

{header:'地址', dataIndex:'address', sortable:true},

{header:'备注', dataIndex:'remark', sortable:true}

]);


6. 复选框

Ext的复选框通过CheckboxSelectionModel对象实现,它在每行数据前添加一个复选框。

1)创建sm,代码如下

var sm = new Ext.grid.CheckboxSelectionModel();

2)将 sm放入cm和 grid中,代码如下:

var cm = new Ext.grid.ColumnModel( [

new Ext.grid.RowNumberer(), //自动显示行号

sm,//添加复选框

{header:'编号', dataIndex:'empId',sortable:true},

{header:'姓名', dataIndex:'empName',sortable:true},

{header:'性别', dataIndex:'sex',sortable:true},

{header:'出生日期', dataIndex:'birthday',sortable:true,

renderer:Ext.util.Format.dateRenderer('Y-m-d H:i:s')},//格式化

{header:'地址', dataIndex:'address', sortable:true},

{header:'备注', dataIndex:'remark', sortable:true}

]);



7. 改变字体颜色、添加图片

在定义列的时候可以指定该列的渲染函数,在函数里可以设置字体颜色、添加图片。

var cm = new Ext.grid.ColumnModel( [

{header:'编号', dataIndex:'empId',width:60}, //指定列宽

{header:'姓名', dataIndex:'empName',width:60},

{header:'性别', dataIndex:'sex', width:40,renderer:renderSex},

{header:'出生日期', dataIndex:'birthday', width:120},

{header:'地址', dataIndex:'address', width:200},

{header:'备注', dataIndex:'remark', width:200}

]);

function renderSex(value)

{

if(value == 'male')

return "<span style='color:red;font-weight:bold;'>红男</span><img src='m.gif'/>";

else

return "<span style='color:green;font-weight:bold;'>绿女</span><img src='m.gif'/>";

}

 

 

本章总结

Ø Ext JS是用于开发 RIA (富客户端)的Ajax应用,是使用JavaScript编写的、与后台技术无关的前端Ajax框架,主要用于创建前端用户界面。

Ø Ext应用需要在页面中引人Ext 的样式及 Ext库文件。

样式文件为 resources/css/ext-all.css

n Ext JS库文件主要包含 adapter/ext/ext-base.js ext-all.js。其中,ext-base.js 表示框架基础库,ext-all.jsExt JS 的核心库。

Ø ExtJS组件可以分为 3 类,即基本组件、工具栏组件、表单及元素组件。

Ø Ext组件由 Component类定义,每种组件都有一个指定的 xtype 属性值,通过该值可以得到组件的类型或定义指定类型的组件。

Ø 事件统一由 Ext.EventManager对象管理,与浏览器W3C 标准事件对象 Event对应。Ext封装了一个 Ext.EventObject事件对象。

Ø Ext的表格功能非常强大,包括排序、缓存、拖动、隐藏列、显示行号以及编辑单元格等。表格由类 Ext.grid.GridPanel定义,它继承自 Panel。

Ext中,Grid控件和其他显示数据的控件能够支持多种数据类型 (二维数组、JSON数据和 XML数据等)甚至自定义的数据类型。而表格的数据存储器由 Ext.data.Store定义,数据存储器根据解析的数据不同分为 JsonStore、SimpleStore、GroupingStore等。

另外,表格控件Grid还必须包括列定义信息,表格的列信息由类Ext.grid.ColumnModel定义。

 

 

任务实训部分

1Ext Grid 控件的显示功能

训练技能点

Ø 使用 Ext Grid 控件显示后台 Servlet 查询的数据

需求说明

(1) 使用 Servlet 查询数据。

(2) 使用 Ext Grid 显示后台 Servlet 查询的数据。

 

实现步骤

(1) 设计数据库表及字段。

(2) 使用 Servlet 查询订单数据。

(3) 使用 Ext Grid 控件显示查询数据。

参考代码

创建数据库表、添加数据的代码:

-- ----------------------------

-- Table structure for pro_order

-- ----------------------------

DROP TABLE IF EXISTS `pro_order`;

CREATE TABLE `pro_order` (

  `order_id` int(11) NOT NULL AUTO_INCREMENT,

  `order_no` varchar(20) DEFAULT NULL,

  `price` float DEFAULT NULL,

  `create_date` varchar(20) DEFAULT NULL,

  PRIMARY KEY (`order_id`)

) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;

 

-- ----------------------------

-- Records

-- ----------------------------

INSERT INTO `pro_order` VALUES ('1', '0001', '2000', '2011-01-01');

INSERT INTO `pro_order` VALUES ('2', '0002', '200', '2011-01-01');

INSERT INTO `pro_order` VALUES ('3', '0003', '3000', '2011-01-01');

INSERT INTO `pro_order` VALUES ('4', '0004', '50', '2011-01-01');

INSERT INTO `pro_order` VALUES ('5', '0005', '30', '2011-01-01');

INSERT INTO `pro_order` VALUES ('6', '0006', '3000', '2011-01-01');

INSERT INTO `pro_order` VALUES ('7', '0007', '34', '2011-01-01');

INSERT INTO `pro_order` VALUES ('8', '0008', '57', '2011-01-01');

INSERT INTO `pro_order` VALUES ('9', '0009', '300', '2011-01-05');

INSERT INTO `pro_order` VALUES ('10', '0010', '80', '2011-01-05');

INSERT INTO `pro_order` VALUES ('11', '0011', '90', '2011-01-05');

INSERT INTO `pro_order` VALUES ('12', '0012', '3090', '2011-01-05');

 

数据库连接类:

public class DBUtil {

public static Connection getCon(){

Connection conn=null;

String url="jdbc:mysql:///test";

String userName="root";

String userPwd="admin";

try {

conn=DriverManager.getConnection(url, userName, userPwd);

} catch (Exception e) {

e.printStackTrace();

}

return conn;

}

public static void closeDB(Connection conn,Statement stmt,PreparedStatement pstmt,ResultSet rs){

try {

if (rs!=null) {

rs.close();

}

if (pstmt!=null) {

pstmt.close();

}

if (stmt!=null) {

stmt.close();

}

if (conn!=null) {

conn.close();

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

查询订单的Servlet 方法:

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html;charset=gbk");

response.setCharacterEncoding("gbk");

request.setCharacterEncoding("gbk");

PrintWriter out = response.getWriter();

Connection conn=null;

Statement stmt=null;

PreparedStatement pstmt=null;

ResultSet rs=null;

String hqlSql="select count(*) from pro_order";

String sql="select * from pro_order";

String json="";

int totalOrder=0;

try {

conn=DBUtil.getCon();

stmt=conn.createStatement();

rs=stmt.executeQuery(hqlSql);

while (rs.next()) {

totalOrder=rs.getInt(1);

}

json="{totalProperty:"+totalOrder+",root:[";

rs=stmt.executeQuery(sql);

while (rs.next()) {

json+="{orderNo:'"+rs.getString("order_no")+"',price:'"+rs.getString("price")+

"',createDate:'"+rs.getString("create_date")+"'},";

}

} catch (Exception e) {

e.printStackTrace();

}finally{

DBUtil.closeDB(conn, stmt, pstmt, rs);

}

json=json.substring(0,json.length()-1);

json+="]}";

System.out.println(111);

out.write(json.toString());

}

查询构造的JSON格式数据:

root:[

{orderNo:'0001',price:'2000',createDate:'2011-01-01'},

{orderNo:'0002',price:'200',createDate:'2011-01-01'},

{orderNo:'0003',price:'3000',createDate:'2011-01-01'},

{orderNo:'0004',price:'50',createDate:'2011-01-01'},

{orderNo:'0005',price:'30',createDate:'2011-01-01'},

{orderNo:'0006',price:'3000',createDate:'2011-01-01'},

{orderNo:'0007',price:'34',createDate:'2011-01-01'},

{orderNo:'0008',price:'57',createDate:'2011-01-01'},

{orderNo:'0009',price:'300',createDate:'2011-01-05'},

{orderNo:'0010',price:'80',createDate:'2011-01-05'},

{orderNo:'0011',price:'90',createDate:'2011-01-05'},

{orderNo:'0012',price:'3090',createDate:'2011-01-05'}

]

使用Ext 表格控件显示数据:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>proOrderList</title>

    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

    <meta http-equiv="description" content="this is my page">

    <meta http-equiv="content-type" content="text/html; charset=gbk">

    <!-- 第一步引入extjs的样式文件 -->

    <link rel="stylesheet" type="text/css" href="ext-3.3.1/resources/css/ext-all.css">

    <!-- 第二步引入extjs的库文件,底层驱动 -->

    <script type="text/javascript" src="ext-3.3.1/adapter/ext/ext-base.js"></script>

    <script type="text/javascript" src="ext-3.3.1/ext-all.js"></script>

    <script type="text/javascript" src="proOrderList.js"></script>

  </head>

  

<body>

    <div id="grid"></div>

    <script type="text/javascript">

     Ext.onReady(function() {

var cm = new Ext.grid.ColumnModel([

{header : "订单编号",dataIndex : 'orderNo'},

{header : "订单价格",dataIndex : 'price' },

{header : "创建日期",dataIndex : 'createDate'}]);

var store=new Ext.data.Store({

proxy:new Ext.data.HttpProxy({url:'Pro_orderServlet'}),

reader:new Ext.data.JsonReader({totalProperty:'totalProperty',root:'root'},

[{name:'orderNo'},{name:'price'},{name:'createDate'}])

});

var grid=new Ext.grid.EditorGridPanel({

renderTo:'grid',

store:store,

cm:cm,

loadMask:true,

width:600,

height:300

});

store.load({params:{start:0,limit:10}});

});

    </script>

  </body>

</html>

2Ext Grid 控件的分页功能

训练技能点

Ø 使用 Ext Grid 控件分页功能

需求说明

在完成上一任务显示功能的基础上,使用Ext Grid 控件实现数据分页,效果如图9.2.2所示。

 

2.2.2 分页显示订单

实现步骤

(1) 设计数据库表及字段。

(2) 使用 Servlet 查询订单数据。

(3) 使用 Ext Grid 控件分页显示查询数据。

参考代码

查询订单的Servlet 方法:

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html;charset=gbk");

response.setCharacterEncoding("gbk");

request.setCharacterEncoding("gbk");

PrintWriter out = response.getWriter();

//分页

String start = request.getParameter("start");

String limit = request.getParameter("limit");

Connection conn=null;

Statement stmt=null;

PreparedStatement pstmt=null;

ResultSet rs=null;

String hqlSql="select count(*) from pro_order";

String sql="select * from pro_order limit "+start + "," + limit;

String json="";

int totalOrder=0;

try {

conn=DBUtil.getCon();

stmt=conn.createStatement();

rs=stmt.executeQuery(hqlSql);

while (rs.next()) {

totalOrder=rs.getInt(1);

}

json="{totalProperty:"+totalOrder+",root:[";

rs=stmt.executeQuery(sql);

while (rs.next()) {

json+="{orderNo:'"+rs.getString("order_no")+"',price:'"+rs.getString("price")+

"',createDate:'"+rs.getString("create_date")+"'},";

}

} catch (Exception e) {

e.printStackTrace();

}finally{

DBUtil.closeDB(conn, stmt, pstmt, rs);

}

json=json.substring(0,json.length()-1);

json+="]}";

out.write(json.toString());

}

使用Ext Grid 控件分页显示:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<html>

  <head>

    <title>分页显示</title>

    <!-- 第一步引入extjs的样式文件 -->

    <link rel="stylesheet" type="text/css" href="ext-3.3.1/resources/css/ext-all.css">

    <!-- 第二步引入extjs的库文件,底层驱动 -->

    <script type="text/javascript" src="ext-3.3.1/adapter/ext/ext-base.js"></script>

    <script type="text/javascript" src="ext-3.3.1/ext-all.js"></script>

  </head>

  <body>

    <div id="grid"></div>

  </body>

  <script type="text/javascript">

    Ext.onReady(

       function(){

         var cm = new Ext.grid.ColumnModel([

           {header:'订单Id',dataIndex:'orderId',hidden:true},

           {header:'订单编号',dataIndex:'orderNo'},

           {header:'订单价格',dataIndex:'price',editable:true},

           {header:'创建日期',dataIndex:'createDate'}

         ]);

          //存储器

         var store=new Ext.data.Store({

  proxy:new Ext.data.HttpProxy({url:"Pro_orderServlet"}),

reader:new Ext.data.JsonReader({totalProperty:'totalProperty',root:'root'},

[{name:'orderNo'},{name:'price'},{name:'createDate'}])

});

         var grid=new Ext.grid.EditorGridPanel({

           renderTo:'grid',

           store:store,

           cm:cm,

           loadMask:true,

            width:600,

            height:300,

            bbar:new Ext.PagingToolbar({

              pageSize:3,

              store:store,

              displayInfo:true,

              displayMsg:'显示第{0}{1},一共有{2}',

              emptyMsg:'没有记录'

            })

         });

           //加载存储器

         store.load({params:{start:0,limit:3}});        

       }

    );

 </script>

</html>

 

3Ext Grid 控件的扩展功能

需求说明

在任务2的基础上,添加以下功能。

1)将分页工具栏放在面板的上方,效果如图9.2.3所示。

 

如图2.2.3 分页工具栏放在面板的上方

提示:tbar:new Ext.PagingToolbar...

2)添加自动行号,效果如图2.2.4所示。

 

图9.2.4添加自动行号

3)添加多选,效果如图2.2.5所示。

 

图2.2.5添加多选

4)添加排序,效果如图2.2.6所示。

 

图2.2.6 按订单编号降序排列

4Ext Grid 控件的删除功能

训练技能点

Ø 使用 Ext Grid 控件实现删除

需求说明

(1) 在上一任务的基础上,完成删除订单信息。

(2) 删除订单记录的提示信息,如图2.2.7所示。

 

2.2.7 删除订单的提示对话框

(3) 删除后,效果如图2.2.8所示

 

2.2.8 删除后的结果

实现步骤

(1) 设计数据库表及字段。

(2) 使用Servlet查询订单信息、删除订单信息。

(3) 使用Ext Grid 分页显示Servlet查询数据。

(4) 使用Ext删除记录。

参考代码

HTML页面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<html>

  <head>

    <title>My JSP 'index.jsp' starting page</title>

<!-- 第一步引入extjs的样式文件 -->

    <link rel="stylesheet" type="text/css" href="ext-3.3.1/resources/css/ext-all.css">

    <!-- 第二步引入extjs的库文件,底层驱动 -->

    <script type="text/javascript" src="ext-3.3.1/adapter/ext/ext-base.js"></script>

    <script type="text/javascript" src="ext-3.3.1/ext-all.js"></script>

  </head>

  <body>

    <div id="grid"></div>

  </body>

  <script type="text/javascript">

 Ext.onReady(function() {

var sm = new Ext.grid.CheckboxSelectionModel();

//定义列

var cm = new Ext.grid.ColumnModel( [ new Ext.grid.RowNumberer, sm, {

header : '订单Id',

dataIndex : 'orderId',

hidden : true

}, {

header : '订单编号',

dataIndex : 'orderNo'

}, {

header : '订单价格',

dataIndex : 'price',

editable : true

}, {

header : '创建日期',

dataIndex : 'createDate'

} ]);

//定义存储器

var store = new Ext.data.Store( {

proxy : new Ext.data.HttpProxy( {

url : "servlet/GridServlet"

}),

reader : new Ext.data.JsonReader( {

totalProperty : 'totalProperty',

root : 'root'

}, [ {

name : 'orderId'

}, {

name : 'orderNo'

}, {

name : 'price'

}, {

name : 'createDate'

} ])

});

//创建表格  

var grid = new Ext.grid.EditorGridPanel( {

renderTo : 'grid',

store : store,

cm : cm,

sm : sm,

loadMask : true,

width : 600,

height : 150,

bbar : new Ext.PagingToolbar( {

pageSize : 3,

store : store,

displayInfo : true,

displayMsg : '显示第{0}{1},一共有{2}',

emptyMsg : '没有记录',

items : [ {

text : '添加',

pressed : false

}, {

text : '删除',

pressed : false,

handler : doDelete

} ]

})

});

//加载存储器

store.load( {

params : {

start : 0,

limit : 3

}

});

//批量删除开始

function doDelete() {

var array = new Array();

var strid = "";

array = sm.getSelections();//被选中的记录存储为Record对象,用其get("")方法取值

if (array.length == 0) {

Ext.MessageBox.alert("错误", "没有选择数据");

} else {

Ext.MessageBox.confirm('温馨提示', '你确定要删除吗?', function(btn) {

if (btn == "yes") {

for ( var i = 0; i < array.length; i++) {

store.remove(array[i]);

//获取记录中的orderId

strid += array[i].get("orderId") + ",";

}

//数据库中删除

//创建request对象

Ext.lib.Ajax.request('GET','servlet/DelSevrvlet?strid='+strid,

{

success : function(response) {

Ext.MessageBox.alert('消息','删除成功',function() {

grid.getStore().reload();

});

},

failure : function(form,action) {

Ext.MessageBox.alert('消息', '删除失败!');

}

}, null);

}

})

}

}

});

</script>

</html>

删除Servlet代码:

@Override

protected void service(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

 response.setContentType("text/html;charset=gbk;");

 //获得删除的id

 String json = request.getParameter("strid");

 String[] p = json.split(",");//获得orderId数组

 String orderId = "";

 //循环给orderId赋值

 for(String i:p){

 orderId+=i+",";

 }

 int index = orderId.lastIndexOf(",");

 orderId=orderId.substring(0,index);

 

 Connection  conn = null;

 Statement stmt = null;

 PreparedStatement  pstmt=null;

 String sql = "delete from pro_order where order_id in ("+orderId+")" ;

 System.out.println(sql);

 try {

conn = DBConnection.getConn();

 stmt = conn.createStatement();

 stmt.executeUpdate(sql);

} catch (SQLException e) {

e.printStackTrace();

}finally{

DBConnection.closeDB(conn, stmt, pstmt, null);

}

request.getRequestDispatcher("GridServlet").forward(request, response);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

巩固练习

 

一、选择题

1. Ext JS提供了一套强大的事件处理机制,通过这些事件处理机制可以实现的功能是(  )

    A. 响应用户的动作

    B. 监控控件状态变化

    C. 更新控件视图信息

    D. 与服务器进行交互

2. Ext JS组件分类不包括(  )

    A. 基本组件

    B. 工具栏组件

    C. 菜单组件

    D. 表单及元素组件

3. Ext组件可以分为(  )

    A. 基本组件

    B. 工具栏组件

    C. 扩展组件

    D. 表单及元素组件

4. 在Ext组件中,window属于(  )组件。

    A. 基本组件

    B. 工具栏组件

    C. 扩展组件

D. 表单及元素组件

5. Ext表格有( )类实现。

A. Ext.grid.GridPanel

B. Ext.table.Table

C. Ext.GridPanel

D. Ext.Panel

二、简答题

1. 什么是 Ext JS?

2. Ext JS组件包括哪些?

三、操作题

使用Ext JS 的 Grid控件查询学校学生信息,实现选择一条或多条记录、高亮显示选择行、调整列宽、显示行号、支持复选框功能。

作者:zhangchen124 发表于2017/3/20 21:02:36 原文链接
阅读:66 评论:0 查看评论

Leetcode 212 Word Search II 字典树 + 回溯

$
0
0

Given a 2D board and a list of words from the dictionary, find all words in the board.

Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.

For example,
Given words = ["oath","pea","eat","rain"] and board =

[
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]
Return ["eat","oath"].

Note:
You may assume that all inputs are consist of lowercase letters a-z.

给一个矩阵,可以从任意一个位置开始,沿水平或垂直方向取连续字符组成字符串,问给定的字符串数组中有多少字符串可以从这个矩阵中生成。

直接套用之前trie的代码。

枚举每一个位置为起点进行dfs,dfs向四个方向搜索,如果当前位置的串不为树中某个词的前缀,则返回,否则看当前串是否为一个存在的单词并继续搜索。

需要注意用一个map维护出现过的单词,避免相同词重复加入结果容器。

同一个位置的字符在一个单词中只能使用一次,因此需要将搜索过的位置置为其他不为字母的字符,并在回溯时调整回来。

class node    
{    
public:    
    int flag;    
    node* next[26];    
    node(int x = 0)    
    {    
        flag = x;    
        memset(next, 0, sizeof(next));    
    }    
};    
class WordDictionary {  
public:  
    node* root;  
    /** Initialize your data structure here. */  
    WordDictionary() {  
        root = new node();  
    }  
    /** Adds a word into the data structure. */  
    void addWord(string word) {  
        //cout<<word<<endl;
        node* p = root;    
        for(int i = 0; i < word.size(); i++)    
        {    
            if(!p->next[word[i] - 'a']) p->next[word[i] - 'a'] = new node();    
            p = p->next[word[i] - 'a'];    
        }    
        p->flag = 1;   
    }
    /** Returns if the word is in the trie. */  
    bool search(string word)   
    {  
        node* p = root;  
        for(int i = 0; i < word.size(); i++)  
        {  
            if(!p->next[word[i] - 'a']) return false;  
            p = p->next[word[i] - 'a'];  
        }  
        return p->flag == 1;  
    }  
    /** Returns if there is any word in the trie that starts with the given prefix. */  
    bool startsWith(string prefix)   
    {  
        node* p = root;  
        for(int i = 0; i < prefix.size(); i++)  
        {  
            if(!p->next[prefix[i] - 'a']) return false;  
            p = p->next[prefix[i] - 'a'];  
        }  
        return true;  
    }  
};  
class Solution {
public:
    WordDictionary tree;
    unordered_map<string, bool> mp;
    void dfs(vector<string> &res, vector<vector<char>>& board, int i,int j, string now)
    {
        if(board[i][j] == ' ') return ;
        now += board[i][j];
        if(!tree.startsWith(now)) return ;
        if(tree.search(now) && !mp[now]) 
        {
            mp[now] = true;
            res.push_back(now);
        }
        char temp = board[i][j];
        board[i][j] = ' ';
        if(i < board.size() - 1) dfs(res, board, i + 1, j, now);
        if(i > 0) dfs(res, board, i - 1, j, now);
        if(j < board[0].size() - 1) dfs(res, board, i, j + 1, now);
        if(j > 0) dfs(res, board, i, j - 1, now);
        board[i][j] = temp;
    }
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        vector<string> res;
        int m = board.size();
        if(m == 0) return res;
        int n = board[0].size();
        for(int i = 0; i < words.size(); i++) tree.addWord(words[i]);
        for(int i = 0; i < m; i++)
        {
            for(int j = 0; j < n; j++)
            {
                string temp;
                dfs(res, board, i, j, temp);
            }
        }
        return res;
    }
};


作者:u012614906 发表于2017/3/20 21:33:43 原文链接
阅读:57 评论:0 查看评论

[时间序列分析][1]--平稳性,白噪声的检验

$
0
0
[时间序列分析][1]--平稳性,白噪声的检验

  这是一个全新的专题,讲关于时间序列分析的。还是老规矩,我使用mathematica来实现。
 
  我个人认为时间序列分析是一门挺重要的科目,如果做建模什么的一定是知道的,或者处理数据的时候,很多数据都是和时间有关的,所以时间序列还是很值得学习的。
 
  这次我申请了一个专栏,我会把文章放在专栏里。截一张图,做一个纪念。
 
  最近还在考虑是否要做一个微信公众号,因为用手机看csdn的博客效果不是很好。
  当然,这些都是之后要考虑的。这一篇文章我们就先来讲一下时间序列的知识。
 
  做时间序列分析,之前需要做两个准备工作,即检查序列是否是平稳的,如果是平稳的,还要检查是否是白噪声。我们一个一个来讲。

  我们用一个例子来说明:数据集是49 - 98 北京最高气温,数据如下:
{{1949., 38.8}, {1950., 35.6}, {1951., 38.3}, {1952., 39.6}, {1953., 
  37.}, {1954., 33.4}, {1955., 39.6}, {1956., 34.6}, {1957., 
  36.2}, {1958., 37.6}, {1959., 36.8}, {1960., 38.1}, {1961., 
  40.6}, {1962., 37.1}, {1963., 39.}, {1964., 37.5}, {1965., 
  38.5}, {1966., 37.5}, {1967., 35.8}, {1968., 40.1}, {1969., 
  35.9}, {1970., 35.3}, {1971., 35.2}, {1972., 39.5}, {1973., 
  37.5}, {1974., 35.8}, {1975., 38.4}, {1976., 35.}, {1977., 
  34.1}, {1978., 37.5}, {1979., 35.9}, {1980., 35.1}, {1981., 
  38.1}, {1982., 37.3}, {1983., 37.2}, {1984., 36.1}, {1985., 
  35.1}, {1986., 38.5}, {1987., 36.1}, {1988., 38.1}, {1989., 
  35.8}, {1990., 37.5}, {1991., 35.7}, {1992., 37.5}, {1993., 
  35.8}, {1994., 37.2}, {1995., 35.}, {1996., 36.}, {1997., 
  38.2}, {1998., 37.2}}

一.
画出散点图
首先我们画出散点图,先从总体上看一下数据
ListLinePlot[data, PlotStyle -> Dashed, PlotMarkers -> {"o", 8}]


  二.
  平稳性的检验

  方法:平稳性检验一般可以从时序图上看或者通过相关性的图中看出。
  我们这里讲一下相关图的方法。
  原理:平稳序列通常具有短期相关性。该性质用自相关系数来描述就是随着延迟期数的增加,平稳序列的自相关系数会很快的衰减到0
  特别,关于延迟的相关系数的计算公式如下
 
  在mathematica里使用的函数是CorrelationFunction[],具体代码如下
ListPlot[
   CorrelationFunction[data[[All, 2]], {20}], 
   PlotMarkers -> {Automatic, Medium}, Filling -> Axis, 
  FillingStyle -> Directive[Thickness[.01], Green, Dashed], 
  PlotRange -> All
]

可以看到相关系数迅速衰减到0,说明该序列是平稳的。

三.
判断数据是否是白噪声

如果一个序列是平稳的,那么下面我们就要判断数据是否是白噪声,白噪声没有研究的意义。
在mathematica中,判断白噪声使用AutocorrelationTest[],这个函数
这个函数必须要说明一下,首先他的原理是bartlett定理

下面对于AutocorrelationTest[]这个函数的使用进行说明,如下图:


就是她返回的是一个p值,p值越大表示原假设成立的可能性越大,即数据是随机的可能性越大。
即p值越大,随机的可能性越大
ListPlot[Table[AutocorrelationTest[data[[All, 2]], i], {i, 1, 10}], Filling -> Axis]
我们可以画出关于滞后数的图


我们可以看到p值还是挺大的,所以认为该数据是白噪声。
我们还有一些其他的检验方法,如下图
AutocorrelationTest[data, Automatic, "HypothesisTestData"]["TestDataTable", All]

也可以使用下图的方式

以上就把白噪声的检验做完了。

到这里就把时间序列的第一节,平稳性和白噪声检验讲完了。
大家有什么问题可以发邮件给我,我的邮箱是wangmaonan@bupt.edu.cn

以上,所有
2017/3/20
作者:WMN7Q 发表于2017/3/20 21:50:02 原文链接
阅读:50 评论:0 查看评论

网游通讯传输可变长度的数值和数组

$
0
0

何为可变长度的数值(int,long等)

其实现在大部分网络游戏(端游、页游、手游都一样),在客户端和服务端通讯,关于数值都会采用可变长度的方式来传输,从简而减小通讯量。
一般情况,客户端和服务端进行网络的socket通讯,都是采用二进制数值来进行的(也有采用字符串)。
可变长度的int是指根据实际的数值在网络传输中动态地改变长度。比如int在传输中可以变为byte,short,从而减少int的长度。文本会就Java服务端,H5和AS3客户端之间的通讯来进行讲解。

固定长度数值的网络发送

表示数组的长度一般都是固定,比如short是2个字节,int4个字节,long8个字节。那么客户端和服务端通讯的时候,传输short,int等数据过程的时候,如果不实现一些算法,则是直接传输,那么就是数值类型有多少个字节,就往数据流(ByteArray)写多少个字节。
但是实际应用中,虽然定义了一个数值类型,但是他表示的值经常在byte,short,int等不同范围之间切换。比如定义用户的金钱

//java
int moeny = 100  //用户的金钱,int 4个bytes
int playerId = 100000001;
//AS3
var moeny:int  = 100;
var playerId:int =  100000001;

js只有number,如果不进行字节长度控制的话,每次都得发8字节过去给js客户端

//js 只有number,8个字节
var money = 100;
var playerId = 100000001;

很显然,如果只发送一个10000或者127以内的数值,直接写4个字节的int,是非常浪费流量。
比如发送moeny这个字段就浪费了,playerId比较大那就是正常采用int了。js的话损失更大了,number是8个字节来进行发送。
所以一些好的通讯协议库会采用根据数值的实际值大小来动态发送byte,short,int这些类型。
然后再收到的那一端再把byte,short转换成int或者long,number类型。
比如Google protobuf就可以把通讯的内容压缩得非常小。
当然具体网络传输协议采用什么样的方式,是个比较广的问题,一般是要根据项目的实际情况来处理,不在本章的讨论范围。
固定长度的发送和接受代码,比如发送playerId和moeny到服务端(演示为伪代码,后面会给出全部代码)

//AS3
var bytes:ByteArray = new ByteArray();
bytes.writeInt(playerId);
bytes.writeInt(moeny);
//java 接受数据
ByteBuf buf = frame.content();
int money = buf.readInt();
int playerId = buf.readInt();

客户端和服务端收发保持一直,这样就可以进行通讯了。
实际项目中,也会对一些数值定义类型做优化,不会全部统一int或者number。
比如表示类型,虽然显示的时候是用int来表示,但是实际写给服务器的时候,是采用采用byte。

//AS3
var type:int = 5;
var bytes:ByteArray = new ByteArray();
bytes.writeByte(type);
//java 接受数据
ByteBuf buf = frame.content();
int type = buf.readByte();

这样是属于主动地节省字节,因为已经明确知道type不会超过127,所以写byte类型是安全的。

发送可变长度的数值的通讯机制

有些数据的值变化比较大,可能是0到上百万之间的变化,这种情况,我们只能使用int来表。比如money(游戏中的元宝)。刚开始玩家可能只有几十个元宝或者0,久一点可能1,2万了。土豪可能直接来个10w8w的。
假如我们还是发送定长的int,对于没有元宝或者低于30000元宝的玩家来说,就浪费通讯字节了。
所以原理是这样的,每次发送的时候,判断一下数值的大小,默认是写byte,如果大于或者等于某个规定值,则是表示类型。比如发送一个int到服务器去,下面的演示代码:
//先判断数据的长度

    /**
    * 写可变的整形数据类型 
    * @param bytes 二进制数组
    * @param value
    */      
    public static function writeVaryInt(bytes:ByteArray,value:int):void
    {
        //用-128、-127,-126来做标识符,分别表示short int 和long类型
        if(value <= 127 && value > -126)
        {
            //最小范围内,直接写byte
            bytes.writeByte(value);
            return ;
        }
        if(value <= 32767 && -value >= -32768)
        {
            //short -128
            bytes.writeByte(-128);
            bytes.writeShort(value);
            return ;
        }
        if(value <= 2147483647 && -value >= -2147483648)
        {
            //int -127
            bytes.writeByte(-127);
            bytes.writeInt(value);
            return ;
        }
        //剩下的都是long了
        bytes.writeByte(-126);
        bytes.writeDouble(value);
}

Java对应的读取内容是这样的:

/**
 * 读取可变长度的整形数据 
 * @param bytes 二进制数据
 * @return 相应的整形
 */     
public static long readVaryInt( ByteBuf bytes)
{
    byte type = bytes.readByte();
    //byte
    if(type <= 127 && type > -126)
        return type;
    //short
    if(type == -128)
        return bytes.readShort();
    //int
    if(type == -127)
        return bytes.readInt();
    //double(long)
    return (long)bytes.readDouble();
}

其实还可以进一步去扩展,比如还可以写单精度和双精度,以及混合之类等等。

数组长度的传输方式

可以很容易地根据这个原理,来写数组长度,而且数组长度比数值更简单。

/**
 * 动态写数组的长度
 * @param bytes
 * @param ary
 */
public static function writeArySize(bytes:ByteArray,ary:Array):void
{
    //数组的int长度比较清晰,不会有负的,所以采用-1来表示
    var len:int = ary.length;
    if(len <= 127 )
    {
        bytes.writeByte(len);
        return ;
    }
    if(len <= 32767)
    {
        //写个标识符
        bytes.writeByte(-1);
        //写个short的长度
        bytes.writeShort(length);
        return ;
    }
    //剩下都写int了,long不用想,太可怕
    bytes.writeByte(-2);
    //写个short的长度
    bytes.writeInt(length);
}

读取就不贴了,只要按照写的规则读出来就行了。

附录:Html5版本的可变长度数值读取方法

这里采用的是白鹭引擎写的,语言是TypeScript。跟AS3的几乎一样的逻辑和写法。

/**
 * 写可变的整形数据类型
 * @param bytes 二进制数组
 * @param value
 */
static writeVaryInt(bytes:egret.ByteArray,value:number):void
{
    //用-128、-127,-126来做标识符,分别表示short int 和long
    //写byte
    if(value <= 127 && value > -126)
    {
        bytes.writeByte(value);
        return ;
    }
    if(value <= 32767 && -value >= -32768)
    {
        //short -128
        bytes.writeByte(-128);
        bytes.writeShort(value);
        return ;
    }
    if(value <= 2147483647 && -value >= -2147483648)
    {
        //int -127
        bytes.writeByte(-127);
        bytes.writeInt(value);
        return ;
    }
    //剩下的都是long了
    bytes.writeByte(-126);
    bytes.writeDouble(value);
}
作者:sujun10 发表于2017/3/20 21:53:56 原文链接
阅读:58 评论:0 查看评论

Qt信号槽与观察者模式

$
0
0

qt的核心机制:信号与槽和设计模式中的观察者模式很类似。
https://www.devbean.net/2012/08/qt-study-road-2-custom-signal-slot
这篇文章讲的很详细,我这就算是做个笔记吧

信号与槽

信号和槽机制是 QT 的核心机制,它是qt自行定义的一种通信机制,独立于标准的 C/C++ 语言。信号与槽的机制,能够设计出解耦(模块化设计)的非常漂亮的程序。

信号(signal)

当某个信号对其客户或所有者发生的内部状态发生改变,信号被一个对象发射。当一个信号被发射时,与其相关联的槽将被立刻执行,就象一个正常的函数调用一样。信号 - 槽机制完全独立于任何 GUI 事件循环。如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地 执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪 个后执行。

槽(slot)

槽是普通的 C++ 成员函数,可以被正常调用,它们唯一的特殊性就是很多信号可以与其相关联。当与其关联的信号被发射时,这个槽就会被调用。

信号与槽的关联(connect)

通过调用 QObject 对象的 connect 函数来将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用。该函数的定义如下:

bool QObject::connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * memberFunction ) [static]

sender:发送方
signal:发送方发送的信号
receiver:接收方
memberFunction :槽函数
函数的作用就是把发送方sender 对象中的信号 signal 与接收方 receiver 中的 memberFunction 槽函数联系起来。
Ex:点击按钮,退出

#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QPushButton button("Quit");
    QObject::connect(&button, SIGNAL(clicked()),
                     &app,    SLOT(quit()));
    button.show();

    return app.exec();
}

观察者模式

观察者模式定义了一对多的依赖关系,当一个对象改变时,它的所有依赖者都会收到通知并自动更新。类似很多人订阅了一个公众号,一旦公众号发送消息,订阅的人都会收到消息。
代码摘自:https://www.devbean.net/2012/08/qt-study-road-2-custom-signal-slot/
经典的观察者模式在讲解举例的时候通常会举报纸和订阅者的例子。有一个报纸类Newspaper,有一个订阅者类Subscriber。Subscriber可以订阅Newspaper。这样,当Newspaper有了新的内容的时候,Subscriber可以立即得到通知。在这个例子中,观察者是Subscriber,被观察者是Newspaper。在经典的实现代码中,观察者会将自身注册到被观察者的一个容器中(比如subscriber.registerTo(newspaper))。被观察者发生了任何变化的时候,会主动遍历这个容器,依次通知各个观察者(newspaper.notifyAllSubscribers())。

下面我们看看使用 Qt 的信号槽,如何实现上述观察者模式。注意,这里我们仅仅是使用这个案例,我们的代码并不是去实现一个经典的观察者模式。也就是说,我们使用 Qt 的信号槽机制来获得同样的效果。

#include <QObject>

////////// newspaper.h
class Newspaper : public QObject
{
    Q_OBJECT
public:
    Newspaper(const QString & name) :
        m_name(name)
    {
    }

    void send() const
    {//emit 的含义是发出,也就是发出newPaper()信号
        emit newPaper(m_name); 
    }

signals:
    void newPaper(const QString &name) const;

private:
    QString m_name;
};

////////// reader.h
#include <QObject>
#include <QDebug>

class Reader : public QObject
{
    Q_OBJECT
public:
    Reader() {}

public slots:
    void receiveNewspaper(const QString & name) const
    {
        qDebug() << "Receives Newspaper: " << name;
    }
};

////////// main.cpp
#include <QCoreApplication>

#include "newspaper.h"
#include "reader.h"

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    Newspaper newspaper("Newspaper A");
    Reader reader;
    QObject::connect(&newspaper, SIGNAL(newPaper(QString)),
                     &reader,    SLOT(receiveNewspaper(QString)));
    newspaper.send();

    return app.exec();
}
作者:u011391629 发表于2017/3/20 21:59:37 原文链接
阅读:56 评论:0 查看评论

PAT (Advanced Level) Practise 1020. Tree Traversals (25)

$
0
0

1020. Tree Traversals (25)

时间限制
400 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, you are supposed to output the level order traversal sequence of the corresponding binary tree.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (<=30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the level order traversal sequence of the corresponding binary tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
Sample Output:
4 1 6 3 5 7 2

提交代码

原题链接:https://www.patest.cn/contests/pat-a-practise/1020

题意:给你一个二叉树的后序和中序遍历的序列,输出前序遍历的序列.

二叉树遍历第一题,当做模板留个纪念吧...

AC代码:

#include <cstdio>
#include <cstdlib>
#include <queue>
#include <iostream>
using namespace std;

const int maxx = 32;

typedef struct Tree
{
    Tree *le;
    Tree *ri;
    int data;
} Tree;

Tree *root;

int pos[maxx],in[maxx];


void printLevelOrder(Tree *root)
{
    queue<Tree *> que;
    Tree *tr = NULL;
    que.push(root);
    bool flg = true;
    while(!que.empty())
    {
        tr = (Tree *)que.front();
        que.pop();
        if(tr==NULL)continue;
        if(flg)
        {
            printf("%d",tr->data);
            flg = false;
        }
        else
        {
            printf(" %d",tr->data);
        }
        que.push(tr->le);
        que.push(tr->ri);
    }
    printf("\n");
}

//构造树pl为后序序列的左边界pr为其右边界
//il为中续遍历的左边界ir为其右边界
//0,n-1,0,n-1
Tree *buildTree(int pl,int pr,int il,int ir)
{
    cout<<pl<<","<<pr<<","<<il<<","<<ir<<endl;
    if(pl>pr)return NULL;
    int p = il;
    while(in[p]!=pos[pr])++p;

    //Tree *tree = (Tree *)malloc(sizeof(Tree));
    Tree* tree = new Tree();
    tree->data = pos[pr];
    tree->le = buildTree(pl,pr-ir+p-1,il,p-1);
    tree->ri = buildTree(pr-ir+p,pr-1,p+1,ir);

    return tree;
}

int main()
{
    int n,i;

    Tree *root;
    scanf("%d",&n);
    for(i=0; i<n; ++i)
    {
        scanf("%d",&pos[i]);
    }
    for(i=0; i<n; ++i)
    {
        scanf("%d",&in[i]);
    }
    root=buildTree(0,n-1,0,n-1);
    printLevelOrder(root);
    return 0;
}
/**
https://www.cnblogs.com/Hali-yang/archive/2012/08/28/2660091.html
http://blog.csdn.net/iaccepted/article/details/20473661
http://blog.csdn.net/iaccepted/article/details/20539395
*/


参考博客:

https://www.cnblogs.com/Hali-yang/archive/2012/08/28/2660091.html

http://blog.csdn.net/iaccepted/article/details/20473661




作者:hurmishine 发表于2017/3/20 22:05:27 原文链接
阅读:59 评论:0 查看评论

《华为机试在线训练》之求int型正整数在内存中存储时1的个数

$
0
0

一,题目要求

1,题目描述:输入一个int型的正整数,计算出该int型数据在内存中存储时1的个数

2,输入描述:输入一个整数(int类型)

3,输出描述:这个数转换成2进制后,输出1的个数

4,输入例子:5

5,输出例子:2

二,思路分析

     假如输入为5时,只要让5/2=2 ......余1,

1,思路一:可以想到的是将输入的整数直接转换为二进制数,然后将二进制数的每一位都赋值给数组,这样再求数组的和,即可以实现内存为1的计数。代码如下:

#include <stdio.h>

int main() 
{
	int a,i=0,j=0,b[32],count=0;
	scanf("%d",&a);
	while(a>0)
	{
	    b[i] = a%2;
		a/=2;
		i++;	
	} 
	for(j=i-1;j>=0;j--)
	{
   
	   count = count + b[j];	
	} 
	printf("%d",count);
	return 0;
}

 2,思路二:可以使用位运算的方法,用移位得出每一位是否为1,如果为1,则计数变量加1,否则计数变量不变

      

#include <iostream>  
  
using namespace std;  
  
int numberof1(int in)  
{  
    int count = 0;  
    int input = in;  
    for(int i = 0; i < 32; i++)  
    {  
        if(1 == (input & 1))  
            count++;  
        input >>= 1;  
    }  
    return count;  
}  
  
int main()  
{  
    int numbertocount;  
    cin>>numbertocount;  
    cout<<numberof1(numbertocount)<<endl;  
    return 0;  
}  

     
作者:huangchijun11 发表于2017/3/20 22:27:27 原文链接
阅读:189 评论:0 查看评论

adb、adb shell am、adb shell pm命令的详细使用说明

$
0
0

本文博客地址:http://blog.csdn.net/qq1084283172/article/details/64183248


1.在命令行终端执行下面的命令:

adb >adb.txt 2>&1


Android Debug Bridge version 1.0.31

 -a                            - directs adb to listen on all interfaces for a connection
 -d                            - directs command to the only connected USB device
                                 returns an error if more than one USB device is present.
 -e                            - directs command to the only running emulator.
                                 returns an error if more than one emulator is running.
 -s <specific device>          - directs command to the device or emulator with the given
                                 serial number or qualifier. Overrides ANDROID_SERIAL
                                 environment variable.
 -p <product name or path>     - simple product name like 'sooner', or
                                 a relative/absolute path to a product
                                 out directory like 'out/target/product/sooner'.
                                 If -p is not specified, the ANDROID_PRODUCT_OUT
                                 environment variable is used, which must
                                 be an absolute path.
 -H                            - Name of adb server host (default: localhost)
 -P                            - Port of adb server (default: 5037)
 devices [-l]                  - list all connected devices
                                 ('-l' will also list device qualifiers)
 connect <host>[:<port>]       - connect to a device via TCP/IP
                                 Port 5555 is used by default if no port number is specified.
 disconnect [<host>[:<port>]]  - disconnect from a TCP/IP device.
                                 Port 5555 is used by default if no port number is specified.
                                 Using this command with no additional arguments
                                 will disconnect from all connected TCP/IP devices.

device commands:
  adb push [-p] <local> <remote>
                               - copy file/dir to device
                                 ('-p' to display the transfer progress)
  adb pull [-p] [-a] <remote> [<local>]
                               - copy file/dir from device
                                 ('-p' to display the transfer progress)
                                 ('-a' means copy timestamp and mode)
  adb sync [ <directory> ]     - copy host->device only if changed
                                 (-l means list but don't copy)
                                 (see 'adb help all')
  adb shell                    - run remote shell interactively
  adb shell <command>          - run remote shell command
  adb emu <command>            - run emulator console command
  adb logcat [ <filter-spec> ] - View device log
  adb forward --list           - list all forward socket connections.
                                 the format is a list of lines with the following format:
                                    <serial> " " <local> " " <remote> "\n"
  adb forward <local> <remote> - forward socket connections
                                 forward specs are one of: 
                                   tcp:<port>
                                   localabstract:<unix domain socket name>
                                   localreserved:<unix domain socket name>
                                   localfilesystem:<unix domain socket name>
                                   dev:<character device name>
                                   jdwp:<process pid> (remote only)
  adb forward --no-rebind <local> <remote>
                               - same as 'adb forward <local> <remote>' but fails
                                 if <local> is already forwarded
  adb forward --remove <local> - remove a specific forward socket connection
  adb forward --remove-all     - remove all forward socket connections
  adb jdwp                     - list PIDs of processes hosting a JDWP transport
  adb install [-l] [-r] [-d] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>
                               - push this package file to the device and install it
                                 ('-l' means forward-lock the app)
                                 ('-r' means reinstall the app, keeping its data)
                                 ('-d' means allow version code downgrade)
                                 ('-s' means install on SD card instead of internal storage)
                                 ('--algo', '--key', and '--iv' mean the file is encrypted already)
  adb uninstall [-k] <package> - remove this app package from the device
                                 ('-k' means keep the data and cache directories)
  adb bugreport                - return all information from the device
                                 that should be included in a bug report.

  adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]
                               - write an archive of the device's data to <file>.
                                 If no -f option is supplied then the data is written
                                 to "backup.ab" in the current directory.
                                 (-apk|-noapk enable/disable backup of the .apks themselves
                                    in the archive; the default is noapk.)
                                 (-obb|-noobb enable/disable backup of any installed apk expansion
                                    (aka .obb) files associated with each application; the default
                                    is noobb.)
                                 (-shared|-noshared enable/disable backup of the device's
                                    shared storage / SD card contents; the default is noshared.)
                                 (-all means to back up all installed applications)
                                 (-system|-nosystem toggles whether -all automatically includes
                                    system applications; the default is to include system apps)
                                 (<packages...> is the list of applications to be backed up.  If
                                    the -all or -shared flags are passed, then the package
                                    list is optional.  Applications explicitly given on the
                                    command line will be included even if -nosystem would
                                    ordinarily cause them to be omitted.)

  adb restore <file>           - restore device contents from the <file> backup archive

  adb help                     - show this help message
  adb version                  - show version num

scripting:
  adb wait-for-device          - block until device is online
  adb start-server             - ensure that there is a server running
  adb kill-server              - kill the server if it is running
  adb get-state                - prints: offline | bootloader | device
  adb get-serialno             - prints: <serial-number>
  adb get-devpath              - prints: <device-path>
  adb status-window            - continuously print device status for a specified device
  adb remount                  - remounts the /system partition on the device read-write
  adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program
  adb reboot-bootloader        - reboots the device into the bootloader
  adb root                     - restarts the adbd daemon with root permissions
  adb usb                      - restarts the adbd daemon listening on USB
  adb tcpip <port>             - restarts the adbd daemon listening on TCP on the specified port
networking:
  adb ppp <tty> [parameters]   - Run PPP over USB.
 Note: you should not automatically start a PPP connection.
 <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1
 [parameters] - Eg. defaultroute debug dump local notty usepeerdns

adb sync notes: adb sync [ <directory> ]
  <localdir> can be interpreted in several ways:

  - If <directory> is not specified, both /system and /data partitions will be updated.

  - If it is "system" or "data", only the corresponding partition
    is updated.

environmental variables:
  ADB_TRACE                    - Print debug information. A comma separated list of the following values
                                 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp
  ANDROID_SERIAL               - The serial number to connect to. -s takes priority over this if given.
  ANDROID_LOG_TAGS             - When used with the logcat option, only these debug tags are printed.



2.在命令行终端执行下面的命令:

adb shell am >am.txt 2>&1


usage: am [subcommand] [options]

usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]

               [--R COUNT] [-S] [--opengl-trace]

               [--user <USER_ID> | current] <INTENT>

       am startservice [--user <USER_ID> | current] <INTENT>

       am stopservice [--user <USER_ID> | current] <INTENT>

       am force-stop [--user <USER_ID> | all | current] <PACKAGE>

       am kill [--user <USER_ID> | all | current] <PACKAGE>

       am kill-all

       am broadcast [--user <USER_ID> | all | current] <INTENT>

       am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]

               [--user <USER_ID> | current]

               [--no-window-animation] <COMPONENT>

       am profile start [--user <USER_ID> current] <PROCESS> <FILE>

       am profile stop [--user <USER_ID> current] [<PROCESS>]

       am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>

       am set-debug-app [-w] [--persistent] <PACKAGE>

       am clear-debug-app

       am monitor [--gdb <port>]

       am hang [--allow-restart]

       am restart

       am idle-maintenance

       am screen-compat [on|off] <PACKAGE>

       am to-uri [INTENT]

       am to-intent-uri [INTENT]

       am switch-user <USER_ID>

       am stop-user <USER_ID>

       am stack create <TASK_ID> <RELATIVE_STACK_BOX_ID> <POSITION> <WEIGHT>

       am stack movetask <TASK_ID> <STACK_ID> [true|false]

       am stack resize <STACK_ID> <WEIGHT>

       am stack boxes

       am stack box <STACK_BOX_ID>



am start: start an Activity.  Options are:

    -D: enable debugging

    -W: wait for launch to complete

    --start-profiler <FILE>: start profiler and send results to <FILE>

    -P <FILE>: like above, but profiling stops when app goes idle

    -R: repeat the activity launch <COUNT> times.  Prior to each repeat,

        the top activity will be finished.

    -S: force stop the target app before starting the activity

    --opengl-trace: enable tracing of OpenGL functions

    --user <USER_ID> | current: Specify which user to run as; if not

        specified then run as the current user.



am startservice: start a Service.  Options are:

    --user <USER_ID> | current: Specify which user to run as; if not

        specified then run as the current user.



am stopservice: stop a Service.  Options are:

    --user <USER_ID> | current: Specify which user to run as; if not

        specified then run as the current user.



am force-stop: force stop everything associated with <PACKAGE>.

    --user <USER_ID> | all | current: Specify user to force stop;

        all users if not specified.



am kill: Kill all processes associated with <PACKAGE>.  Only kills.

  processes that are safe to kill -- that is, will not impact the user

  experience.

    --user <USER_ID> | all | current: Specify user whose processes to kill;

        all users if not specified.



am kill-all: Kill all background processes.



am broadcast: send a broadcast Intent.  Options are:

    --user <USER_ID> | all | current: Specify which user to send to; if not

        specified then send to all users.

    --receiver-permission <PERMISSION>: Require receiver to hold permission.



am instrument: start an Instrumentation.  Typically this target <COMPONENT>

  is the form <TEST_PACKAGE>/<RUNNER_CLASS>.  Options are:

    -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with

        [-e perf true] to generate raw output for performance measurements.

    -e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners a

        common form is [-e <testrunner_flag> <value>[,<value>...]].

    -p <FILE>: write profiling data to <FILE>

    -w: wait for instrumentation to finish before returning.  Required for

        test runners.

    --user <USER_ID> | current: Specify user instrumentation runs in;

        current user if not specified.

    --no-window-animation: turn off window animations while running.



am profile: start and stop profiler on a process.  The given <PROCESS> argument

  may be either a process name or pid.  Options are:

    --user <USER_ID> | current: When supplying a process name,

        specify user of process to profile; uses current user if not specified.



am dumpheap: dump the heap of a process.  The given <PROCESS> argument may

  be either a process name or pid.  Options are:

    -n: dump native heap instead of managed heap

    --user <USER_ID> | current: When supplying a process name,

        specify user of process to dump; uses current user if not specified.



am set-debug-app: set application <PACKAGE> to debug.  Options are:

    -w: wait for debugger when application starts

    --persistent: retain this value



am clear-debug-app: clear the previously set-debug-app.



am bug-report: request bug report generation; will launch UI

    when done to select where it should be delivered.



am monitor: start monitoring for crashes or ANRs.

    --gdb: start gdbserv on the given port at crash/ANR



am hang: hang the system.

    --allow-restart: allow watchdog to perform normal system restart



am restart: restart the user-space system.



am idle-maintenance: perform idle maintenance now.



am screen-compat: control screen compatibility mode of <PACKAGE>.



am to-uri: print the given Intent specification as a URI.



am to-intent-uri: print the given Intent specification as an intent: URI.



am switch-user: switch to put USER_ID in the foreground, starting

  execution of that user if it is currently stopped.



am stop-user: stop execution of USER_ID, not allowing it to run any

  code until a later explicit switch to it.



am stack create: create a new stack relative to an existing one.

   <TASK_ID>: the task to populate the new stack with. Must exist.

   <RELATIVE_STACK_BOX_ID>: existing stack box's id.

   <POSITION>: 0: before <RELATIVE_STACK_BOX_ID>, per RTL/LTR configuration,

               1: after <RELATIVE_STACK_BOX_ID>, per RTL/LTR configuration,

               2: to left of <RELATIVE_STACK_BOX_ID>,

               3: to right of <RELATIVE_STACK_BOX_ID>,               
               4: above <RELATIVE_STACK_BOX_ID>, 
               5: below <RELATIVE_STACK_BOX_ID>

   <WEIGHT>: float between 0.2 and 0.8 inclusive.



am stack movetask: move <TASK_ID> from its current stack to the top (true) or   bottom (false) of <STACK_ID>.



am stack resize: change <STACK_ID> relative size to new <WEIGHT>.



am stack boxes: list the hierarchy of stack boxes and their contents.



am stack box: list the hierarchy of stack boxes rooted at <STACK_BOX_ID>.



<INTENT> specifications include these flags and arguments:

    [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]

    [-c <CATEGORY> [-c <CATEGORY>] ...]

    [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]

    [--esn <EXTRA_KEY> ...]

    [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]

    [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]

    [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]

    [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]

    [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]

    [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]

    [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]

    [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]

    [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]

    [-n <COMPONENT>] [-f <FLAGS>]

    [--grant-read-uri-permission] [--grant-write-uri-permission]

    [--debug-log-resolution] [--exclude-stopped-packages]

    [--include-stopped-packages]

    [--activity-brought-to-front] [--activity-clear-top]

    [--activity-clear-when-task-reset] [--activity-exclude-from-recents]

    [--activity-launched-from-history] [--activity-multiple-task]

    [--activity-no-animation] [--activity-no-history]

    [--activity-no-user-action] [--activity-previous-is-top]

    [--activity-reorder-to-front] [--activity-reset-task-if-needed]

    [--activity-single-top] [--activity-clear-task]

    [--activity-task-on-home]

    [--receiver-registered-only] [--receiver-replace-pending]

    [--selector]

    [<URI> | <PACKAGE> | <COMPONENT>]





Error: No intent supplied

3.在命令行终端执行下面的命令:

adb shell pm >pm.txt 2>&1


usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]

       pm list permission-groups

       pm list permissions [-g] [-f] [-d] [-u] [GROUP]

       pm list instrumentation [-f] [TARGET-PACKAGE]

       pm list features

       pm list libraries

       pm list users

       pm path PACKAGE

       pm dump PACKAGE

       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]

                  [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]

                  [--originating-uri <URI>] [--referrer <URI>] PATH

       pm uninstall [-k] PACKAGE

       pm clear [--user USER_ID] PACKAGE

       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT

       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT

       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT

       pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT

       pm block [--user USER_ID] PACKAGE_OR_COMPONENT

       pm unblock [--user USER_ID] PACKAGE_OR_COMPONENT

       pm grant PACKAGE PERMISSION

       pm revoke PACKAGE PERMISSION

       pm set-install-location [0/auto] [1/internal] [2/external]

       pm get-install-location

       pm set-permission-enforced PERMISSION [true|false]

       pm trim-caches DESIRED_FREE_SPACE

       pm create-user USER_NAME

       pm remove-user USER_ID

       pm get-max-users



pm list packages: prints all packages, optionally only

  those whose package name contains the text in FILTER.  Options:

    -f: see their associated file.

    -d: filter to only show disbled packages.

    -e: filter to only show enabled packages.

    -s: filter to only show system packages.

    -3: filter to only show third party packages.

    -i: see the installer for the packages.

    -u: also include uninstalled packages.



pm list permission-groups: prints all known permission groups.



pm list permissions: prints all known permissions, optionally only

  those in GROUP.  Options:

    -g: organize by group.

    -f: print all information.

    -s: short summary.

    -d: only list dangerous permissions.

    -u: list only the permissions users will see.



pm list instrumentation: use to list all test packages; optionally

  supply <TARGET-PACKAGE> to list the test packages for a particular

  application.  Options:

    -f: list the .apk file for the test package.



pm list features: prints all features of the system.



pm list users: prints all users on the system.



pm path: print the path to the .apk of the given PACKAGE.



pm dump: print system state associated w ith the given PACKAGE.



pm install: installs a package to the system.  Options:

    -l: install the package with FORWARD_LOCK.

    -r: reinstall an exisiting app, keeping its data.

    -t: allow test .apks to be installed.

    -i: specify the installer package name.

    -s: install package on sdcard.

    -f: install package on internal flash.

    -d: allow version code downgrade.



pm uninstall: removes a package from the system. Options:

    -k: keep the data and cache directories around after package removal.



pm clear: deletes all data associated with a package.



pm enable, disable, disable-user, disable-until-used: these commands

  change the enabled state of a given package or component (written

  as "package/class").



pm grant, revoke: these commands either grant or revoke permissions

  to applications.  Only optional permissions the application has

  declared can be granted or revoked.



pm get-install-location: returns the current install location.

    0 [auto]: Let system decide the best location

    1 [internal]: Install on internal device storage

    2 [external]: Install on external media



pm set-install-location: changes the default install location.

  NOTE: this is only intended for debugging; using this can cause

  applications to break and other undersireable behavior.

    0 [auto]: Let system decide the best location

    1 [internal]: Install on internal device storage

    2 [external]: Install on external media



pm trim-caches: trim cache files to reach the given free space.



pm create-user: create a new user with the given USER_NAME,

  printing the new user identifier of the user.



pm remove-user: remove the user with the given USER_IDENTIFIER,

  deleting all data associated with that user

作者:QQ1084283172 发表于2017/3/20 22:37:13 原文链接
阅读:64 评论:0 查看评论

Hibernate快速入门

$
0
0

Hibernate框架介绍

什么是Hibernate

我们可以从度娘上摘抄这样有关Hibernate的介绍:

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用。

从中,我们可以得出这样的结论:Hibernate是一个轻量级的JDBC封装,也就是说,我们可以使用Hibernate来完成原来我们使用JDBC完成的操作,也就是与数据库的交互操作。它是在dao层去使用的。

什么是ORM

对象关系映射(英语:Object Relation Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
对象-关系映射,是随着面向对象的软件开发方法发展而产生的。面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。
ORM模型的简单性简化了数据库查询过程。使用ORM查询工具,用户可以访问期望数据,而不必理解数据库的底层结构。
这里写图片描述
简单来说,我们使用ORM可以将我们的对象(或类)去进行映射,使得我们可以去操作对象就能完成对表的操作。

为什么使用Hibernate框架

原因如下:

  • Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
  • Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现,它很大程度的简化了dao层编码工作。

总结:Hibernate是企业级开发中的主流框架,映射的灵活性很出色。它支持很多关系型数据库。

Hiberate框架学习目标

由于之前学过Hiberate框架,所以这就等于是在复习了。对于Hiberate框架的学习重点,可以总结为:

  1. 掌握Hiberate的基本配置——即搭建Hiberate开发环境
  2. 掌握Hiberate常用API——即如何使用Hiberate框架进行开发
  3. 掌握Hiberate的关联映射——解决表与表之间存在的关系问题,有1:n(一对多)、 1:1(一对一)、m:n(多对多)关系
  4. 掌握Hiberate的检索方式——即掌握Hiberate的查询
  5. 掌握Hiberate的优化方式——即提高Hiberate的效率

Hibernate快速入门

介绍完Hibernate框架之后,我们来快速入门Hibernate,对其有一个直观的了解。

下载Hibernate

可去官网下载Hibernate,我下载的是
这里写图片描述
所以,之后有关Hibernate的系列文章都是以这个版本为蓝图展开的。下载解压缩之后,可以看到如下目录结构:
这里写图片描述
其中,在lib/required目录下,包含运行Hibernate项目必须的jar包有:
这里写图片描述

创建数据库与表

正如前面所说,Hibernate是一个轻量级的JDBC封装,也就是说,我们可以使用Hibernate来完成原来我们使用JDBC完成的操作,也就是与数据库的交互操作。所以我们首先要创建数据库与表,这里我使用的数据库是mysql。

create database hibernateTest;
use hibernateTest;
create table t_customer(
    id int primary key auto_increment,
    name varchar(20),
    address varchar(50)
);

创建实体类

首先在Eclipse上创建一个Dynamic Web Project,比如我创建的是hibernate_demo1,然后再切到Java透视图。这儿我们在cn.itheima.domain包中创建一个实体类——Customer.java。

public class Customer {

    private int id;
    private String name;
    private String address;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "Customer [id=" + id + ", name=" + name + ", address=" + address + "]";
    }   
}

导入Hibernate框架相关依赖jar包

首先导入lib/required目录下所有的jar包:
这里写图片描述
再导入mysql数据库的驱动jar包:
这里写图片描述
最后导入日志相关的jar包:
这里写图片描述
导入完日志相关的jar包之后,我们还须将project/etc/log4j.properties文件导入到工程hibernate_demo1的src目录下,这样工程的整个结构就为:
这里写图片描述

Hibernate的相关配置文件

准备好以上工作之后,我们终于要踏入Hibernate的学习中了。首先我们要编写Hibernate的相关配置文件,Hibernate的相关配置文件分为两种:

  1. xxx.hbm.xml:它主要是用于描述类与数据库中的表的映射关系。
  2. hibernate.cfg.xml:它是Hibernate框架的核心配置文件。

有关这两个配置文件的详细介绍,我们后面会给大家讲解,如果就在这里弄的话,违背了我的初衷了,本文只是在教初学者怎样快速入门Hibernate。

映射配置文件

首先我们要学会如何编写映射配置文件,大家要知道编写完的映射配置文件应与实体类在同一个包下,并且名称应是类名.hbm.xml,所以我们要在cn.itheima.domain包下创建一个Customer.hbm.xml文件,但是它的约束应该怎么写呢?可以在Hibernate的核心jar包——hibernate-core-5.0.7.Final.jar的org.hibernate包下查找到hibernate-mapping-3.0.dtd文件,打开该文件,找到如下内容:

<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

然后复制黏贴到Customer.hbm.xml文件中。
这里我先给出Customer.hbm.xml文件的内容,但内容不做过多介绍:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itheima.domain">
    <!-- 
        name:即实体类的全名
        table:映射到数据库里面的那个表的名称
        catalog:数据库的名称
     -->
    <class name="Customer" table="t_customer" catalog="hibernateTest">
        <!-- class下必须要有一个id的子元素 -->
        <!-- id是用于描述主键的 -->
        <id name="id" column="id">
            <!-- 主键生成策略 -->
            <generator class="native"></generator>
        </id>
        <!-- 
            使用property来描述属性与字段的对应关系
            如果length忽略不写,且你的表是自动创建这种方案,那么length的默认长度是255
        -->
        <property name="name" column="name" length="20"></property>
        <property name="address" column="address" length="50"></property>
    </class>
</hibernate-mapping>

核心配置文件

核心配置文件主要是Hibernate框架所使用的,它主要包含了连接数据库的相关信息和Hibernate的相关配置等。
现在我们要学会如何编写Hibernate核心配置文件,大家也要知道编写完的核心配置文件应在src目录下,并且名称应是hibernate.cfg.xml,所以我们要在src目录下创建一个hibernate.cfg.xml文件,但是它的约束应该怎么写呢?可以在Hibernate的核心jar包——hibernate-core-5.0.7.Final.jar的org.hibernate包下查找到hibernate-configuration-3.0.dtd文件,打开该文件,找到如下内容:

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

然后复制黏贴到hibernate.cfg.xml文件中。
在这个文件中到底如何配置昵?我们可以参考hibernate-release-5.0.7.Final\project\etc\hibernate.properties文件。这里我先给出hibernate.cfg.xml文件的内容,但内容不做过多介绍:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- 配置关于数据库连接的四个项:driverClass  url username password -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///hibernateTest</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">yezi</property>

        <!-- 可以将向数据库发送的SQL语句显示出来 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 格式化SQL语句 -->
        <property name="hibernate.format_sql">true</property>

        <!-- hibernate的方言 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- 配置hibernate的映射文件所在的位置 -->
        <mapping resource="cn/itheima/domain/Customer.hbm.xml" />
    </session-factory>
</hibernate-configuration>

Hibernate快速入门开发测试

在cn.itheima.test包下创建一个单元测试类——HibernateTest1.java。

public class HibernateTest1 {

    // 保存一个Customer
    @Test
    public void saveCustomerTest() {
        // 创建一个Customer
        Customer c = new Customer();
        c.setName("叶子");
        c.setAddress("武汉");

        // 使用Hibernate的API来完成将Customer信息保存到mysql数据库中的操作
        Configuration config = new Configuration().configure(); // Hibernate框架加载hibernate.cfg.xml文件
        SessionFactory sessionFactory = config.buildSessionFactory();
        Session session = sessionFactory.openSession(); // 相当于得到一个Connection
        // 开启事务
        session.beginTransaction();

        // 操作
        session.save(c);

        // 事务提交
        session.getTransaction().commit();
        session.close();
        sessionFactory.close();
    }

    // 根据id查询一个Customer对象
    @Test
    public void findCustomerByIdTest() {
        Configuration config = new Configuration().configure(); // Hibernate框架加载hibernate.cfg.xml文件
        SessionFactory sessionFactory = config.buildSessionFactory();
        Session session = sessionFactory.openSession(); // 相当于得到一个Connection
        // 开启事务
        session.beginTransaction();

        // 根据业务来编写代码
        // Customer c = session.get(Customer.class, 1);
        Customer c = session.load(Customer.class, 1);

        System.out.println(c.getName());

        // 事务提交
        session.getTransaction().commit();
        session.close();
        sessionFactory.close();
    }

    // 修改操作
    @Test
    public void updateCustomerTest() {
        Configuration config = new Configuration().configure(); // Hibernate框架加载hibernate.cfg.xml文件
        SessionFactory sessionFactory = config.buildSessionFactory();
        Session session = sessionFactory.openSession(); // 相当于得到一个Connection
        // 开启事务
        session.beginTransaction();

        // 根据业务来编写代码
        Customer c = session.get(Customer.class, 1);
        c.setName("郑敏");
        session.update(c); // 修改操作

        // 事务提交
        session.getTransaction().commit();
        session.close();
        sessionFactory.close();
    }

    // 删除操作---根据id进行删除
    @Test
    public void deleteCustomerTest() {
        Configuration config = new Configuration().configure(); // Hibernate框架加载hibernate.cfg.xml文件
        SessionFactory sessionFactory = config.buildSessionFactory();
        Session session = sessionFactory.openSession(); // 相当于得到一个Connection
        // 开启事务
        session.beginTransaction();

        // 根据业务来编写代码
        Customer c = session.get(Customer.class, 1);
        session.delete(c); // 删除操作

        // 事务提交
        session.getTransaction().commit();
        session.close();
        sessionFactory.close();
    }

    // 查询所有Customer
    @Test
    public void findAllCustomerTest() {
        Configuration config = new Configuration().configure(); // Hibernate框架加载hibernate.cfg.xml文件
        SessionFactory sessionFactory = config.buildSessionFactory();
        Session session = sessionFactory.openSession(); // 相当于得到一个Connection
        // 开启事务
        session.beginTransaction();

        // 根据业务来编写代码
        Query query = session.createQuery("from Customer"); // HQL语句,它类似于SQL语句
        List<Customer> list = query.list();
        System.out.println(list);

        // 事务提交
        session.getTransaction().commit();
        session.close();
        sessionFactory.close();
    }

}

测试如若都无任何问题,则我们就算入门Hibernate了。

Hibernate执行原理总结

可从度娘上摘抄到如下文字:

  1. 通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件。
  2. 由hibernate.cfg.xml中的<mapping resource="com/xx/Xxx.hbm.xml"/>读取解析映射信息。
  3. 通过config.buildSessionFactory();得到sessionFactory。
  4. sessionFactory.openSession();得到session。
  5. session.beginTransaction();开启事务。
  6. persistent operate; 执行你自己的操作。
  7. session.getTransaction().commit();提交事务。
  8. 关闭session。
  9. 关闭sessionFactory。
作者:yerenyuan_pku 发表于2017/3/20 23:08:29 原文链接
阅读:51 评论:0 查看评论

I/O多路转接之epoll

$
0
0

一、epoll函数
epoll是linux特有的I/O复用函数,它比select和poll要高效的多。epoll用一个事件表来保存用户关心的文件描述符,但是这个事件表需要一个文件描述符来标识。

1、内核事件表

#include<sys/epoll.h>
int epoll_create(int size);

功能:创建一个事件表,并返回这个事件表的文件描述符。这个文件描述符就代表一个epoll模型,用作其他epoll系统调用的第一个参数,以指定要访问的内核事件表。
参数:size参数并不起作用,只是给内核一个提示,告诉它事件表需要多大。

2、操作内核事件表

#include<sys/epoll.h>
int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);

参数:
epfd:表示要操作的内核事件表的文件描述符。
op:指定操作的类型。操作类型有三种。
EPOLL_CTL_ADD:向事件表中注册fd上的事件。
EPOLL_CTL_MOD:修改fd上的注册事件。
EPOLL_CTL_DEL:删除fd上的注册事件。
fd:是要操作的文件描述符。
event:用来指定事件,它是epoll_event结构指针类型。

struct epoll_event
{
     _uint32_t events;   //epoll事件
     epoll_data_t data;  //用户数据
}

这里写图片描述
epoll_data是一个联合体,其中fd使用的最多,表示指定事件的文件描述符。ptr可以用来指定与fd相关的用户数据。如果要将文件描述符和用户数据关联起来,可以让ptr指向的用户数据这种包含fd。

typedef union epoll_data
{
     void* ptr;     
     int fd;            
     uint32_t u32;
     uint64_t u64;
}
epoll_ctl成功时返回0,失败时返回-1并设置errno。

3、等待事件发生

#include<sys/epoll.h>
int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout);

功能:该函数成功时返回就绪的文件描述符的个数,失败返回-1并设置errno。
参数:
epfd:要监测的epoll模型,也就是要监测的内核事件表。
events:它表示一个结构体数组,是一个输出型参数,用来获取已经就绪的事件的相关信息。events不可以是空指针,内核只负责把数据复制到这个events数组中,而不会去帮助我们在用户态中分配内存。
maxevents:指明events的大小。这个值不能大于epoll_create的参数size。
timeout:设置超时时间的。

4、LT和ET模式
LT(水平触发)模式是默认的模式,在这种模式下epoll相当于一个效率较高poll。采用LT的工作模式时:当epoll_wait检测到其上有事件发生并将此事件通知应用程序后,应用程序可以不立即处理该事件。这样,当应用程序下一次调用epoll_wait时,epoll_wait还会再次向应用程序通告此事件,直到事件被处理。LT同时支持阻塞和非阻塞方式。
ET:当向epoll内核事件表中注册一个文件描述符上的EPOLLET事件的时,epoll将通过ET(边沿模式)来操作该文件描述符,ET模式是epoll的高效工作模式。对于在ET模式工作的文件描述符来说:当epoll_wait检测到其上有事件发生并将此事件通知应用程序后,应用程序应该立即处理该事件,因为后续的epoll_wait调用将不再向应用程序通知这一事件。ET模式在很大程度上降低了同一个epoll事件被重复触发的次数,所以ET要更高效。使用ET模式的文件描述符都应该是非阻塞的,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务都饿死。ET只支持非阻塞方式。

二、EPOLL工作原理
1、当调用epoll_wait获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值,你只需要去epoll指定一个数组依次取得相应数量的文件描述符即可,这里使用了内存映射(mmap)技术,会节省一些文件描述符在系统调用时的复制开销。
2、一但文件描述符就绪,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait时便得到通知。
3、epoll与select和poll不同,epoll将事件表完全交给内核去管理,用户只需要将要监测的文件描述符添加进入内核表中即可,等到事件就绪后内核会自动将就绪事件的文件描述符激活。
那么在内核中是怎样对这些文件描述符进行监测的呢?又是怎样处理就绪事件的呢?
这里写图片描述

三、epoll的优点
1、内核通过一个事件表直接管理用户感兴趣的所有事件。因此每次调用epoll_wait时,无需反复传入用户感兴趣的事件。
2、epoll采用回调方式来监测就绪事件,算法复杂度为O(1)。epoll_wait返回值是就绪事件的个数。
3、epoll将事件表交给内核去管理,底层用红黑树,效率高。
4、epoll支持ET模式,非常高效。
5、epoll支持的文件描述符最大值一般是65535,比select要优。

作者:LF_2016 发表于2017/3/20 23:09:40 原文链接
阅读:46 评论:0 查看评论

I/O复用(二)

$
0
0

Linux下实现I/O多路复用的系统调用主要有select、poll和epoll。

这里主要剖析poll。


1>fds参数是一个pollfd结构类型的数组,它指定所有我们感兴趣的文件描述符上发生的可读、可写和异常事件,pollfd结构体的定义如下:


其中,fd成员指定文件描述符;events成员告诉poll监听fd上的哪些事情,它是一系列事件的按位或;revents成员则由内核修改,以通知应用程序fd上实际发生了哪些事件。poll支持的事件类型有POLLIN、POLLOUT、POLLPRI等。

2>nfds参数指定被监听的事件集合fds的大小。类型是:typedef unsigned long int nfds_t;

3>timeout参数指定poll的超时值,单位是毫秒。当timeout为-1时,poll调用将永远阻塞,知道某个事件发生;当timeout为0时,poll调用将立即返回。

poll系统调用的返回值的含义与select相同。

poll是一个系统调用,系统主要做这几件事:

1.将用户传入的pollfd数组拷贝到内核空间因为拷贝操作与数组长度相关。时间上这是一个O(n)操作。

2.查询每个文件描述符对应设备的状态,如果该设备尚未就绪,则在该设备的等待队列中加入一项并继续查询下一设备的状态,查询完所有设备后没有一个就绪,这时则需要挂起当前进程等待,直到设备就绪或者超时。

3.将获得的数据传到用户空间并执行释放内存和剥离等待队列等善后工作。

代码实现:

/*************************************************************************
	> File Name: poll.c
	> Author: ZX
	> Mail: 18829897183@163.com 
	> Created Time: Fri 17 Mar 2017 10:37:42 PM PDT
 ************************************************************************/

#include <stdio.h>
#include <poll.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <assert.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>

#define _SIZE_ 1024

int startup(const char* _ip, int _port)
{
	int sock = socket(AF_INET, SOCK_STREAM, 0);
	if(sock < 0)
	{
		perror("socket");
		return 1;
	}
	struct sockaddr_in local;
	local.sin_family = AF_INET;
	local.sin_addr.s_addr = inet_addr(_ip);
	local.sin_port = htons(_port);
	socklen_t len = sizeof(local);

	if(bind(sock, (struct sockaddr*)&local, len) < 0)
	{
		perror("bind");
		return 2;
	}

	if(listen(sock, 5) < 0)
	{
		perror("listen");
		return 3;
	}
	return sock;
}

static void Init_fd(struct pollfd* pfd, int len)
{
	assert(pfd);
	int i = 0;
	for(; i<len; i++)
	{
		pfd[i].fd = -1;
		pfd[i].events = 0;
		pfd[i].revents = 0;
	}
}

static int Add_fd(struct pollfd* pfd, int len, int add_fd)
{
	assert(pfd);
	int i = 0;
	for(; i<len; i++)
	{
		if(pfd[i].fd == -1)
		{
			pfd[i].fd = add_fd;
			return i;
		}
	}
	return -1;
}

int main(int argc, char* argv[])
{
	if(argc != 3)
	{
		printf("Usage: %s [local_ip] [local_port]", argv[0]);
		return 4;
	}
	int listen_sock = startup(argv[1], atoi(argv[2]));

	struct pollfd pfd[_SIZE_];
	Init_fd(pfd, _SIZE_);
	
	int index = Add_fd(pfd, _SIZE_, listen_sock);
	if(index != -1)
	{
		pfd[index].events = POLLIN;
	}

	int timeout = 2000;
	char* buf[1024];
	while(1)
	{
		switch(poll(pfd, _SIZE_, timeout))
		{
			case 0:
				printf("timeout...\n");
				break;
			case -1:
				perror("poll");
		//		exit(1);
				break;
			default:
				{
					int i = 0;
					printf("default..\n");
					for(; i<_SIZE_; i++)
					{
						int fd = pfd[i].fd;
						printf("fd: %d\n",fd);
						sleep(1);
						if(fd == listen_sock && (pfd[i].fd & POLLIN))
						{							
							struct sockaddr_in peer;
							socklen_t len =  sizeof(peer);
							int new_sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
							if(new_sock < 0)
							{
								perror("accept");
//								exit(5);
								return 5;
							}
							else if(new_sock > 0)
							{
								printf("get a new client# ip: %s\n", inet_ntoa(peer.sin_addr));
								int newfd = Add_fd(pfd, _SIZE_, new_sock);
								printf("newfd: %d\n",newfd);
								if(newfd != -1)
								{
									pfd[newfd].events = POLLIN;
								}
								else if(newfd == _SIZE_)
								{
									printf("newfd == _SIZE_\n");
									close(newfd);
								}
							}
						}
						else if(fd != -1 && fd != listen_sock && (pfd[i].events & POLLIN))
						{
							printf("read:\n");
							char buf[1024];
							memset(buf, '\0', sizeof(buf));

							ssize_t _s = read(fd, buf, sizeof(buf)-1);
							if(_s > 0)
							{
								buf[_s] = 0;
								printf("buf: %s\n", buf);
							}
							else if(_s == 0)
							{
								printf("client is quit!\n");
								close(pfd[i].fd);
							}
							else
							{
								perror("read");
								continue;
							}
						}//else if
					}
				}
		}
	}
	return 0;
}
实质上就是数组处理。

作者:z_xiao_xue 发表于2017/3/21 0:03:51 原文链接
阅读:45 评论:0 查看评论

【NDN安全】Poseidon: Mitigating Interest Flooding DDoS Attacks in Named Data Networking 学习笔记

$
0
0

      1、在t=1s时,消费者突然短暂地发送30个兴趣包,每2ms一个,从1.2s开始,正常消费者每10.7ms发送一个兴趣包,虚假兴趣包每1.337ms生成一个。路由器的PIT表大小为120KB,兴趣包超时时间设置为4s。

      2、兴趣包洪泛攻击的检测阶段:有两个参数,ω(rij,tk)和ρ(rij,tk)。ω(rij,tk)=时间间隔tk内从接口rij接收到的兴趣包/时间间隔tk内从接口rij接收到的数据包,代表兴趣包的满足率。ρ(rij,tk)为PIT中在时间间隔tk内从接口rij接收到的未满足的兴趣包的多少,即PIT中一段时间内从该接口接收到的兴趣包的多少。ω(rij,tk)有阈值Ω(rij),ρ(rij,tk)有阈值P(rij)。当某时刻检测到兴趣包满足率低于阈值,从接口接收到的兴趣包数量高于阈值时,即可认为检测到了攻击。

      3、该检测方法可以排除两种正常请求:

      (1)在一个相对短的时间段内,如果路由器不能满足进来的兴趣包,即PIT中可能存在大量的未满足兴趣包,则ρ(rij,tk)可能超过阈值,但ω(rij,tk)可能不会。

      (2)当路由器接收到一些短暂的突发兴趣包时,ω(rij,tk)可能超过阈值,而ρ(rij,tk)不会。

      只有当ω(rij,tk)和ρ(rij,tk)都超过阈值,才可判断路由器受到攻击。

      4、兴趣包洪泛攻击的缓解阶段:当路由器检测出受到攻击,即向下游节点发送告知包(alert message),告知包是未经请求的内容包,用于传达正在进行的兴趣包洪泛攻击的信息。使用内容包有两个原因:(1)攻击期间,下一跳的PIT可能已满,无法接收兴趣包,而可以接收内容包;(2)内容包可以签名,而兴趣包不可以,这可以防止伪造的告知包。告知包允许在离目的受害者很远的地方就可以检测出兴趣包洪泛攻击。

      5、评估实验:设置Ω(rij)=3,P(rij)=1/8 PIT Size。缩减比例因子为s=2,等待时间wait_time=60ms。

作者:gongxifacai_believe 发表于2017/3/21 1:45:24 原文链接
阅读:24 评论:0 查看评论

【NDN安全】Coordination Supports Security: A New Defence Mechanism Against Interest Flooding in NDN 学习笔记

$
0
0

1、之前提出的兴趣包洪泛攻击缓解策略存在下面的缺陷:

     (1)攻击检测比较困难,且并不精确,特别是对于分布式低速率兴趣洪泛攻击,因为可观察到的流量相对较小。与此相反,由于存在大量的攻击流量,靠近目标检测的路由器可能不能承受大量的攻击流量。

     (2)由于不能区分合法包和恶意包,合法的请求也可能受到影响。

     (3)每个路由器都需要执行攻击检测和缓解,路由器之间的协作需要较高的通信开销。

2、本文改写了CoMon框架,这是一个用于协调NDN中与缓存相关的策略的框架。

3、兴趣包洪泛攻击的缓解机制有以下5点原则:

     (1)对于低速率分布式兴趣包洪泛攻击,不能够在单独的节点上自动检测,而是基于包传输和转发状态的汇聚信息。

     (2)兴趣包洪泛攻击的检测和缓解应该在尽早执行,在恶意兴趣包消耗过多资源之前执行。

     (3)重复的攻击检测和对于攻击的过度反应应该被避免。

     (4)该机制应该能够区分合法兴趣包和恶意兴趣包,以避免损害合法流量。

     (5)协同机制的开销应该较低。

4、网络中共有3个角色:域控制器(Domain Controller, DC)、NDN路由器(NRs)、监控路由器(Monitoring Routers, MRs)。

      域控制器控制监控路由器监控网络内NDN路由器每个接口PIT条目的超时数目,以找出恶意接口和恶意包的名字前缀。监控路由器周期性地报告他们观察到的结果的汇总信息给域控制器,而域控制器返回给监控路由器整个域内正在进行的攻击的汇总信息。该套机制可用来缓解可能的兴趣包洪泛攻击。

      为了避免重复检测,监控路由器不检测之前被另一个监控路由器检测过的兴趣包。一旦一个兴趣包被监控路由器第一次捕获到,这个路由器即将兴趣包中增加一位,叫做“Checked”,设置为1。为了避免过度反应,每个兴趣包仅在第一次遇到监控路由器时决定是否做出反应。


作者:gongxifacai_believe 发表于2017/3/21 2:48:10 原文链接
阅读:75 评论:0 查看评论

Leetcode94——Binary Tree Inorder Traversal

$
0
0

文章作者:Tyan
博客:noahsnail.com  |  CSDN  |  简书

1. 问题描述

Given a binary tree, return the inorder traversal of its nodes’ values.

For example:
Given binary tree [1,null,2,3],

   1
    \
     2
    /
   3

return [1,3,2].

2. 求解

这个题就是一个树的中序遍历问题,最简单的方案就是递归的遍历子树,要注意递归退出的条件。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<Integer>();
        if(root == null) {
            return list;
        }
        List<Integer> left = inorderTraversal(root.left);
        List<Integer> right = inorderTraversal(root.right);
        list.addAll(left);
        list.add(root.val);
        list.addAll(right);
        return list;
    }
}
作者:Quincuntial 发表于2017/3/21 18:29:59 原文链接
阅读:127 评论:0 查看评论

Leetcode144——Binary Tree Preorder Traversal

$
0
0

文章作者:Tyan
博客:noahsnail.com  |  CSDN  |  简书

1. 问题描述

Given a binary tree, return the preorder traversal of its nodes’ values.

For example:
Given binary tree {1,#,2,3},

   1
    \
     2
    /
   3

return [1,2,3].

2. 求解

这个题就是一个树的先序遍历问题,最简单的方案就是递归的遍历子树,要注意递归退出的条件。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<Integer>();
        if(root == null) {
            return list;
        }
        list.add(root.val);
        List<Integer> left = preorderTraversal(root.left);
        List<Integer> right = preorderTraversal(root.right);
        list.addAll(left);
        list.addAll(right);
        return list;
    }
}
作者:Quincuntial 发表于2017/3/21 18:30:44 原文链接
阅读:160 评论:0 查看评论

Oracle Database 12c中的新进程

$
0
0

转自:


APPLIES TO:

Oracle Database - Enterprise Edition - Version 12.1.0.1 and later
Information in this document applies to any platform.

PURPOSE

This article provides information on new background processes introduced in 12c

A complete list of background processes can be found in the Oracle Documentation:
https://docs.oracle.com/database/121/REFRN/GUID-86184690-5531-405F-AA05-BB935F57B76D.htm#REFRN104

DETAILS

*  BWnn  There can be 1 to 100 Database Writer Processes. The names of the first 36 Database Writer Processes are DBW0-DBW9 and DBWa-DBWz. The names of the 37th through 100th Database Writer Processes are BW36-BW99. The database selects an appropriate default setting for the DB_WRITER_PROCESSES parameter or adjusts a user-specified setting based on the number of CPUs and processor groups.

 


*  FENC (Fence Monitor Process) Processes fence requests for RDBMS instances which are using Oracle ASM instances




*  IPC0 (IPC Service Background Process) Common background server for basic messaging and RDMA primitives based on IPC (Inter-process communication) methods.



* LDDn (Global Enqueue Service Daemon Helper Slave) Helps the LMDn processes with various tasks



* LGnn (Log Writer Worker) On multiprocessor systems, LGWR creates worker processes to improve the performance of writing to the redo log. LGWR workers are not used when there is a SYNC standby destination. Possible processes include LG00-LG99.



*LREG  (Listener Registration Process) Registers the instance with the listeners

 

*OFSD (Oracle File Server Background Process) Serves file system requests submitted to an Oracle instance



* RPOP (Instant Recovery Repopulation Daemon) Responsible for re-creating and/or repopulating data files from snapshot files and backup files



*  SAnn (SGA Allocator) Allocates SGA  The SAnn process allocates SGA in small chunks. The process exits upon completion of SGA allocation.



*  SCRB (ASM Disk Scrubbing Master Process) Coordinates Oracle ASM disk scrubbing operations




* SCRn  (ASM Disk Scrubbing Slave Repair Process) Performs Oracle ASM disk scrubbing repair operation

 

* SCVn  (ASM Disk Scrubbing Slave Verify Process) Performs Oracle ASM disk scrubbing verify operation

作者:msdnchina 发表于2017/3/21 18:35:35 原文链接
阅读:162 评论:0 查看评论

【PMP】PMBOK 笔记 第3章 项目管理过程

$
0
0

第3章 项目管理过程

过程是为创建预定的产品、服务或成果而执行的一系列相互关联的行动和活动

每个过程都有各自的输入工具和技术及相应输出

事业环境因素则可能限制项目管理的灵活性。

  • 项目管理过程(4-13章)
  • 产品导向过程

从项目开始到结束,项目管理过程和产品导向过程始终彼此重叠、相互作用。

裁剪-> 项目经理及其团队应该认真考虑每个过程及其输入和输出,确定哪些过程适用于他们正在从事的项目。

项目需要从组织内外部获取输入数据,并向组织交付所形成的能力。

五大项目管理过程组
- 启动过程组
- 规划过程组
- 执行过程组
- 监控过程组
- 收尾过程组

总结

本书介绍了5个管理过程组。

重点是表 3-1 项目管理过程组与知识领域

3.1 项目管理过程间的相互作用

项目管理的整合性质要求监控过程组与其他所有过程组相互作用。

图 3-1 项目管理过程组

过程组极少是孤立的或一次性事件,而是在整个项目期间相互重叠

一个过程的输出通常成为另一个过程的输入,或者成为项目、子项目或项目阶段的可交付成果。

图 3-2 过程组在项目或阶段中的相互作用

3.2 项目管理过程组

五大过程组有清晰的相互依赖关系,通常在每个项目中都需要执行,而且彼此之间有很强的相互作用。

它们与应用领域或行业无关。

在项目完成之前,往往需要反复实施各过程组及其过程。各过程可能在同一过程组内或跨越不同过程组相互作用。

事实上,在一个阶段中很可能会执行全部过程组。

图 3-3 项目管理过程组之间的相互作用

3.3 启动过程组

定义初步范围和落实初步财务资源,识别那些将相互作用并影响项目总体结果的内外部干系人,选定项目经理(如果尚未安排)。

一旦项目章程获得批准,项目也就得到了正式授权。

项目边界指的是一个项目或项目阶段从获得授权的时间点到得以完成的时间点。

本组过程有助于设定项目愿景——需要完成什么。

让发起人、客户和其他干系人参与启动过程,可以建立对成功标准的共同理解,降低参与费用,提升可交付成果的可接受性,提高客户和其他干系人的满意度。

3.4 规划过程组

规划过程组包含明确项目范围,定义和优化目标,为实现目标制定行动方案的一组过程。

规划过程组制定用于指导项目实施的项目管理计划和项目文件。

渐进明细-> 由于项目管理的复杂性,可能需要通过多次反馈来做进一步分析。随着收集和掌握的项目信息或特性不断增多,项目很可能需要进一步规划。

3.5 执行过程组

满足项目规范要求,按照项目管理计划来协调人员和资源,管理干系人期望,以及**整合并实施项目活
动**。

项目执行的结果可能引发计划更新和基准重建,包括变更预期的活动持续时间、变更资源生产率与可用性,以及考虑未曾预料到的风险。

项目的一大部分预算将花费在执行过程组中。

3.6 监控过程组

监控过程组包含跟踪、审查和调整项目进展与绩效,识别必要的计划变更并启动相应变更的一组过程。

控制变更,推荐纠正措施,或者对可能出现的问题推荐预防措施

确保只有经批准的变更才能付诸执行

监控过程组不仅监控某个过程组内正在进行的工作,而且监控整个项目工作

3.7 收尾过程组

当本过程组完成时,就表明为完成某一项目或项目阶段所需的所有过程组的所有过程均已完成,标志着项目或项目阶段正式结束

本过程组也用于正式处理项目提前结束的情形。
提前结束的项目可能包括:中止的项目、取消的项目或有严重问题的项目。

主要工作
- 获得客户或发起人的验收,以正式结束项目或阶段
- 进行项目后评价或阶段结束评价
- 对组织过程资产进行适当更新
- 所有相关项目文件在项目管理信息系统中归档,以便作为历史数据使用
- 对团队成员进行评估,释放项目资源

3.8 项目信息

  • 工作绩效数据。正在执行的活动中收集到的原始观察结果和测量值
  • 工作绩效信息。进行整合分析而得到的绩效数据
  • 工作绩效报告。汇编工作绩效信息,所形成的实物或电子项目文件

图 3-5 项目数据、信息和报告流向

3.9 知识领域的作用

47 个项目管理过程被进一步归组于十大知识领域。

图 3-6 数据流向图的图例

下图为本书的重点~

表 3-1 项目管理过程组与知识领域

表 3-1 项目管理过程组与知识领域

作者:diandianxiyu 发表于2017/3/21 18:53:16 原文链接
阅读:89 评论:0 查看评论
Viewing all 35570 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>