
暂无个人介绍
在谈述函数调用和返回值问题之前,先来看看C++中内存分配的问题。 C++编译器将计算机内存分为代码区和数据区,很显然,代码区就是存放程序代码,而数据区则是存放程序编译和执行过程出现的变量和常量。数据区又分为静态数据区、动态数据区,动态数据区包括堆区和栈区。 以下是各个区的作用: (1)代码区:存放程序代码; (2)数据区 a.静态数据区: 在编译器进行编译的时候就为该变量分配的内存,存放在这个区的数据在程序全部执行结束后系统自动释放,生命周期贯穿于整个程序执行过程。 b.动态数据区:包括堆区和栈区 堆区:这部分存储空间完全由程序员自己负责管理,它的分配和释放都由程序员自己负责。这个区是唯一一个可以由程序员自己决定变量生存期的区间。可以用malloc,new申请对内存,并通过free和delete释放空间。如果程序员自己在堆区申请了空间,又忘记将这片内存释放掉,就会造成内存泄露的问题,导致后面一直无法访问这片存储区域。 栈区:存放函数的形式参数和局部变量,由编译器分配和自动释放,函数执行完后,局部变量和形参占用的空间会自动被释放。效率比较高,但是分配的容量很有限。 注意:1)全局变量以及静态变量存放在静态数据区; 2)注意常量的存放区域,通常情况下,常量存放在程序区(程序区是只读的,因此任何修改常量的行为都是非法的),而不是数据区。有的系统,也将部分常量分配到静态数据区,比如字符串常量(有的系统也将其分配在程序区)。但是要记住一点,常量所在的内存空间都是受系统保护的,不能修改。对常量空间的修改将造成访问内存出错,一般系统都会提示。常量的生命周期一直到程序执行结束为止。 在弄懂内存分配的问题过后,来看看函数调用的过程: 执行某个函数时,如果有参数,则在栈上为形式参数分配空间(如果是引用类型的参数则类外),继续进入到函数体内部,如果遇到变量,则按情况为变量在不同的存储区域分配空间(如果是static类型的变量,则是在进行编译的过程中已经就分配了空间),函数内的语句执行完后,如果函数没有返回值,则直接返回调用该函数的地方(即执行远点),如果存在返回值,则先将返回值进行拷贝传回,再返回执行远点,函数全部执行完毕后,进行退栈操作,将刚才函数内部在栈上申请的内存空间释放掉。 下面通过几个例子来谈谈内存分配和函数返回值的问题: 内存分配的问题: int a=1; a在栈区 char s[]="123"; s在栈区,“123”在栈区,其值可以被修改 char *s="123"; s在栈区,“123”在常量区,其值不能被修改 int *p=new int; p在栈区,申请的空间在堆区(p指向的区域) int *p=(int *)malloc(sizeof(int)); p在栈区,p指向的空间在堆区 static int b=0; b在静态区 1.test1 #include<iostream>using namespace std;void test(int *p){ int b=2; p=&b; cout<<p<<endl;}int main(void){ int a=10; int *p=&a; cout<<p<<endl; test(p); cout<<p<<endl; return 0;} 第一行输出和第三行输出的结果相同,而第一行、第三行与第二行输出的结果不同。从这里可以看出,当指针作为参数进行传递时传递的也只是一个值,只不过该值只一个地址,因此对于形参的改变并不影响实参。 2.test2 #include<iostream>using namespace std;char* test(void){ char str[]="hello world!"; return str;}int main(void){ char *p; p=test(); cout<<p<<endl; return 0;} 输出结果可能是hello world!,也可能是乱麻。 出现这种情况的原因在于:在test函数内部声明的str数组以及它的值"hello world”是在栈上保存的,当用return将str的值返回时,将str的值拷贝一份传回,当test函数执行结束后,会自动释放栈上的空间,即存放hello world的单元可能被重新写入数据,因此虽然main函数中的指针p是指向存放hello world的单元,但是无法保证test函数执行完后该存储单元里面存放的还是hello world,所以打印出的结果有时候是hello world,有时候是乱麻。 3.test3 #include<iostream>using namespace std;int test(void){ int a=1; return a;}int main(void){ int b; b=test(); cout<<b<<endl; return 0;} 输出结果为 1 有人会问为什么这里传回来的值可以正确打印出来,不是栈会被刷新内容么?是的,确实,在test函数执行完后,存放a值的单元是可能会被重写,但是在函数执行return时,会创建一个int型的零时变量,将a的值复制拷贝给该零时变量,因此返回后能够得到正确的值,即使存放a值的单元被重写数据,但是不会受到影响。 4.test4 #include<iostream>using namespace std;char* test(void){ char *p="hello world!"; return p;}int main(void){ char *str; str=test(); cout<<str<<endl; return 0;} 执行结果是 hello world! 同样返回的是指针,为什么这里会正确地打印出hello world1?这是因为char *p="hello world!",指针p是存放在栈上的,但是"hello world!”是一个常量字符串,因此存放在常量区,而常量区的变量的生存期与整个程序执行的生命期是一样的,因此在test函数执行完后,str指向存放“hello world!”的单元,并且该单元里的内容在程序没有执行完是不会被修改的,因此可以正确输出结果。 5.test5 #include<iostream>using namespace std;char* test(void){ char *p=(char *)malloc(sizeof(char)*100); strcpy(p,"hello world"); return p;}int main(void){ char *str; str=test(); cout<<str<<endl; return 0;} 运行结果 hello world 这种情况下同样可以输出正确的结果,是因为是用malloc在堆上申请的空间,这部分空间是由程序员自己管理的,如果程序员没有手动释放堆区的空间,那么存储单元里的内容是不会被重写的,因此可以正确输出结果。 6.test6 #include<iostream>using namespace std;void test(void){ char *p=(char *)malloc(sizeof(char)*100); strcpy(p,"hello world"); free(p); if(p==NULL) { cout<<"NULL"<<endl; }}int main(void){ test(); return 0;} 没有输出 在这里注意了,free()释放的是指针指向的内存!注意!释放的是内存,不是指针!这点非常非常重 要!指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针还是存在!只不过现在指针指向的内容的垃圾,是未定义的,所以说是垃圾。因此,释放内存后应把把指针指向NULL,防止指针在后面不小心又被使用,造成无法估计的后果。 本文转载自海 子博客园博客,原文链接:http://www.cnblogs.com/dolphin0520/archive/2011/04/04/2005061.html如需转载自行联系原作者
关于tomcat作为服务器 URL访问的一些问题 由于tomcat对中文支持不是很好,所以在某些情况下导致URL无法访问或者找不到路径的问题,一般主要存在两个问题: 1.含有中文的URL无法访问 上传一个资源到服务器后,通过连接无法进行访问,进行几次尝试之后,发现如果URL包含中文字符则无法访问,而纯英文字符的URL则可以访问。网上查资料发现是tomcat默认的配置不支持中文路径访问,因为通过链接进行访问时采用的是get协议,而默认的get协议是采用ISO-8859-1对URL进行编码的,而这个字符集不支持中文双字节信息。 在Server.xml文件中添加一个名为URIEncoding的属性,它定义了对HTTP请求中的get方法传过来的URL进行编码的采用的方案。 在Tomcat安装目录下找到server.xml文件,找到 <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> 在里面加入URIEncoding="utf-8" 这个属性,保存,然后重启tomcat即可。 2.含有空格的URL无法访问 在下载一个mp3文件的时候,如果它的资源URL为"http:10.0.0.2:8080/MusicServer/resource/今天 - 刘德华.mp3",路径中含有空格和中文字符,会报找不到该资源的错误。报这种错误主要有两个原因:1)没有对中文部分进行转码;2)路径中空格要进行转换。 例如: String urlString="http:10.0.0.2:8080/MusicServer/resource/今天 - 刘德华.mp3"; String name="今天 - 刘德华.mp3"; String temp1=URLEncoder.encode(name, "UTF-8"); System.out.println(temp1); 输出结果为:%E4%BB%8A%E5%A4%A9+-+%E5%88%98%E5%BE%B7%E5%8D%8E.mp3 发现空格被转码成'+'了,而在tomcat服务器中,空格是'%20',所以会导致无法访问到该路径,可以采用下面的办法解决问题: 首先将中文部分转码成UTF-8格式的字符串,然后将转换后得到的字符串中的所有'+'替换成'%20'。 String urlString="http:10.0.0.2:8080/MusicServer/resource/今天 - 刘德华.mp3"; String name="今天 - 刘德华.mp3"; String temp1=URLEncoder.encode(name, "UTF-8"); String temp2=temp1.replaceAll("\\+", "%20"); //因为'+'是关键字,所以要进行转义 System.out.println(temp1); System.out.println(temp2); 输出结果就为: %E4%BB%8A%E5%A4%A9+-+%E5%88%98%E5%BE%B7%E5%8D%8E.mp3 %E4%BB%8A%E5%A4%A9%20-%20%E5%88%98%E5%BE%B7%E5%8D%8E.mp3 是正确的结果了。 本文转载自海 子博客园博客,原文链接:http://www.cnblogs.com/dolphin0520/archive/2012/03/28/2421922.html如需转载自行联系原作者
Android ListView的item背景色设置以及item点击无响应等相关问题 在Android开发中,listview控件是非常常用的控件,在大多数情况下,大家都会改掉listview的item默认的外观,下面讲解以下在使用listview时最常见的几个问题。 1.如何改变item的背景色和按下颜色 listview默认情况下,item的背景色是黑色,在用户点击时是黄色的。如果需要修改为自定义的背景颜色,一般情况下有三种方法: 1)设置listSelector 2)在布局文件中设置item的background 3)在adapter的getview中设置 这三种方法都能达到改变item默认的背景色和按下颜色,下面来分别讲解,但是在这之前需要先写好selector.xml文件; <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@color/light_blue"></item> <item android:state_pressed="false" android:drawable="@color/sgray"></item> </selector> 在改变button或者listview的item默认背景色,就可以用到selector。drawable可以设置为色彩资源,也可以设置为图片资源。 1)设置listview的listSelector <ListView android:id="@+id/history_list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="#565C5D" android:dividerHeight="3dp" android:listSelector="@drawable/selector" android:cacheColorHint="@android:color/transparent"> </ListView> 2)在listitem的布局文件中设置background属性,下面是listitem的布局文件 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/selector"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="历史记录" android:textColor="#ffffff" android:textSize="20sp" android:layout_centerInParent="true"> </TextView> </RelativeLayout> 3)在adapter的getView方法中设置 if(convertView ==null) { convertView = LayoutInflater.from(context).inflate(R.layout.listitem, null); } convertView.setBackgroundResource(R.drawable.selector); 上述方法都能达到同样的效果,就是改变item默认的背景色和点击时的背景颜色,第三种方法最灵活,如果listview的奇数行和偶数行需要设置为不同的selector,只能用第三种方法。 2.包含button,checkbox等控件时点击无响应问题。 如果listitem里面包括button或者checkbox等控件,默认情况下listitem会失去焦点,导致无法响应item的事件,最常用的解决办法是在listitem的布局文件中设置descendantFocusability属性。 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="10dp" android:paddingBottom="10dp" android:paddingLeft="5dp" android:paddingRight="5dp" android:descendantFocusability="blocksDescendants"> <CheckBox android:id="@+id/history_item_checkbt" android:layout_height="30dp" android:layout_width="wrap_content" android:layout_centerVertical="true" android:layout_alignParentLeft="true" android:checked="false" > </CheckBox> <ImageView android:id="@+id/history_item_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@id/history_item_checkbt" android:background="@drawable/item_icon"> </ImageView> <Button android:id="@+id/history_item_edit_bt" android:layout_alignParentRight="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:text="编辑" android:textColor="#ffffff" android:textSize="14sp" android:background="@drawable/button_bg"> </Button> <TextView android:id="@+id/history_item_time_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:textColor="#565C5D" android:textSize="14sp" android:text="10-01 10:20" android:layout_marginRight="5dp" android:layout_toLeftOf="@id/history_item_edit_bt"> </TextView> <TextView android:id="@+id/history_item_title_tv" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_centerVertical="true" android:textColor="#565C5D" android:textSize="14sp" android:text="xxxxxxxxXXXXXXXXXXXXXXXX" android:ellipsize="end" android:maxLines="1" android:layout_toRightOf="@id/history_item_image" android:layout_toLeftOf="@id/history_item_time_tv" android:layout_marginLeft="3dp"> </TextView> </RelativeLayout>
阅读时编写代码的代码,经常看到一个代码: typedef void *HANDLE ,这是它背后的故事?怎么理解呢? 不明白的时候。这是非常美妙的感觉,后来我才知道这,这是typedef定义,就在void*键入罢了。那是,HANDLE相当于void *,们能够叫它披着句柄皮的指针(PS:指针和句柄是有差别的,在这说句废话); 对于void* 神通广大。由于它作为函数參数or函数返回值,可以接受不论什么类型的指针;也就是来者不拒,是指针就接受(so open ,Aha)。但应用的时候。应该注意,void * 必须指向详细的类型。比如: void * HappyPt; int* pi=static_cast<int*>HappyPt;; //注意喽,在这里详细到了int*哦! 详细使用方法例如以下所看到的: 1.还记得它吗? void * __cdecl memset(_Out_opt_bytecapcount_(_Size) void * _Dst, _In_ int _Val, _In_ size_t _Size); 这是memset这个函数的原型,在这里你能够毫不留情的把void* 换成HANDLE,memset就是为了将传递进来的地址開始的n个字节的值所有赋值成某个特定的值,所以不是必需知道是什么类型的指针。就用void类型指针取代了。 用作參数的时候,我们一般不关心传递进来的地址类型; 用作返回值的时候。通常是返回一个地址,至于这个地址你要做什么用那是你决定的。最常见的就是malloc了,它返回void类型指针作为分配好的内存区的首地址。至于是什么类型,就须要用户自己来指定了。 演示样例 typedef void *HANDLE; HANDLE m_exitThreadEvent; m_exitThreadEvent = CreateEvent(NULL,FALSE,FALSE,NULL); HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPTSTR lpName ); 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4654763.html,如需转载请自行联系原作者
1.下载并安装Simple DNS plus 2.界面例如以下: 3:点击 Records 4:新建一个 5:下一步 6:填上名字完毕 7:在Options里找到Forwarding 加入一些上级的DNS 就完毕了。 把DNS设置成自己的IP地址,检查能否够正常訪问站点。 版权声明:来自: 代码代码猿猿AC路 http://blog.csdn.net/ck_boss 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4755249.html,如需转载请自行联系原作者
终于效果图: Sqlite3函数总结 1.打开数据库 int sqlite3_open( const char *filename, // 数据库的文件路径 sqlite3 **ppDb // 数据库实例 ); 2.运行不论什么SQL语句 int sqlite3_exec( sqlite3*, // 一个打开的数据库实例 const char *sql, // 须要运行的SQL语句 int (*callback)(void*,int,char**,char**), // SQL语句运行完成后的回调 void *, // 回调函数的第1个參数 char **errmsg // 错误信息 ); 3.检查SQL语句的合法性(查询前的准备) int sqlite3_prepare_v2( sqlite3 *db, // 数据库实例 const char *zSql, // 须要检查的SQL语句 int nByte, // SQL语句的最大字节长度 sqlite3_stmt **ppStmt, // sqlite3_stmt实例,用来获得数据库数据 const char **pzTail ); 4.查询一行数据 int sqlite3_step(sqlite3_stmt*); // 假设查询到一行数据,就会返回SQLITE_ROW 5.利用stmt获得某一字段的值(字段的下标从0開始) double sqlite3_column_double(sqlite3_stmt*, int iCol); // 浮点数据 int sqlite3_column_int(sqlite3_stmt*, int iCol); // 整型数据 sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); // 长整型数据 const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); // 二进制文本数据 const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); // 字符串数据 控制器中直接写SQL语句,未封装 // // ViewController.m // 1.sqlite3基本操作 // // Created by xss on 14-11-2. // Copyright (c) 2014年 beyond. All rights reserved. // #import "ViewController.h" // 1.导入库,2.加入主头文件 #import <sqlite3.h> @interface ViewController () { // db代表着整个数据库。db是数据库实例 sqlite3 *_db; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 0.获得沙盒中的数据库文件名称 NSString *filename = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"student.sqlite"]; NSLog(@"filePath:%@",filename); /* 2014-11-02 18:32:38.895 1.sqlite3基本操作[85356:245858] filePath:/Users/juns/Library/Developer/CoreSimulator/Devices/3198E002-E3C9-4523-983E-AC3E1283A654/data/Containers/Data/Application/E1150608-3EB8-4B9D-87AF-33EDF9FB6FF3/Documents/student.sqlite 2014-11-02 18:32:38.896 1.sqlite3基本操作[85356:245858] 成功打开数据库 2014-11-02 18:32:38.897 1.sqlite3基本操作[85356:245858] 成功创建t_student表 */ // 1.创建(打开)数据库(假设是首次打开,则数据库文件不存在。那么会自己主动创建) // OC字符串,直接转成C语言字符串,通过 UTF8String方法 int result = sqlite3_open(filename.UTF8String, &_db); if (result == SQLITE_OK) { NSLog(@"成功打开数据库"); // 2.创表 const char *sql = "create table if not exists t_student (id integer primary key autoincrement, name text, age integer);"; // 凡是要传地址的,最好先清空,防止出现野指针,C语言中空是NULL char *errorMesg = NULL; // 參数3和4是回调时用 int result = sqlite3_exec(_db, sql, NULL, NULL, &errorMesg); if (result == SQLITE_OK) { NSLog(@"成功创建t_student表"); } else { NSLog(@"创建t_student表失败:%s", errorMesg); } } else { NSLog(@"打开数据库失败"); } } // 全然仿造createTable操作 - (IBAction)insertBtnClicked:(UIButton *)sender { for (int i = 0; i<30; i++) { NSString *name = [NSString stringWithFormat:@"beyond-%d", arc4random()%100]; int age = arc4random()%100; NSString *sql = [NSString stringWithFormat:@"insert into t_student (name, age) values('%@', %d);", name, age]; char *errorMesg = NULL; int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &errorMesg); if (result == SQLITE_OK) { NSLog(@"成功加入数据"); } else { NSLog(@"加入数据失败:%s", errorMesg); } } } // 方法同上 - (IBAction)deleteBtnClicked:(UIButton *)sender { } // 方法同上 - (IBAction)updateBtnClicked:(UIButton *)sender { } // - (IBAction)queryBtnClicked:(UIButton *)sender { // SQL注入漏洞 /** 登录功能 1.用户输入账号和password * 账号:123' or 1 = 1 or '' = ' * password:456654679 2.拿到用户输入的账号和password去数据库查询(查询有没有这个用户名和password) select * from t_user where username = '123' and password = '456'; select * from t_user where username = '123' and password = '456'; */ // 1.定义sql语句 const char *sql = "select id, name, age from t_student where name = ?;"; // 2.定义一个stmt存放结果集,用于运行静态 SQL 语句并返回它所生成结果的对象 sqlite3_stmt *stmt = NULL; // 3.检測SQL语句的合法性,參数3是sql语句的长度,仅仅要写-1,会自己主动计算,參数4是statement存放结果集 int result = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL); if (result == SQLITE_OK) { NSLog(@"查询语句是合法的"); // 设置占位符的内容,參数2 指的是第几个占位符号,注意是从1開始;參数4是占位符的长度,仅仅要写-1,会自己主动计算, sqlite3_bind_text(stmt, 1, "beyond", -1, NULL); // 4.step 运行SQL语句,从结果集中取出数据 // int stepResult = sqlite3_step(stmt); // step的运行结果等于SQLITE_ROW,表示真的查询到一行数据 while (sqlite3_step(stmt) == SQLITE_ROW) { // 获得这行相应的数据,结果存放在statement中 // 获得第0列的id int sid = sqlite3_column_int(stmt, 0); // 获得第1列的name const unsigned char *sname = sqlite3_column_text(stmt, 1); // 获得第2列的age int sage = sqlite3_column_int(stmt, 2); NSLog(@"%d %s %d", sid, sname, sage); } } else { NSLog(@"查询语句非合法"); } } @end 使用工具类封装 模型 // // Student.h // 2_数据库工具类封装 // // Created by xss on 14-11-2. // Copyright (c) 2014年 beyond. All rights reserved. // #import <Foundation/Foundation.h> @interface Student : NSObject // 学号 @property (nonatomic, assign) int ID; // 姓名 @property (nonatomic, copy) NSString *name; // 年龄 @property (nonatomic, assign) int age; @end 工具类StudentDAO // // StudentDAO.h // 2_数据库工具类封装 // // Created by xss on 14-11-2. // Copyright (c) 2014年 beyond. All rights reserved. // 学生数据的CRUD(增删改查) #import <Foundation/Foundation.h> @class Student; @interface StudentDAO : NSObject /** * 加入学生 * * @param student 须要加入的学生 */ + (BOOL)addStudent:(Student *)student; /** * 获得全部的学生 * * @return 数组中装着都是IWStudent模型 */ + (NSArray *)students; /** * 依据搜索条件获得相应的学生 * * @param condition 搜索条件 */ + (NSArray *)studentsWithCondition:(NSString *)condition; @end 关键封装的代码 // // StudentDAO.m // 2_数据库工具类封装 // // Created by xss on 14-11-2. // Copyright (c) 2014年 beyond. All rights reserved. // #import "StudentDAO.h" #import "Student.h" #import <sqlite3.h> @implementation StudentDAO // 重点~~~~加上static的作用:能保证_db这个变量仅仅被StudentDAO.m内部訪问 static sqlite3 *_db; // 重点~~~~工具类第一次载入的时候调用initialize方法 + (void)initialize { // 0.获得沙盒中的数据库文件名称 NSString *filename = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"student.sqlite"]; // 1.创建(打开)数据库(假设数据库文件不存在。会自己主动创建) int result = sqlite3_open(filename.UTF8String, &_db); if (result == SQLITE_OK) { NSLog(@"成功打开数据库"); // 2.创表 const char *sql = "create table if not exists t_student (id integer primary key autoincrement, name text, age integer);"; char *errorMesg = NULL; int result = sqlite3_exec(_db, sql, NULL, NULL, &errorMesg); if (result == SQLITE_OK) { NSLog(@"成功创建t_student表"); } else { NSLog(@"创建t_student表失败:%s", errorMesg); } } else { NSLog(@"打开数据库失败"); } for (int i = 0; i<30; i++) { NSString *name = [NSString stringWithFormat:@"beyond-%d", arc4random()%100]; int age = arc4random()%100; NSString *sql = [NSString stringWithFormat:@"insert into t_student (name, age) values('%@', %d);", name, age]; char *errorMesg = NULL; int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &errorMesg); if (result == SQLITE_OK) { NSLog(@"成功加入数据"); } else { NSLog(@"加入数据失败:%s", errorMesg); } } } + (BOOL)addStudent:(Student *)student { // Sqlite3中全部的字符串必须用单引號 NSString *sql = [NSString stringWithFormat:@"insert into t_student (name, age) values('%@', %d);", student.name, student.age]; char *errorMesg = NULL; // 两个NULL代表的是回调方法,此处不须要 int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &errorMesg); return result == SQLITE_OK; } // 返回全部的学生对象组成的数组 + (NSArray *)students { // 0.定义数组 NSMutableArray *students = nil; // 1.定义sql语句 const char *sql = "select id, name, age from t_student;"; // 2.定义一个stmt存放结果集 sqlite3_stmt *stmt = NULL; // 3.检測SQL语句的合法性 int result = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL); if (result == SQLITE_OK) { NSLog(@"查询语句是合法的"); students = [NSMutableArray array]; // 4.运行SQL语句,从结果集中取出数据 while (sqlite3_step(stmt) == SQLITE_ROW) { // 真的查询到一行数据 // 获得这行相应的数据 Student *student = [[Student alloc] init]; // 获得第0列的id student.ID = sqlite3_column_int(stmt, 0); // 获得第1列的name const unsigned char *sname = sqlite3_column_text(stmt, 1); student.name = [NSString stringWithUTF8String:(const char *)sname]; // 获得第2列的age student.age = sqlite3_column_int(stmt, 2); // 加入到数组 [students addObject:student]; } } else { NSLog(@"查询语句非合法"); } return students; } // 模糊查询 + (NSArray *)studentsWithCondition:(NSString *)condition { // 0.定义数组 NSMutableArray *students = nil; // 1.定义sql语句 带模糊查询 '%林%' const char *sql = "select id, name, age from t_student where name like ? ;"; // 2.定义一个stmt存放结果集 sqlite3_stmt *stmt = NULL; // 3.检測SQL语句的合法性 int result = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL); if (result == SQLITE_OK) { NSLog(@"查询语句是合法的"); students = [NSMutableArray array]; // 填补占位符的内容,%在OC中是keyword,因此转义 NSString *newCondition = [NSString stringWithFormat:@"%%%@%%", condition]; sqlite3_bind_text(stmt, 1, newCondition.UTF8String, -1, NULL); // 4.运行SQL语句,从结果集中取出数据 while (sqlite3_step(stmt) == SQLITE_ROW) { // 真的查询到一行数据 // 获得这行相应的数据 Student *student = [[Student alloc] init]; // 获得第0列的id student.ID = sqlite3_column_int(stmt, 0); // 获得第1列的name const unsigned char *sname = sqlite3_column_text(stmt, 1); student.name = [NSString stringWithUTF8String:(const char *)sname]; // 获得第2列的age student.age = sqlite3_column_int(stmt, 2); // 加入到数组 [students addObject:student]; } } else { NSLog(@"查询语句非法"); } return students; } @end 控制器中使用工具类为tableView提供数据源,而且监听搜索框的模糊查询 // // ViewController.m // 2_数据库工具类封装 // // Created by xss on 14-11-2. // Copyright (c) 2014年 beyond. All rights reserved. // #import "ViewController.h" #import "Student.h" #import "StudentDAO.h" @interface ViewController ()<UISearchBarDelegate> // 从数据库中返回的封装好的对象数组,为tableView提供数据源 @property (nonatomic, strong) NSArray *students; @end @implementation ViewController #pragma mark - 懒载入 - (NSArray *)students { if (_students == nil) { _students = [StudentDAO students]; } return _students; } - (void)viewDidLoad { [super viewDidLoad]; // 加入一个搜索框,并设置代理 UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)]; searchBar.delegate = self; // headView self.tableView.tableHeaderView = searchBar; } #pragma mark - 搜索框代理 - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { // 直接覆盖原来的对象数组 self.students = [StudentDAO studentsWithCondition:searchText]; // 刷新表格 [self.tableView reloadData]; } #pragma mark - tableView代理方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.students.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 1.创建cell static NSString *ID = @"student"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } // 2.设置cell的数据 Student *stu = self.students[indexPath.row]; cell.textLabel.text = stu.name; cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", stu.age]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self.view endEditing:YES]; } @end 版权声明:本文博主原创文章,博客,未经同意不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4865134.html,如需转载请自行联系原作者
称号 Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4]. Note: Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem. [show hint] Related problem: Reverse Words in a String II Credits: Special thanks to @Freezen for adding this problem and creating all test cases. 代码 public class Solution { public void rotate(int[] nums, int k) { int len=nums.length; if(k==0 || k==len) return; if(k>len) k=k-len; int[] result=new int[len]; int result_index=0; int j=0; for(int i=k;i>=1;i--){ result[result_index]=nums[len-i]; result_index++; } while(result_index<len){ result[result_index]=nums[j]; result_index++; j++; } for(int m=0;m<len;m++){ nums[m]=result[m]; } } } 代码下载:https://github.com/jimenbian/GarvinLeetCode /******************************** * 本文来自博客 “李博Garvin“ * 转载请标明出处:http://blog.csdn.net/buptgshengod ******************************************/ 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4680485.html,如需转载请自行联系原作者
在写手机卫士的时候,用户拨打|接听电话须要显示号码归属地,然后出现了一些异常,在此留下记号。希望对麻友们有帮助: BUG教程 在使用 view = View.inflate(this, R.layout.ui_toast, null);获得View对象后wm.addView出现错误: 10-12 14:29:06.166: E/AndroidRuntime(1268): Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@41087ed8 -- permission denied for this window type 解决的方法: 使用另外的方法获取: LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); mDesktopLayout = inflater.inflate(R.layout.volume_panel, null); 完整代码: LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); mDesktopLayout = inflater.inflate(R.layout.volume_panel, null); // 取得系统窗口 mWindowManager = (WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE); // 窗口的布局样式 mLayoutParams = new WindowManager.LayoutParams(); // 设置窗口显示类型――TYPE_SYSTEM_ALERT(系统提示) mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; // 设置窗口焦点及触摸: // FLAG_NOT_FOCUSABLE(不能获得按键输入焦点) mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 设置显示的模式 mLayoutParams.format = PixelFormat.RGBA_8888; // 设置对齐的方法 mLayoutParams.gravity = Gravity.TOP | Gravity.LEFT; // 设置窗口宽度和高度 mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; // 设置窗口显示的位置。否则在屏幕中心显示 mLayoutParams.x = 50; mLayoutParams.y = 50; mWindowManager.addView(mDesktopLayout, mLayoutParams); 问题总结 这两种方式显示出来的窗体都不会激发当前Activity的onPause()事件。据说还能够先一个窗体风格的Activity。只是显示时会激发当前窗体的onPause()事件。详细咋样没试过。 推荐风格 <?xml version="1.0" encoding="utf-8"? > <resources> <style name="selectorDialog" parent="@Android:style/Theme.Dialog"> <item name="android:windowFrame">@null</item><!--边框--> <item name="android:windowIsFloating">true</item><!--是否浮如今activity之上--> <item name="android:windowIsTranslucent">false</item><!--半透明--> <item name="android:windowNoTitle">true</item><!--无标题--> <!--<item name="android:windowBackground">@drawable/selector_dialog_bg</item>背景透明--> <item name="android:backgroundDimEnabled">false</item><!--模糊--> <item name="android:backgroundDimAmount">0.6</item> </style> </resources> OK,谢谢关注破晓博客 版权声明:本文博客原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4734812.html,如需转载请自行联系原作者
php接收HTML当表单提交的信息,数据将存储提交在全局阵列中,我们能够调用系统特定的自己主动全局变量数组来获取这些值。经常使用的自己主动全局变量例如以下所看到的:$_GET$_POST$_REQUEST 在获取表单数据中,最经常使用的自己主动全局变量是$_GET和$_POST,它们分别获取通过GET方法提交的数据和通过POST方法提交的数据。 比方一个名称为"txtAge"的文本框表单控件。假设用GET方法提交。能够用 $_GET["txtAge"]或者$_GET['txtAge'] 获取它提交的值。 $_REQUEST自己主动全局变量包括了全部GET、POST、COOKIE和FILE的数据,如不关心数据来源,能够用 $_REQUEST["txtAge"]或$_REQUEST['txtAge']来获取提交的数据。 以下是一个简单的获取提交数据的实例: <?php echo("你的帐号是:" . $_POST['login']); //输出帐号 echo("<br>"); echo("你的姓名是:" .$_POST['yourname'] ); //输出姓名 echo( "<br>"); echo("你的password是:" . $_POST['passwd'] ); //输出password echo("<br>"); echo("你的查询password问题是:" . $_POST['question'] ); //查询password问题 echo("<br>"); echo("你的查询password答案是:" . $_POST['question2'] ); //查询password答案 echo("<br>"); echo("你的出生日期是:" . $_POST['byear'] ."年". $_POST['bmonth'] . "月" . $_POST['bday'] . "日" ); //出生日期 echo("<br>"); echo("你的性别是:" . $_POST['gender']); //性别 echo("<br>"); echo("你的爱好是:<br>" ); //爱好 foreach ($_POST['hobby'] as $hobby) { echo($hobby . "<br>"); } ?> 对应的表单代码例如以下: <html> <head> <title> 用户调查表 </title> </head> <body> 欢迎光临本站点。请首先输入下面个人资料:<br> <form method=post action="baidu.php"> 帐号:<INPUT maxLength=25 size=16 name=login><br> 姓名:<INPUT type=password size=19 name=yourname ><br> password:<INPUT type=password size=19 name=passwd ><br> 确认password:<INPUT type=password size=19 name=passwd ><br> 查询password问题:<br> <select name=question> <option selected value="">--请您选择--</option> <option value="我的宠物名字?">我的宠物名字?</option> <option value="我最好的朋友是谁?">我最好的朋友是谁?</option> <option value="我最喜爱的颜色?">我最喜爱的颜色?</option> <option value="我最喜爱的电影?">我最喜爱的电影?</option> <option value="我最喜爱的影星?">我最喜爱的影星?</option> <option value="我最喜爱的歌曲?">我最喜爱的歌曲?</option> <option value="我最喜爱的食物?">我最喜爱的食物?</option> <option value="我最大的爱好?">我最大的爱好?</option> </select> <br> 查询password答案:<input name="question2" size="18"><br> 出生日期: <select name="byear" id="BirthYear" tabindex=8> <?php for($i=1930;$i<=2009;$i++){ echo "<option value='$i'>" . $i ."年</option>"; } ?> </select> <select name="bmonth" id="BirthYear" tabindex=8> <?php for($i=1;$i<=12;$i++){ echo "<option value='$i'>" . $i ."月</option>"; } ?> </select> <select name="bday" id="BirthYear" tabindex=8> <?php for($i=1;$i<=30;$i++){ echo "<option value='$i'>" . $i ."日</option>"; } ?> </select> <br> 性别:<input type="radio" name="gender" value="1" checked> 男 <input type="radio" name="gender" value="2" > 女 <br> 请选择你的爱好:<br> <input type="checkbox" name="hobby[]" value="dance" >跳舞<br> <input type="checkbox" name="hobby[]" value="tour" >旅游<br> <input type="checkbox" name="hobby[]" value="sing" >唱歌<br> <input type="checkbox" name="hobby[]" value="dance" >打球<br> <input type="submit" value="提交"> <input type="reset" value="重填"> <br> </body> <html> 版权声明:本文博客原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4736288.html,如需转载请自行联系原作者
一个:MySQL标准数据库优化注意事项 1.数据库设计(表设计合理)三范式(规范的模式) 三范式包含: 第一范式:1NF是对属性的原子性的约束。要求属性具有原子性,不可再分解。(仅仅要是关系型数据库都满足) 第二范式:2NF是记录的唯一性约束,要求记录有唯一标识。即实体的唯一性。(设立主键) 第三范式:3NF是对字段冗余性约束,即不论什么字段不能由其它字段派生出来。要求字段没有冗余。 (通过表外键) 逆范式(适当的冗余):提高查询效率。 PS:冗余应当放在记录尽量少的表上。避免造成空间浪费。. 2.sql语句优化 3.数据库參数的配置(缓存大小) 4.恰当的硬件资源和操作系统 二:sql语句优化步骤 1.通过show status命令了解各种sql的运行效率 show status命令能够显示你的MySQL数据库的当前状态。 关心"Com_"打头的数据语句。 显示当前控制台的MySQL情况: show status like "Com%" ; <=> show session status like "Com%"; 显示数据库从启动到此时的情况: show global status like "Com%"; 显示连接数据库的次数: show status like "Connections"; 显示server工作了的时间: show status like "Uptime"; 显示慢查询的次数(默认是10s): show status like "slow_queries"; 显示慢查询时间: show variables like "long_query_time" 设置慢查询时间(2s): set long_query_time=2; 2.定位到运行效率较低的sql语句 MySQL数据库支持将慢查询语句记录到日志中,供程序员分析(默认情况下不启动日志功能)。启动:进入到MySQL的安装文件夹bin下 mysqld.exe --slow-query-log. //以日志功能方式启功MySQL 3.通过explain 分析低效率的sql语句的运行情况 explain一款很重要的工具。这个分析工具能够对sql语句进行分析能够预測sql的运行效率。 4.确定问题并提供对应的优化措施 三:sql语句的几种类型 ddl(数据库定义语言):create,alter,drop dml(数据库操作语言):insert,delete,update select dtl(数据库事务语言):commit,rollback,savepoint dcl(数据库控制语言):grant,revoke 四:数据库存储引擎MyISAM和InnoDB比較 1.MyISAM既不支持外键也不支持事务。InnoDB都支持。 2.假设存储引擎是MyISAM的,则当创建一个表后有三个文件: *.frm(记录表结构),*.myd(记录数据),*.myI(记录索引) InnoDB仅仅相应一个文件*.frm。数据存储在ibdata1文件里。 3.对于MyISAM存储引擎数据库要定时清理: 运行命令:optimize table 表名; 五:sql语句优化之加入索引 索引的原理:对于MyISAM存储引擎。索引是加入在.myI文件里。数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就能够在这些数据结构上实现高级查找算法。这样的数据结构。就是索引。再次查询速度将明显变快,可是牺牲了删除,改动,加入表数据的代价。 索引的类型: 1.主键索引。主键自己主动的为主索引(类型为Primary)主键自带索引 2.唯一索引(UNIQUE)。唯一性同一时候又是索引 3.普通索引(Index) 4.全文索引(FULLTEXT)。仅仅有MyISAM存储引擎支持 5.复合索引(多列和在一起)。create index 索引名 on 表名 (列1,列2); 创建索引: 1.create [UNIQUE / FULLTEXT] index 索引名 on 表名 (列名...); 2.alter table 表名 add index 索引名 (列名...); 3.假设加入主键索引:alter table 表名 add primary key(列名); 删除索引: 1.drop index 索引名 on 表名; 2.alter table 表名 drop index 索引名; 3.假设删除主键索引:alter table 表名 drop primary key; 查看某表的全部索引: 1.show indexes from 表名; 2.show keys from 表名; 3.desc 表名; ! !!PS! !!下列表查询将不使用索引: 1.假设查询条件中有or,即使当中有索引也不会使用(or指令要少用)。 2.对于使用多列索引的表,仅仅有最左边的列才干使用到索引,其余列则不会使用索引。 3.对于使用like查询。查询假设是"%aaa"不会使用到索引。"aaa%"则会使用到索引。 4.假设列类型是字符串,那一定要在条件中将数据使用引號引用起来。否则不会使用索引。 5.假设MySQL预计使用全表扫描要比使用索引快,则不使用索引。 查看索引的使用情况: show status like "Handler_read%"; 注意结果:Handler_read_key:这个值越高越好。越高表示使用索引查询到的次数。Handler_read_rnd_next:这个值越高,说明查询低效。 六:explain对sql语句的分析 比如:explain select * from emp where empno=2000\G; 会产生下面信息: select_type:表示查询的类型。 table:对哪张表查询。 type:表示表的连接类型。 possible_keys:表示查询时,可能使用的索引类型。 key:表示实际使用的索引类型。 key_len:索引的字段长度。 rows:扫描的行数。 Extra:运行情况的描写叙述和说明。 Type的三种类型: 1.ALL:完整的表扫描,通常不好。 eg:explain select * from emp\G; 2.system:表仅有一行,这是const连接类型的特例。 3.const:表最多有一个匹配行。 Extra分析: Notables:不存在表。 Using filesort:当Query中包括ORDER BY操作,并且无法利用索引进行排序。 Using temporary:某些操作必须使用暂时表,常见GROUP BY,ORDER BY。 Using where:不用读取表中全部信息。仅通过索引就能获取所需信息。 七:常见sql优化 1.大批量插入数据: 对于MyISAM存储引擎: alter table 表名 disable keys; //避免建立大量索引 loading data; alter table 表名 enable keys; 对于InnoDB存储引擎: 1.将要导入的数据依照主键排序 2.set unique_checks=0; 关闭唯一性校验 3.set autocommit=0; 关闭自己主动提交 2.优化group by语句 默认情况,MySQL对全部的group by列进行排序。这与在查询中指定order by列类似。 假设在查询中包含group by但用户想要避免查询结果的消耗,则能够使用order by null禁止排序 eg: select * from dept group by ename order by null; 3.假设在含有or的查询语句中利用索引。则or之间的每一个条件列都必须用到索引。假设没有索引,则应该考虑添加索引。 4.在精度要求高的应用中,建议使用定点数(decimal)来存储数值,不使用浮点数(float),以保证结果的准确性。 5.对于MyISAM的存储引擎的数据库,假设常常做删除和改动记录的操作,要定时运行optimize table 表名;对表进行碎片整理。 6.日期类型要依据实际须要选择最小存储的类型(timestamp:4个字节。datetime:8字节)。 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4746200.html,如需转载请自行联系原作者
JavaWeb-11 JSP&EL表达式 JSP 四、JSP语法(学好的关键:相应的Servlet) JavaWeb-10 总结:session技术也是cookie的一种。server给浏览器创建一个篮子,并加上编号,这编号会存储到client上,当client再次訪问server时。server会读取client的ID号。假设server找得到,就在篮子中拿出该client的session,若没有就新建一个 重点:URL重写。 1、JSP模版元素 JSP模板元素:HTML页面 JSP页面中的HTML内容称之为JSP模版元素。 JSP模版元素定义了网页的基本骨架。即定义了页面的结构和外观。 2、JSP表达式 JSP脚本表达式(expression)用于将程序数据输出到client 语法:<%= 变量或表达式 %> 举例:当前时间:<%= new java.util.Date() %> JSP引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在对应位置用out.print(…) 将数据输给client。 JSP脚本表达式中的变量或表达式后面不能有分号(;)。 注意:现实中不同意这么写,那是html,是美工开发框架用的。 写这么多java代码没意义。正规开发中不同意出现Jsp脚本 项目架构: 下面实验要使用到的User类: public class User { private String id ; private String username ; private int age ; public User() { } public User(String id, String username, int age) { super(); this.id = id; this.username = username; this.age = age; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } 实验:1.jsp <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>输出表达式</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <% //String name = "张三丰" ; request.setAttribute("name", "张三丰") ; String name = (String) request.getAttribute("name") ; out.write(name) ; %> <br> : <%=name %> </body> </html> 在浏览器输入http://localhost:8080/day1100jsp/1.jsp,IE结果: 3、JSP脚本片断 a、JSP脚本片断(scriptlet)用于在JSP页面中编写多行Java代码。语法: <% 多行java代码 %> 注意:JSP脚本片断中仅仅能出现java代码。不能出现其他模板元素, JSP引擎在翻译JSP页面中,会将JSP脚本片断中的Java代码将被原封不动地放到Servlet的_jspService方法中。 JSP脚本片断中的Java代码必须严格遵循Java语法,比如。每运行语句后面必须用分号(;)结束。 b、在一个JSP页面中能够有多个脚本片断,在两个或多个脚本片断之间能够嵌入文本、HTML标记和其它JSP元素。 举例: <% int x = 10; out.println(x); %> <p>这是JSP页面文本</p> <% int y = 20; out.println(y); %> 多个脚本片断中的代码能够相互訪问。宛如将全部的代码放在一对<%%>之中的情况。如:out.println(x); 正规开发中的JSP中不应出现java脚本:标签封装 c、单个脚本片断中的Java语句能够是不完整的,可是,多个脚本片断组合后的结果必须是完整的Java语句。比如: <% for (int i=1; i<5; i++) { %> <H1>www.it315.org</H1> <% } %> 实验:2.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>jsp脚本片段</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <table border = 1> <tr> <td>编号</td> <td>姓名</td> <td>年龄</td> </tr> <% List<User> list = new ArrayList<User>() ; list.add(new User("1","张三丰",20)) ; list.add(new User("2","张无忌",23)) ; list.add(new User("3","张翠山",25)) ; list.add(new User("4","张国老",28)) ; /*out.write("<table border = 1>") ; out.write("<tr><td>编号</td><td>姓名</td><td>年龄</td></tr>") ; for(int i = 0 ;i <list.size() ;i++){ User u = list.get(i) ; out.write("<tr><td>") ; out.write(u.getId()) ; out.write("</td><td>") ; out.write(u.getUsername()) ; out.write("</td><td>") ; out.write(u.getAge() + "") ; out.write("</td></tr>") ; }*/ // out.write("</table>") ; for(int i = 0 ;i<list.size() ;i++){ User u = list.get(i) ; %> <tr> <td><%=u.getId() %></td> <td><%=u.getUsername() %></td> <td><%=u.getAge() + "" %></td> </tr> <% } %> </table> </body> </html> 以上的底层Servlet源代码例如以下: 2jsp.java package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; import java.util.*; import com.heima.bean.*; public final class _2_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory(); private static java.util.List _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.AnnotationProcessor _jsp_annotationprocessor; public Object getDependants() { return _jspx_dependants; } public void _jspInit() { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName()); } public void _jspDestroy() { } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Object page = this; JspWriter _jspx_out = null; PageContext _jspx_page_context = null; try { response.setContentType("text/html;charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write('\r'); out.write('\n'); String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; out.write("\r\n"); out.write("\r\n"); out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n"); out.write("<html>\r\n"); out.write(" <head>\r\n"); out.write(" <base href=\""); out.print(basePath); out.write("\">\r\n"); out.write(" \r\n"); out.write(" <title>jsp脚本片段</title>\r\n"); out.write(" \r\n"); out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n"); out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n"); out.write("\t<meta http-equiv=\"expires\" content=\"0\"> \r\n"); out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n"); out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n"); out.write("\t<!--\r\n"); out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n"); out.write("\t-->\r\n"); out.write("\r\n"); out.write(" </head>\r\n"); out.write(" \r\n"); out.write(" <body>\r\n"); out.write(" \t\t<table border = 1>\r\n"); out.write(" \t\t <tr>\r\n"); out.write("\t\t\t\t<td>编号</td>\r\n"); out.write("\t\t\t\t<td>姓名</td>\r\n"); out.write("\t\t\t\t<td>年龄</td>\r\n"); out.write("\t\t\t</tr>\r\n"); out.write("\t\t"); List<User> list = new ArrayList<User>() ; list.add(new User("1","张三丰",20)) ; list.add(new User("2","张无忌",23)) ; list.add(new User("3","张翠山",25)) ; list.add(new User("4","张国老",28)) ; /*out.write("<table border = 1>") ; out.write("<tr><td>编号</td><td>姓名</td><td>年龄</td></tr>") ; for(int i = 0 ;i <list.size() ;i++){ User u = list.get(i) ; out.write("<tr><td>") ; out.write(u.getId()) ; out.write("</td><td>") ; out.write(u.getUsername()) ; out.write("</td><td>") ; out.write(u.getAge() + "") ; out.write("</td></tr>") ; }*/ // out.write("</table>") ; for(int i = 0 ;i<list.size() ;i++){ User u = list.get(i) ; out.write("\r\n"); out.write("\t\t\t<tr>\r\n"); out.write("\t\t\t\t<td>"); out.print(u.getId() ); out.write("</td>\r\n"); out.write("\t\t\t\t<td>"); out.print(u.getUsername() ); out.write("</td>\r\n"); out.write("\t\t\t\t<td>"); out.print(u.getAge() + "" ); out.write("</td>\r\n"); out.write("\t\t\t</tr>\r\n"); out.write("\t\t"); } out.write("\r\n"); out.write("\t\t</table>\r\n"); out.write(" </body>\r\n"); out.write("</html>\r\n"); } catch (Throwable t) { if (!(t instanceof SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else log(t.getMessage(), t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } } 在浏览器输入:http://localhost:8080/day1100jsp/2.jsp,输出结果: 3.1、JSP声明 <%! name = "啊啊啊"%>//全局变量 <% name = "啊啊啊"%>//局部变量 JSP页面中编写的全部代码,默认会翻译到servlet的service方法中, 而Jsp声明中的java代码被翻译到_jspService方法的外面。语法: <%! java代码 %> 所以。JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法 。 多个静态代码块、变量和函数能够定义在一个JSP声明中,也能够分别单独定义在多个JSP声明中。 JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些隐式对象。 实验: 3.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>jsp声明</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <%! String name = "小龙女" ; public static void demo(){ System.out.print("你好") ; } public void demo1(){ System.out.print("你好") ; } public class A{} %> <% demo1() ; demo() ; %> </body> </html> 在浏览器输入:http://localhost:8080/day1100jsp/3.jsp。在server输出的结果例如以下: 总结出来的在jsp编译环境下:事实上就是在HTML页面里,用标签编写的代码。会转成servlet类里的out.write()里的内容输出。而用<%%>括了的代码就会转成servlet类里的正常java代码 4、JSP凝视 <!--HTML凝视--> //这是java凝视 <%--<%这是jsp凝视%>--%>:这种凝视仅仅能在jsp文档里能够看见。把文档编译成了的servlet类文件就观察不到了,相当于隐身了。 实验: 4.jsp和servlet源代码 <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>jsp凝视</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <% //这是java凝视 %> <%--<% out.write("你好") ; %>--%> <!-- HTML凝视 --> </body> </html> 在浏览器输入:http://localhost:8080/day1100jsp/4.jsp, 可发现Servlet源代码例如以下: package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; import java.util.*; import com.heima.bean.*; public final class _4_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory(); private static java.util.List _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.AnnotationProcessor _jsp_annotationprocessor; public Object getDependants() { return _jspx_dependants; } public void _jspInit() { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName()); } public void _jspDestroy() { } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Object page = this; JspWriter _jspx_out = null; PageContext _jspx_page_context = null; try { response.setContentType("text/html;charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write('\r'); out.write('\n'); String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; out.write("\r\n"); out.write("\r\n"); out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n"); out.write("<html>\r\n"); out.write(" <head>\r\n"); out.write(" <base href=\""); out.print(basePath); out.write("\">\r\n"); out.write(" \r\n"); out.write(" <title>jsp凝视</title>\r\n"); out.write(" \r\n"); out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n"); out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n"); out.write("\t<meta http-equiv=\"expires\" content=\"0\"> \r\n"); out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n"); out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n"); out.write("\t<!--\r\n"); out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n"); out.write("\t-->\r\n"); out.write("\r\n"); out.write(" </head>\r\n"); out.write(" \r\n"); out.write(" <body>\r\n"); out.write(" \t\t"); //这是java凝视 out.write("\r\n"); out.write(" \t\t"); out.write("\r\n"); out.write(" \t\t<!-- HTML凝视 -->\r\n"); out.write(" </body>\r\n"); out.write("</html>\r\n"); } catch (Throwable t) { if (!(t instanceof SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else log(t.getMessage(), t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } } 5、JSP指令 JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生不论什么可见输出,而仅仅是告诉引擎怎样处理JSP页面中的其余部分。 在JSP 2.0规范中共定义了三个指令: a. page指令 b. Include指令 c. taglib指令 page指令:演示errorPage:当你的页面出现异常后你须要去哪个页面(错误处理页面)。 演示include指令:<%@ include file = "6.jsp"%> //静态包括,在6.jsp里不能有和5.jsp同样的一部分指令标签。也能够包括txt文档(a.txt)。 以上这样的叫静态包括,也是代码级别的包括,所包括的要使用的代码的其它代码能够删除掉! <%@ taglib %>:引入标签库 除了import指令标签能够反复。 、其它指令标签仅仅能写一遍 errorPage也能够在web.xml里配置(优先级高) <error-page> <error-code>404</error-code> <location></location> </error-page> 实验: 5.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8" errorPage="6.jsp" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>jsp指令标签</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <%response.setCharacterEncoding("UTF-8"); %> <%--<% // out.write(10/0) ; %>--%> aaaaaaaaaaaaaaaa <%@ include file="6.jsp" %> <br> <%@ include file="a.txt" %> </body> </html> 6.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8" isErrorPage="true" %> <body> server正忙。请一会再来訪问 <%--<% out.write(exception.getMessage()) ; %> --%> </body> 在浏览器输入:http://localhost:8080/day1100jsp/5.jsp。 浏览器输出下面结果: 6、JSP标签 <jsp:include>标签 :动态包括 page属性、它包括了其它路径的jsp时,里面反复的内容不用删除。 不像静态包括那样。 静态包括与动态包括之间的优缺点:静态包括(代码级别的包括。效率高)、动态包括(页面级别的包括,),他们结果没差别。 <jsp:forward>标签 : page属性:请求转发(地址栏是不变的),动态标签中的forward标签是须要配合param标签来使用吗?不一定。 <jsp:param>标签 : 怎么拿出10.jsp的param属性值,还有中文值们拿出是乱码怎么办?request.setCharacterEncodeing("UTF-8");重要)。主要用来传递參数。 value属性: name属性 实验:10.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>动作指令</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <%--<jsp:include page="11.jsp"></jsp:include>--%> <% request.setCharacterEncoding("UTF-8") ; %> <jsp:forward page="11.jsp?a=abc&addr=武当山"> <jsp:param value="bbbbb" name="b"/> <jsp:param value="张无忌" name="name"/> </jsp:forward> </body> </html> 11.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>动作指令</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body><%-- 111111111111111 <% out.write("你好") ; %> --%> <% String a = request.getParameter("a") ; String b = request.getParameter("b") ; String addr = request.getParameter("addr") ; String name = request.getParameter("name") ; // name = new String(name.getBytes("iso-8859-1"),"UTF-8") ; out.write(a + ":" + b + "<br>") ; out.write(name + ":" + addr + "<br>") ; %> </body> </html> 在浏览器输入:http://localhost:8080/day1100jsp/10.jsp,结果例如以下: 7、JSP内置对象 a、request b、response c、config d、application e、exception f、Session g、page h、out i、pageContext JSP九大隐式对象表示图 7.1、out隐式对象: a. out隐式对象用于向client发送文本数据。 b. out对象是通过调用pageContext对象的getOut方法返回的。其作用和使用方法与ServletResponse.getWriter方法返回的PrintWriter对象很相似。 c. JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性能够调整它的缓存大小,甚至关闭它的缓存。 d. 仅仅有向out对象中写入了内容,且满足例如以下不论什么一个条件时。out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中: e. 设置page指令的buffer属性关闭了out对象的缓存功能 f. out对象的缓冲区已满 g. 整个JSP页面结束 实验:7.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>out对象的细节</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <% out.write("12345") ; //out.flush() ; response.getWriter().write("67890") ; %> </body> </html> 在浏览器输入:http://localhost:8080/day1100jsp/7.jsp,输出结果例如以下: out对象总结: out.write("123"); reponse.getWriter().write("456"); 该两对象不一样。他们要输出的内容都先经过缓存,再由server整理在输出,而输出是先输出456 再123。根本原因是server会先清空out对象的缓存,那么out对象要输出的内容会把内容先存在reponse.getWriter()对象缓存里,当server要清空reponse.getWriter()对象缓存时,就会一起输出。所以是456 123 假设在指令标签的缓存属性设置xxx="0KB" 那么以上总结就不成立了,server会直接顺序输出以上内容。 7.2、pageContext对象 pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的执行环境,这个对象不仅封装了对其他8大隐式对象的引用。它自身还是一个域对象。能够用来保存数据。而且,这个对象还封装了web开发中经常涉及到的一些经常使用操作,比如引入和跳转其他资源、检索其他域对象中的属性等。jsp中最重要对象。底层代码的基础! 7.3、通过pageContext获得其它对象 getException方法返回exception隐式对象 getPage方法返回page隐式对象 getRequest方法返回request隐式对象 getResponse方法返回response隐式对象 getServletConfig方法返回config隐式对象 getServletContext方法返回application隐式对象 getSession方法返回session隐式对象 getOut方法返回out隐式对象 pageContext封装其他8大内置对象的意义,思考:假设在编程过程中。把pageContext对象传递给一个普通java对象。那么这个java对象将具有什么功能? 7.4、pageContext对象的方法 public void setAttribute(java.lang.String? name,java.lang.Object?value) public java.lang.Object?getAttribute(java.lang.String? name) public void?removeAttribute(java.lang.String?name) 7.5、pageContext对象中还封装了訪问其他域的方法 public java.lang.Object? getAttribute(java.lang.String?name,int? scope) public void setAttribute(java.lang.String? name, java.lang.Object?value,int?scope) public void?removeAttribute(java.lang.String? name,int? scope) 7.5、代表各个域的常量 PageContext.APPLICATION_SCOPE PageContext.SESSION_SCOPE PageContext.REQUEST_SCOPE PageContext.PAGE_SCOPE findAttribute方法 (*重点,查找各个域中的属性) EL表达式 PageContext代表jsp页面的执行环境,页面对象。也是一个域对象,封装了经常使用操作。 1、域对象(第四个域对象了。):范围在本页面 a、存储数据:setAttribute()、和它的重载(4个范围) b、能够将数据存放在其它范围中 c、查找方法findAttribute():要从page_Scope。Request_Scope。SESSION_Scope,APPLICATION_SCOPE范围依次去寻找,找不到返回null 2、提供了请求转发和包括 forward() include() 实验: 8.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>pageContext对象</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <!-- 1. 域对象: 范围在本页面 a. 存储数据 b. 能够将数据存放到其它范围中 c. 查找方法 findAttribute() : 要从Page_Scope,Request_SCOPE,sESSION_SCOPE,APPLICATION_SCOPE范围依次去 寻找,找不到返回空字符串 2. 提供了拿取其它8个对象的方法 3. 提供了请求转发和包括 --> <% pageContext.setAttribute("name", "东方不败") ; pageContext.setAttribute("name1", "张三丰",pageContext.REQUEST_SCOPE) ; String name = (String) pageContext.getAttribute("name") ; String name1 = (String) pageContext.getAttribute("name1") ; out.write(name) ; out.write(name1); pageContext.setAttribute("name2", "张无忌") ; request.setAttribute("name2", "张三丰") ; session.setAttribute("name2", "张翠山") ; application.setAttribute("name2", "张果老") ; // request.setAttribute("age", "123") ; // pageContext.getRequest().setAttribute("age", "123") ; %> <!-- <a href="http://blog.163.com/faith_yee/blog/9.jsp">9.jsp</a> --> <% //pageContext.forward("9.jsp") ; pageContext.include("9.jsp") ; %> <br> <%--<% String n = (String) pageContext.findAttribute("name2") ; out.write(n) ; %> --%></body> </html> 9.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>pageContext对象</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> 9999999999999999999<br> <% //String name = (String)request.getAttribute("name1") ; //out.write(name) ; String name = (String)pageContext.findAttribute("name2") ; out.write(name) ; %> </body> </html> 在浏览器输入:http://localhost:8080/day1100jsp/8.jsp,在浏览器输出结果例如以下: 五、JSP中操作JavaBean 5.1、JavaBean的概念: (VO:value Object, DO:Data Object 。POJO:最简单的java对象 ,DTO:Data Transfer Object)不同的场景不同的解释 遵循一定的命名规则: 1、必须有默认的构造方法 2、类的声明为public类型 3、字段都是私有的private boolean married 4、提供共同拥有的getter或setter方法(属性)。 通常是先java.io.Serializable接口 实际开发中有什么用?封装数据。便于传递数据 5.2、JavaWeb开发模型: MVC模型(model(JavaBean数据)+veiw(JSP显示)+controller(Servlet控制器)) 现实的样例:桌子+吧台+厨房(流程!) 三层架构:MVC仅仅是三层架构的表现层 三层架构:(表现层+业务逻辑层+数据訪问层) (耦合性低:兼容性扩展性强! ) 评价程序猿好坏:编出来的成品的扩展性。QQ。 更新换代这么多年非常大原因是项目扩展性好 JSP开发模式 : *SUN公司推出JSP技术后。同一时候也推荐了两种web应用程序的开发模式。一种是JSP+JavaBean模式(模型1)。一种是Servlet+JSP+JavaBean模式(模型2)。 *JSP+JavaBean模式适合开发业务逻辑不太复杂的web应用程序,这样的模式下。JavaBean用于封装业务数据。JSP即负责处理用户请求,又显示数据。 (计算器演示样例) *Servlet+JSP+JavaBean(MVC)模式适合开发复杂的web应用,在这样的模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装数据。 Servlet+JSP、JavaBean模式程序各个模块之间层次清晰,web开发推荐採用此种模式。(绘图MVC及三层架构) 5.3、jsp:useBean标签(重要内容:就是要封装标签里的内容!) <jsp:useBean>标签用来干什么的:创建对象的。 <!--User user = new User();--> 在这样的标签里能够创建对象(用来取代页面里的java代码) 属性 1、id 2、class:我是用哪个类创建的 3、scope:作用范围:(拿去bean中的数据,在实例里用动作标签拿不出还有一个jsp里的session属性,尽管session是共享的。而jsp里的java代码能够拿出,老师给我们展示底层的代码) 实验: 12.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>jsp:UseBean标签</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <!-- User user = new User() ; --> <jsp:useBean id="user" class="com.heima.bean.User" scope="session"> <jsp:setProperty property="username" name="user" value="张无忌"/> </jsp:useBean> <jsp:getProperty property="username" name="user"/> <a href="http://blog.163.com/faith_yee/blog/13.jsp">13.jsp</a> </body> </html> 13.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>jsp:UseBean标签</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <!-- 拿取bean中的数据 --> <!-- <jsp:getProperty property="username" name="user"/>--> <% User u = (User) session.getAttribute("user") ; out.write(u.getUsername()) ; %> </body> </html> 在浏览器输入http://localhost:8080/day1100jsp/12.jsp,输出结果例如以下: 在点击页面上的超链:进入了http://localhost:8080/day1100jsp/13.jsp,输出下面结果: 张无忌 5.4、jsp:useBean标签的内省机制 在jsp里怎么封装javaBean? 学习经验:假设搞不懂jsp怎么利用<jsp:useBean> 标签来封装JavaBean的话,能够观察jsp的底层代码:Servlet类的代码! <jsp:setProperty="*" name = "user"/>//内省 <jsp:getProperty property="id" name="user"/> <jsp:getProperty property="username" name="user"/> <jsp:getProperty property="age" name="user"/> 以上过程叫内省机制。 那么内省的底层是怎么回事? 内省要求Bean的属性名和页面上的表单控制的名字一样即可 实验: 14.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>jsp:UseBean标签的内省机制</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <form action="15.jsp" method="post"> 编号: <input type = "text" name = "id"><br> 姓名: <input type = "text" name = "username"><br> 年龄: <input type = "text" name = "age"><br> <input type = "submit" value = "提交"><br> </form> <a href="http://blog.163.com/faith_yee/blog/15.jsp?id=111&username=abc&age=100">15.jsp</a><%-- <jsp:forward page="15.jsp"> <jsp:param value="1000" name="id"/> <jsp:param value="nba" name="username"/> <jsp:param value="50" name="age"/> </jsp:forward> --%></body> </html> 15.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>jsp:UseBean标签的内省机制</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <% request.setCharacterEncoding("UTF-8") ; %> <jsp:useBean id="user" class="com.heima.bean.User"></jsp:useBean> <!-- 封装超链的数据 --> <jsp:useBean id="user1" class="com.heima.bean.User"></jsp:useBean> <jsp:setProperty property="*" name="user"/> <jsp:setProperty property="id" name="user" param="id"/> <jsp:setProperty property="*" name="user1"/> <jsp:getProperty property="id" name="user" />: <jsp:getProperty property="username" name="user"/>: <jsp:getProperty property="age" name="user"/> <hr> <jsp:getProperty property="id" name="user1"/>: <jsp:getProperty property="username" name="user1"/>: <jsp:getProperty property="age" name="user1"/> </body> </html> 在浏览器输入:http://localhost:8080/day1100jsp/14.jsp,页面例如以下: 在表单里填写例如以下信息: 点击提交: 或者在14.jsp页面里点击超链,结果例如以下: 在15.jsp里的总结 <!--封装超链的数据--> < .........> <jsp:setProperty="*" name = "user1"/>(内省! ) <jsp:getProperty property="id" name="user1"/> <jsp:getProperty property="username" name="user1"/> <jsp:getProperty property="age" name="user1"/> 出现故障:在超链提交的数据怎么限制封装到哪个对象里? 主要看属性名+參数是否一致。 发现user所要封装的属性名+參数和user1所要封装的属性名+參数都一样。所以都封装成了对象(user+user1),所以在页面输出了两个对象的内容。15.jsp不会关心其它jsp传过来的数据是否反复或者是什么方式传过来的,仅仅要传过来的属性名+參数满足JavaBean对象里的属性名和方法的接口。那么就为这些数据新建对象。 假设想把传过来的数据指定特定的对象名能够吗?貌似不行。以上是内省机制。 六、四大域对象(相当重要) a. PageContext:页面范围的数据。用的非常少 b. ServletRequest:请求范围的数据。 用的非常多。显示一次数据后就没实用了。这种数据应该放到该范围中 c. HttpSession:会话范围的数据。用的非常多。每次请求和响应都须要共享的数据。比方登录信息,购物信息。 d. ServletContext(application域):应用范围的数据。用的不多。全部client都共享的信息。注意同步。 数据能不能取到,关键是不是从一个地方取的数据 使用的情况详细分析 七、EL表达式(属于JSP中的技术,今天最重要! ) 1、EL表达式简单介绍 EL 全名为Expression Language。EL主要作用: 1、获取数据: EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象、获取数据。(某个web域 中的对象,訪问javabean的属性、訪问list集合、訪问map集合、訪问数组) 2、运行运算: 利用EL表达式能够在JSP页面中运行一些主要的关系运算、逻辑运算和算术运算,以在JSP页面中完毕一些简单的逻辑运算。${user==null} 3、获取web开发经常使用对象 EL 表达式定义了一些隐式对象,利用这些隐式对象,web开发者能够非常轻松获得对web经常使用对象的引用。从而获得这些对象中的数据。 4、调用Java方法 EL表达式同意用户开发自己定义EL函数,以在JSP页面中通过EL表达式调用Java类的方法。 a、获取数据: 老做法: String name =(Stirng )session.getAttribute("name"); out.write(name); EL表达式: El:${name} 拿到的name也是看设置好的范围来获取的。(观察底层代码) 指定某个域对象中拿去数据:${sessionScope.name} EL中存在了11个隐含对象 第一仅仅猫的样例: &{user.friend.cat.name} &{user["friend"]["cat"]["name"]} 用点的地方能够用中括号。反之不行 EL表达式输出常量要加引號,不加的话会识别是变量 ${"abvca"} 使用EL表达式获取数据语法:“${标识符}” EL表达式语句在运行时,会调用pageContext.findAttribute方法,用标识符为keyword,分别从page、request、session、application四个域中查找对应的对象。找到则返回对应对象。找不到则返回”” (注意。不是null,而是空字符串)。 演示样例:${user} EL表达式也能够非常轻松获取JavaBean的属性,或获取数组、Collection、Map类型集合的数据,比如: ${user.address.city} ${user.list[0]}:訪问有序集合某个位置的元素 ${map.key} : 获得map集合中指定key的值 结合JSTL的foreach标签,使用EL表达式也能够非常轻松迭代各种类型的数组或集合。演示样例: 迭代数组 迭代collection类型集合 迭代map类型集合 实验:project架构: 在实验中要使用到的类: User.java package com.heima.bean; public class User { private String id ; private String username ; private Friend friend; private int age ; public User() { } public User(String id, String username, int age) { super(); this.id = id; this.username = username; this.age = age; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Friend getFriend() { return friend; } public void setFriend(Friend friend) { this.friend = friend; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } Friend.java package com.heima.bean; public class Friend { private Cat cat ; public Cat getCat() { return cat; } public void setCat(Cat cat) { this.cat = cat; } } Cat.java package com.heima.bean; public class Cat { private String name ; private String color ; public Cat() { } public Cat(String name, String color) { super(); this.name = name; this.color = color; } public String getName() { return name; } public String getColor() { return color; } } 实验:1.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>el表达式从域对象中获取数据</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <% pageContext.setAttribute("name", "小龙女") ; request.setAttribute("name", "赵敏") ; session.setAttribute("name", "黄蓉") ; application.setAttribute("name", "周芷若") ; String name = (String) session.getAttribute("name") ; out.write(name) ; User user = new User() ; Friend f = new Friend() ; f.setCat(new Cat("喵喵","白色")) ; user.setFriend(f) ; request.setAttribute("user", user) ; List<User> list = new ArrayList<User>() ; list.add(new User("1","张无忌",20)) ; list.add(new User("2","乔峰",25)) ; list.add(new User("3","郭靖",30)) ; request.setAttribute("list", list) ; Map<String,User> map = new HashMap<String,User>() ; map.put("a", new User("1","张无忌",20)) ; map.put("b", new User("2","乔峰",25)) ; map.put("c", new User("3","郭靖",30)) ; request.setAttribute("map", map) ; %> <br> 採用el表达式输出常量:${"abcde"}<br> 採用el表达式拿取数据: ${name}<br> 指定从session中拿取数据: ${sessionScope.name }<br> 拿到人的朋友的第一仅仅猫的名字: ${user.friend.cat.name}:${user["friend"]["cat"]["name"]} <br> 拿到人的朋友的第一仅仅猫的颜色: ${user.friend.cat.color} <br> 拿取list中的第一个人的名字:${list[0].username} <br> 拿取map中的乔峰的名字:${map["b"].username}:${map.b.username} <br> </body> </html> 在浏览器输入:http://localhost:8080/day1101el/1.jsp,页面输出下面结果: b、运行运算: 语法: ${运算表达式},EL表达式支持例如以下运算符: empty运算符: 检查对象是否为null或“空”,非常好用!!! 三元表达式: ${user!=null? user.name : “”} ,非常好用! ! ! [ ] 和 . 号运算符 实验:2.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>el表达式的数学运算</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <% int a = 10 ; request.setAttribute("a", a) ; String s = (String) request.getAttribute("name") ; out.write(s) ; request.setAttribute("name", s) ; Map<String,User> map = new HashMap<String,User>() ; map.put("a", new User("1","张无忌",20)) ; map.put("b", new User("2","乔峰",25)) ; map.put("c", new User("3","郭靖",30)) ; request.setAttribute("map", map) ; %> 运行加法: ${1+1 }<br> 运行比較运算:${ 10 >5}:${ 10 gt 5}<br> 运行比較运算:${ a >5}<br> 运行逻辑运算: ${a > 5 || a < 0 }<br> 运行null运算:${name == null}<br> 运行三元运算符: ${a>5?"哈哈":"呵呵" }<br> 检測map是否为空:${empty map }:${ not empty map } </body> </html> 在浏览器输入:http://localhost:8080/day1101el/2.jsp。页面输出结果例如以下: c、获取web开发经常使用对象 实验: 3.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>el表达式的内置对象</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <%request.setCharacterEncoding("UTF-8") ; %> <form action="4.jsp" method="get"> 姓名: <input type = "text" name = "username"><br> password: <input type = "text" name = "pass"><br> 反复password: <input type = "text" name = "pass"><br> <input type = "submit" value = "提交"><br> </form> <a href="http://blog.163.com/faith_yee/blog/4.jsp?username=张无忌">4.jsp</a> <%--<jsp:forward page="4.jsp"> <jsp:param value="东方不败" name="username"/> </jsp:forward> --%></body> </html> 4.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>el表达式的内置对象</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body><%-- <% String name = request.getParameter("username") ; name = new String(name.getBytes("ISO-8859-1"),"GBK") ; out.write(name) ; %>--%> 拿取表单传递的參数: ${param.username }<br> 拿取超链传递的參数: ${param.username }<br> 拿取请求转发传递的參数: ${param.username }<br> 拿取重名參数的值: ${paramValues.pass[0] }: ${paramValues.pass[1] }<br> 获取请求头的值: ${header.Referer }<br> 获取请求头的值: ${headerValues.Referer[0] }<br> 获取全局參数的值: ${initParam.name }<br> 获取Cookie(是一个map): ${cookie.JSESSIONID }<br> 获取Cookie(是一个Cookie对象)的名字: ${cookie.JSESSIONID.name }<br> 获取Cookie(是一个Cookie对象)的值: ${cookie.JSESSIONID.value }<br> </body> </html> web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name></display-name> <context-param> <param-name>name</param-name> <param-value>山本五十六</param-value> </context-param> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> 在浏览器输入http://localhost:8080/day1101el/3.jsp。页面结果例如以下,输入例如以下信息: 点击提交后进入4.jsp,显演示样例如以下结果: 假设在13.jsp点击超链,得到例如以下结果: 获取Cookie(是一个map)的键:${cookie.key}//拿不出 d、调用Java方法 ${"abc"+"de"}//不行:+支持整数浮点数,不支持字符串 EL不支持字符串的不论什么操作 但我们能够定义函数来实现 ${fun:toupper("abcde")}//EL不识别函数,那么怎么来实现这种方式?EL一定和底层的JAVA代码相关联,所以我们能够自己定义标签函数 实验: 5.jsp <%@ page language="java" import="java.util.*,com.heima.bean.*" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/myfun" prefix="fun" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>el表达式的内置对象</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> ${fun:toupper("abcde")} ${fun:toupper("aaaaaaaaa") } ${fun:out("abcde") } </body> </html> a.tld <?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <tlib-version>1.1</tlib-version> <short-name>fun</short-name> <uri>http://java.sun.com/jsp/myfun</uri> <function> <name>toupper</name> <function-class>com.heima.demo.Demo</function-class> <function-signature>java.lang.String demo(java.lang.String)</function-signature> </function> <function> <name>out</name> <function-class>com.heima.demo.Demo</function-class> <function-signature>void demo1(java.lang.String)</function-signature> </function> </taglib> Demo.java package com.heima.demo; public class Demo { //将參数转变为大写 public static String demo(String str){ return str.toUpperCase() ; } public static void demo1(String str){ System.out.println(str); } } 在浏览器输入:http://localhost:8080/day1101el/5.jsp。得到例如以下结果: 方法总结: 1、创建一个类(后台) 2、类里写方法(静态) 3、写描写叙述性文件(注意路径) 4、页面上要用taglib指令标签引入 5、能够用EL语句是使用了 taglib里能够引用sun公司已经定义好了的方法。 用属性来改变要用法的名字 八、在地址栏里输入中文,server解析为乱码的IE解决的方法 地址栏输入有中文: String s = request.getQueryString("username"); //String s = request.getParameter("username"); s = new String(s.getBytes("iso-8859-1"),"gbk"); out.write(s); 下载 版权声明:本文博客原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4746773.html,如需转载请自行联系原作者
来点需要:我使用的数据库访问EF框架,但是,因为使用一个动态表来的统计报告中。单独是每天产生基于数据表,它是很难使用EF加盟前。所以我包装在两组数据库存取层的框内,一个是EF,一种是传统的ADO.NET。当设计使用动态表,我打电话跟ADO.NET进行数据库訪问操作了。 先看下View。这里我使用的是jquery easyUI里面的datagrid来做的报表。 例如以下: 单击选中日报: 年报例如以下: @model YKT.Model.SubCompanyReport @{ ViewBag.Title = "分公司营收统计"; Layout = "~/Views/Shared/Base.cshtml"; } <style type="text/css"> .datagrid-header-row .datagrid-cell-group { font-size:12px; font-weight:bold; } .datagrid-header td { font-weight:bold; } </style> <script src="../../Res/My97DatePicker/WdatePicker.js" type="text/javascript"></script> <script type="text/javascript"> var cTime = ""; var cUser = '<div style="text-align: left; float:left;">制表人:</div>'; var dataDate = ""; var yearMonthTitle = ""; var dayMonthTitle = ""; var tbTitle=""; //获取组织类型 function getComponentType() { $("#sltCompany").empty(); var url = "SubCompanyReport/GetComList" $.getJSON(url, function (data) { if (data != null) { $.each(data, function (i, item) { $("<option></option>") .val(item["COMPONENT_ID"]) .text(item["COMPONENT_NAME"]) .appendTo($("#sltCompany")); }); } }); } //“查询”button。弹出查询框 function flexiQuery() { if ($("#Start_Time").val() == "") { $.messager.alert('提示', '结算日期不能为空'); } else { //将查询条件依照分隔符拼接成字符串 var search = "Start_Time=" + $("#Start_Time").val() + "&&End_Time=" + $("#End_Time").val() + "&&sltCompany=" + $("#sltCompany").val() + "&&sltReportType=" + $("#sltReportType").val(); var url = 'SubCompanyReport/GetData?' + search; cTime = '<div style="text-align: left; float:left;">制表时间:' + CurentDate() + '</div>'; var myDate = new Date(); var startDate = StringToDate($("#Start_Time").val()); dataDate = '<div style="text-align: left; float:left;">数据日期:'; if ($("#sltReportType").val() == "0") { var endDate = StringToDate($("#End_Time").val()); if (endDate == "") { dataDate += getDateByStr(startDate) + getWeek(startDate); } else { dataDate += getDateByStr(startDate) + getWeek(startDate) + " 到 " + getDateByStr(endDate) + getWeek(endDate); } dataDate += '</div>'; $('#div1').panel('close'); $('#div').panel('open'); yearMonthTitle = "月累计"; dayMonthTitle = "当日"; //运行查询 getData(url); } else if ($("#sltReportType").val() == "1") { $('#div1').panel('close'); $('#div').panel('open'); var v = getDateByStr(startDate); dataDate += v.substring(0, 8); dayMonthTitle = "当月"; yearMonthTitle = "年累计"; dataDate += '</div>'; //运行查询 getData(url); } else if ($("#sltReportType").val() == "2") { var v1 = getDateByStr(startDate); dataDate = v1.substring(0, 5); tbTitle = '公交总公司' + dataDate + '运营收入统计表(按分公司)'; $('#div1').panel('open'); $('#div').panel('close'); dataDate += '</div>'; //运行查询 getData1(url); } } } $(function () { initData(); $("#sltReportType").change(function () { if ($("#sltReportType").val() == "0") { $("#spnEndTime").css("display", "inline"); } else { $("#spnEndTime").css("display", "none"); } }); }); //初始化数据 function initData() { var d = getDate(0); $("#Start_Time").val(d); //$("#End_Time").val(d); getComponentType(); } //导出 function outputExcel() { $.messager.confirm('操作提示', "确认导出数据吗? ", function (r) { if (r) { //将查询条件依照分隔符拼接成字符串 var search = "Start_Time=" + $("#Start_Time").val() + "&&End_Time=" + $("#End_Time").val() + "&&sltCompany=" + $("#sltCompany").val() + "&&sltReportType=" + $("#sltReportType").val(); var url = 'SubCompanyReport/Export?' + search; window.location.href = url; } }); } //日报表 function getData(url) { var searchH = $("#divQuery").height(); var h = document.documentElement.clientHeight - searchH - 26; //var w = document.documentElement.clientWidth; $('#flexigridData').datagrid({ title: '分公司营收统计', //列表的标题 iconCls: 'icon-site', // fit: true, //列表自己主动适应宽度 width: 'auto', singleSelect: true, height: h, nowrap: false, //True 就会把数据显示在一行里。 striped: true, //True 就把行条纹化。(即奇偶行使用不同背景色) collapsible: true, //可调节列宽 //remoteSort: true, //定义是否从server给数据排序。 url: url, //获取数据的url toolbar: [], columns: [ [{ title: '公交公司全日运营收入统计表(按分公司)', colspan: 17,align:'center'}], //第一行 [{ title: '<div style="text-align: left; float:left;">制表单位:吴江公交总公司IC卡结算管理中心</div>', colspan: 8, headalign: 'left' }, { title: cTime, colspan: 7 }, { title: cUser, colspan: 2}], //第二行 [{ title: dataDate, colspan: 17}], //第三行 [{ title: '单位', rowspan: 3, field: 'ComponentName' }, { title: '投币收入', colspan: 4 }, { title: 'IC卡收入', colspan: 4 }, { title: 'IC卡收入占%', colspan: 4 }, { title: '合计', colspan: 4}], //第四行 [{ title: dayMonthTitle, colspan: 2 }, { title: yearMonthTitle, colspan: 2 }, { title: dayMonthTitle, colspan: 2 }, { title: yearMonthTitle, colspan: 2 }, { title: dayMonthTitle, colspan: 2 }, { title: yearMonthTitle, colspan: 2 }, { title: dayMonthTitle, colspan: 2 }, { title: yearMonthTitle, colspan: 2}], //第五行 [{ title: '人次(次)', field: 'tbrec' }, { title: '金额(元)', field: 'tbamt', width: 80 }, { title: '人次(次)', field: 'tbljrec' }, { title: '金额(元)', field: 'tbljamt', width: 80 }, { title: '人次(次)', field: 'icrec' }, { title: '金额(元)', field: 'icamt', width: 80 }, { title: '人次(次)', field: 'icljrec' }, { title: '金额(元)', field: 'icljamt', width: 80 }, { title: '人次(次)', field: 'dayrecPer' }, { title: '金额(元)', field: 'dayAmtPer' }, { title: '人次(次)', field: 'monthrecPer' }, { title: '金额(元)', field: 'monthAmtPer' }, { title: '人次(次)', field: 'dayrecTotal' }, { title: '金额(元)', field: 'dayAmtTotal',width:80 }, { title: '人次(次)', field: 'monthrecTotal' }, { title: '金额(元)', field: 'monthAmtTotal',width:80}], //第六行 ] //, //pagination: true, //在 datagrid 的底部显示分页栏。 //rownumbers: true //显示行号的列 }); //异步获取button //首先获取iframe标签的id值 var iframeid = window.parent.$('#tabs').tabs('getSelected').find('iframe').attr("id"); //然后关闭AJAX对应的缓存 $.ajaxSetup({ cache: false }); //获取button值 $.getJSON("../Home/GetToolbar", { id: iframeid }, function (data) { if (data == null) { return; } $('#flexigridData').datagrid("addToolbarItem", data); }); } //年报表 function getData1(url) { var searchH = $("#divQuery").height(); var h = document.documentElement.clientHeight - searchH - 26; //var w = document.documentElement.clientWidth; $('#flexigridData1').datagrid({ title: '分公司营收统计', //列表的标题 iconCls: 'icon-site', // fit: true, //列表自己主动适应宽度 width: 'auto', singleSelect: true, height: h, nowrap: false, //True 就会把数据显示在一行里。 striped: true, //True 就把行条纹化。 (即奇偶行使用不同背景色) collapsible: true, //可调节列宽 //remoteSort: true, //定义是否从server给数据排序。 url: url, //获取数据的url toolbar: [], columns: [ [{ title: tbTitle, colspan: 9, align: 'center'}], //第一行 [{ title: '<span style="text">制表单位:吴江公交总公司IC卡结算管理中心</span>', colspan: 4, headalign: 'left' }, { title: cTime, colspan: 3 }, { title: cUser, colspan: 2}], //第二行 [{ title: '单位', rowspan: 2, field: 'ComponentName' }, { title: '投币收入', colspan: 2 }, { title: 'IC卡收入', colspan: 2 }, { title: 'IC卡收入占%', colspan: 2 }, { title: '合计', colspan: 2}], //第三行 [{ title: '人次(次)', field: 'tbrec' }, { title: '金额(元)', field: 'tbamt', width: 120 }, { title: '人次(次)', field: 'icrec' }, { title: '金额(元)', field: 'icamt', width: 120 }, { title: '人次(次)', field: 'yearrecPer' }, { title: '金额(元)', field: 'yearAmtPer', width: 120 }, { title: '人次(次)', field: 'yearrecTotal' }, { title: '金额(元)', field: 'yearAmtTotal', width: 120}] ] //, //pagination: true, //在 datagrid 的底部显示分页栏。 //rownumbers: true //显示行号的列 }); //异步获取按钮 //首先获取iframe标签的id值 var iframeid = window.parent.$('#tabs').tabs('getSelected').find('iframe').attr("id"); //然后关闭AJAX对应的缓存 $.ajaxSetup({ cache: false }); //获取按钮值 $.getJSON("../Home/GetToolbar", { id: iframeid }, function (data) { if (data == null) { return; } $('#flexigridData1').datagrid("addToolbarItem", data); }); } </script> <div id="content" region="center" fit="true"> <form id="form1"> <div id="divQuery" style="padding: 5px; font-size: 12px;" title="查询列表" class="easyui-toolbar"> <span>结算日期:</span><span> <input type="text" readonly="readonly" id="Start_Time" onclick="WdatePicker({maxDate:'#F{$dp.$D(\'End_Time\');}'})" /> </span> <span id="spnEndTime"> 到 <input type="text" readonly="readonly" id="End_Time" onclick="WdatePicker({minDate:'#F{$dp.$D(\'Start_Time\');}'})" /></span> <span>公司类型:</span> <span><select id="sltCompany"></select></span> <span style=" margin:4px;">报表类型:</span><span><select id="sltReportType"> <option value="0">日报</option> <option value="1">月报</option> <option value="2">年报</option> </select></span> <a href="javascript:flexiQuery()" class="easyui-linkbutton" data-options="iconCls:'icon-search'">查询</a> <a href="javascript:resetData()" class="easyui-linkbutton" data-options="iconCls:'icon-redo'"> 重置</a> </div> </form> <div id="div" class="easyui-panel" closed="true"> <table id="flexigridData" style=" text-align:center"> </table> </div> <div id="div1" class="easyui-panel" closed="true"> <table id="flexigridData1" style=" text-align:center"> </table> </div> </div> 控制器SubCompanyReportController例如以下: using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using YKT.BLL; using YKT.Common; using YKT.Model; using System.IO; using Microsoft.Office.Interop.Excel; using System.Text; namespace YKT.Controllers { public class CompanyClass { public string COMPONENT_ID { get; set; } public string COMPONENT_NAME { get; set; } } public class SubCompanyReportController : Controller { #region 初始化 string ClassName = "SubCompanyReport"; //类名 SubCompanyReportService _service; public SubCompanyReportController() { if (_service == null) { _service = new SubCompanyReportService(); } } ValidationErrors validationErrors = new ValidationErrors(); OMOPERATIONLOGTB OperLog = new OMOPERATIONLOGTB(); #endregion public ActionResult Index() { return View(); } public JsonResult GetComList() { System.Data.DataTable data = _service.GetComList(1, -1, 0, "COMMON,BUS"); List<CompanyClass> list = new List<CompanyClass>(); if (data != null && data.Rows.Count > 0) { for (int i = 0; i < data.Rows.Count; i++) { list.Add(new CompanyClass { COMPONENT_ID = data.Rows[i][0].ToString(), COMPONENT_NAME = data.Rows[i][1].ToString() }); } } return Json(list, JsonRequestBehavior.AllowGet); } [HttpPost] public JsonResult GetData(string sltReportType, string Start_Time, string End_Time, string sltCompany, string sltSubCompany) { List<SubCompanyReport> list = _service.GetTotalStatBySubCompany(sltReportType, Start_Time, End_Time); return Json(list, JsonRequestBehavior.AllowGet); } #region 导出 /// <summary> /// 数据导出 /// </summary> /// <param name="search"></param> /// <returns></returns> public ActionResult Export(string sltReportType, string Start_Time, string End_Time, string sltCompany, string sltSubCompany) { List<SubCompanyReport> queryData = _service.GetTotalStatBySubCompany(sltReportType, Start_Time, End_Time); if (queryData == null || queryData.Count < 1) { Response.Write("<script> alert('没有要导出的数据! '); </script>"); return View("Index"); } int sheet; //结算起始时间 #region 导出Excel string newpath = AppDomain.CurrentDomain.BaseDirectory + "Excel\\"; string newFileName = newpath + "temp.xls";//+ Guid.NewGuid() if (!Directory.Exists(newpath)) { Directory.CreateDirectory(newpath); } //string newpath = Server.MapPath(".") + @"\Excel\" + Guid.NewGuid() + ".xls"; //调用的模板文件 FileInfo mode = new FileInfo(Server.MapPath("~/xlsMode/营收报表.xls")); Application app = new Application(); if (app == null) { return Json("当前用户电脑未安装EXCEL!", JsonRequestBehavior.AllowGet); } app.Application.DisplayAlerts = false; app.Visible = false; if (mode.Exists) { Workbook tworkbook; Object missing = System.Reflection.Missing.Value; app.Workbooks.Add(missing); string beginTime = string.IsNullOrEmpty(Start_Time) ? string.Empty : DateTime.Parse(Start_Time).ToString("yyyyMMdd"); string endTime = string.IsNullOrEmpty(End_Time) ? string.Empty : DateTime.Parse(End_Time).ToString("yyyyMMdd"); //调用模板 写表头 tworkbook = app.Workbooks.Open(mode.FullName, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing); Worksheet tworksheet=new Worksheet(); string ctitle = "制表时间:"; string dataDateText = "数据日期:"; switch (sltReportType) { case "0": //日报 sheet = 8; tworksheet = (Worksheet)tworkbook.Sheets[sheet]; if (!string.IsNullOrEmpty(beginTime) && string.IsNullOrEmpty(endTime)) { dataDateText += ValueConvert.GetDatetimeString(beginTime); } else if (string.IsNullOrEmpty(beginTime) && !string.IsNullOrEmpty(endTime)) { dataDateText += ValueConvert.GetDatetimeString(endTime); } else if (!string.IsNullOrEmpty(beginTime) && !string.IsNullOrEmpty(endTime)) { dataDateText += ValueConvert.GetDatetimeString(beginTime) + " 到 " + ValueConvert.GetDatetimeString(endTime); ; } tworksheet.Cells[3, 9] = ctitle+ValueConvert.GetDatetimeString(DateTime.Now.ToString("yyyyMMdd")); tworksheet.Cells[4, 1] = dataDateText; break; case "1": //月报 sheet = 9; tworksheet = (Worksheet)tworkbook.Sheets[sheet]; tworksheet.Cells[1, 1] = "吴江市公交公司" + beginTime.Substring(4, 2) + "月份运营收入统计表(按分公司)"; tworksheet.Cells[3, 9] = ctitle + ValueConvert.GetDatetimeString(DateTime.Now.ToString("yyyyMMdd")); break; case "2": //年报 sheet = 10; tworksheet = (Worksheet)tworkbook.Sheets[sheet]; tworksheet.Cells[1, 1] = "吴江市公交公司" + beginTime.Substring(0, 4) + "年运营收入统计表(按分公司)"; tworksheet.Cells[3, 5] = ctitle + ValueConvert.GetDatetimeString(DateTime.Now.ToString("yyyyMMdd")); break; } #region 写Excel的内容 if (queryData != null && queryData.Count > 0) { if (sltReportType == "0" || sltReportType == "1") { int m = 7; for (int i = 0; i < queryData.Count; i++) { tworksheet.Cells[m + i, 1] = queryData[i].ComponentName; tworksheet.Cells[m + i, 2] = queryData[i].tbrec; tworksheet.Cells[m + i, 3] = queryData[i].tbamt; tworksheet.Cells[m + i, 4] = queryData[i].tbljrec; tworksheet.Cells[m + i, 5] = queryData[i].tbljamt; tworksheet.Cells[m + i, 6] = queryData[i].icrec; tworksheet.Cells[m + i, 7] = queryData[i].icamt; tworksheet.Cells[m + i, 8] = queryData[i].icljrec; tworksheet.Cells[m + i, 9] = queryData[i].icljamt; tworksheet.Cells[m + i, 10] = queryData[i].dayrecPer; tworksheet.Cells[m + i, 11] = queryData[i].dayAmtPer; tworksheet.Cells[m + i, 12] = queryData[i].monthrecPer; tworksheet.Cells[m + i, 13] = queryData[i].monthAmtPer; tworksheet.Cells[m + i, 14] = queryData[i].dayrecTotal; tworksheet.Cells[m + i, 15] = queryData[i].dayAmtTotal; tworksheet.Cells[m + i, 16] = queryData[i].monthrecTotal; tworksheet.Cells[m + i, 17] = queryData[i].monthAmtTotal; } } else if (sltReportType == "2") { int m = 4; for (int i = 0; i < queryData.Count; i++) { tworksheet.Cells[m + i, 1] = queryData[i].ComponentName; tworksheet.Cells[m + i, 2] = queryData[i].tbrec; tworksheet.Cells[m + i, 3] = queryData[i].tbamt; tworksheet.Cells[m + i, 4] = queryData[i].icrec; tworksheet.Cells[m + i, 5] = queryData[i].icamt; tworksheet.Cells[m + i, 6] = queryData[i].yearrecPer; tworksheet.Cells[m + i, 7] = queryData[i].yearAmtPer; tworksheet.Cells[m + i, 8] = queryData[i].yearrecTotal; tworksheet.Cells[m + i, 9] = queryData[i].yearAmtTotal; } } } #endregion tworksheet.SaveAs(newFileName, missing, missing, missing, missing, missing, missing, missing, missing, missing); tworkbook.Close(false, mode.FullName, missing); app.Workbooks.Close(); app.Quit(); tworkbook = null; app = null; //强制对全部代进行垃圾回收 GC.Collect(); } System.IO.FileInfo file = new System.IO.FileInfo(newFileName); Response.Clear(); Response.Charset = "GB2312"; Response.ContentEncoding = System.Text.Encoding.Default; // 加入头信息,为"文件下载/另存为"对话框指定默认文件名称 string nm = "分公司_" + mode.Name; Response.AddHeader("Content-Disposition", "attachment; filename=" +HttpUtility.UrlEncode(nm, Encoding.UTF8).ToString() ); //Server.UrlEncode(mode.Name)); // 加入头信息,指定文件大小。让浏览器可以显示下载进度 Response.AddHeader("Content-Length", file.Length.ToString()); // 指定返回的是一个不能被client读取的流。必须被下载 Response.ContentType = "application/ms-excel"; // 把文件流发送到client Response.WriteFile(file.FullName); // 停止页面的运行 Response.End(); return Json("导出成功!", JsonRequestBehavior.AllowGet); #endregion } #endregion } } 版权声明:本文博客原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4642128.html,如需转载请自行联系原作者
于 debian 接着写 2048, 的影响,如下面的: 感兴趣的朋友能够在这里(http://download.csdn.net/download/kamsau/7330933)下载。 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4757513.html,如需转载请自行联系原作者
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace openUrl { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void toolStripButton1_Click(object sender, EventArgs e) { string add = ""; if (!(txtUrl.Text.Trim().StartsWith("http://"))) { add = "http://" + txtUrl.Text.Trim(); txtUrl.Text = add; } webBrowser1.Url = new Uri(add); } } } 版权声明:本文博主原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4757804.html,如需转载请自行联系原作者
层(Layer)的生命周期函数有例如以下: init()。初始化层调用。 onEnter()。进入层时候调用。 onEnterTransitionDidFinish()。 进入层并且过渡动画结束时候调用。 onExit()。退出层时候调用。 onExitTransitionDidStart()。退出层并且開始过渡动画时候调用。 cleanup()。 层对象被清除时候调用。 提示 层(Layer)继承于节点(Node),这些生命周期函数根本上是从Node继承而来。其实全部Node对象(包含:场景、层、精灵等)都有这些函数。仅仅要是子类化这些类都能够重写这些函数,来处理这些对象的不同生命周期阶段事件。 我们重写HelloWorld层的中几个生命周期函数,代码例如以下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 bool HelloWorld::init() { if( !Layer::init() ) { returnfalse; } log("HelloWorldinit"); ...... returntrue; } void HelloWorld::onEnter() { Layer::onEnter(); log("HelloWorldonEnter"); } voidHelloWorld::onEnterTransitionDidFinish() { Layer::onEnterTransitionDidFinish(); log("HelloWorldonEnterTransitionDidFinish"); } void HelloWorld::onExit() { Layer::onExit(); log("HelloWorldonExit"); } voidHelloWorld::onExitTransitionDidStart() { Layer::onExitTransitionDidStart(); log("HelloWorldonExitTransitionDidStart"); } void HelloWorld::cleanup() { Layer::cleanup(); log("HelloWorldcleanup"); } 注意 在重写层生命周期函数中,第一行代码应该是调用父类的函数。比如HelloWorld::onEnter()中第一行应该是Layer::onEnter()函数,假设不调用父类的函数可能会导致层中动画、动作或计划无法运行。 假设HelloWorld是第一个场景,当启动HelloWorld场景时候,它的调用顺序例如以下图所看到的: 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4759382.html,如需转载请自行联系原作者
转载请注明出处,http://blog.csdn.net/suool/article/details/38406211,谢谢。 Linux进程存储结构和进程结构 可运行文件结构 例如以下图: 能够看出,此ELF可运行文件存储时(没有调入内存)分为代码区、数据区和未出花数据区三部分。 代码区:存放cpu的运行的机器指令。 数据区:包括程序中的已经初始化的静态变量,以及已经初始化的全局变量。 未初始化数据区:存入的是未初始化的全局变量和未初始化的静态变量。 如今在上面的程序代码中添加一个int的静态变量,结果例如以下: 代码部分添加了4个字节。是int的大小。 进程结构 假设将一个ELF格式可执行文件载入到内存中执行,则将演变成一个或多个进程。进程是Linux事务管理的基本单元,全部的进程均拥有独立的环境和资源。 下图展示一个ELF可运行文件的存储结构和Linux进程基本结构的对比: 上图仅给出了一个进程的在内存中申请的代码区、初始化数据区、未初始化数据区、堆区、栈区五个部分。 为了更好的管理linux所訪问的资源,系统定义了进程控制块(PCB)结构体来管理每一个进程资源。如图: 而进程资源分为: 内核空间进程资源和用户空间进程资源 内核空间进程资源即PCB相关的信息。用户空间进程资源包含:通过成员mm_struct映射的内存空间。 进程状态 // 内核进程结构 #define TASK_RUNNING 0 // 就绪 #define TASK_INTERRUPTIBLE 1 // 中断等待 #define TASK_UNINTERRUPTIBLE 2 // 不可中断等待 #define __TASK_STOPPED 4 // 僵死 #define __TASK_TRACED 8 // 暂停 /* in tsk->exit_state */ #define EXIT_ZOMBIE 16 #define EXIT_DEAD 32 /* in tsk->state again */ #define TASK_DEAD 64 #define TASK_WAKEKILL 128 #define TASK_WAKING 256 系统中的每一个进程都必定处于以上所列进程状态中的一种。 TASK_RUNNING表示进程要么正在运行。要么正要准备运行。 TASK_INTERRUPTIBLE表示进程被堵塞(睡眠),直到某个条件变为真。条件一旦达成。进程的状态就被设置为TASK_RUNNING。 TASK_UNINTERRUPTIBLE的意义与TASK_INTERRUPTIBLE类似。除了不能通过接受一个信号来唤醒以外。 __TASK_STOPPED表示进程被停止运行。 __TASK_TRACED表示进程被debugger等进程监视。 EXIT_ZOMBIE表示进程的运行被终止,可是其父进程还没有使用wait()等系统调用来获知它的终止信息。 EXIT_DEAD表示进程的终于状态。 EXIT_ZOMBIE和EXIT_DEAD也能够存放在exit_state成员中。进程状态的切换过程和原因大致例如以下图(图片来自《Linux Kernel Development》) 进程基本属性 进程号(PID) PID是系统维护的唯一标示一个进程的正整数。进程号是无法在用户层改动的。 在Linux系统中,系统的第一个用户进程是init进程。PID是1,其它的进程的PID依次添加。例如以下: 在应用编程中能够使用getpid()函数获取当前进程的PID.详细參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getpid.html 父进程号(PPID) 除init进程外的全部进程都是由还有一进程创建的。该进程成为父进程,被创建的进程成为子进程。 PPID一样无法在用户层改动。 使用getppid()函数获取当前进程的父进程号。參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getppid.html 进程组号(PGID) 和用户管理一样,进程也有自己的进程号(PID)和进程组号(PGID)。进程组是一个或多个进程的集合。他们与同一个作业相关联。能够接受来自同一个终端的各种信号,可是进程组号能够在用户层改动。 使用getpgid()函数获取指定进程的进程组号。详见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getpgid.html 以下一个程序是总和上面三个函数使用的演示样例: #include<stdio.h> #include<unistd.h> int main(int argc,char *argv[]) { int i; printf("\tpid\t ppid \t pgid\n"); // 提示信息 printf("parent\t%d\t%d\t%d\n",getpid(),getppid(),getpgid(0)); // 当前进程信息 for(i=0;i<2;i++) if(fork()==0) printf("child\t%d\t%d\t%d\n",getpid(),getppid(),getpgid(0)); // 子进程信息 return 0; } 此外,getpgrp()也能够用来获取当前进程的进程组号。 參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getpgrp.html 会话 会话(session)是一个或多个进程的合集。 系统调用函数getsid()用来获取某个进程会话的SID。 參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getsid.html 某进程的sid是能够改动的,函数setsid()用于创建新的会话。 here : http://pubs.opengroup.org/onlinepubs/009695399/functions/setsid.html 控制终端 会话和进程组有例如以下特点: 为了让终端设备驱动程序将信号送到进程。能够调用tcgetpgrp()获取前台进程组的进程组号。返回与打开的终端相关联的前台进程组号。http://pubs.opengroup.org/onlinepubs/009695399/functions/tcgetpgrp.html tcsetpgrp()函数用来设置某个进程组是前台还是后台进程组。http://pubs.opengroup.org/onlinepubs/009695399/functions/tcsetpgrp.html 假设进程有一个控制终端,则将前台进程组ID设置为pgrpid,这个值应该在用一个会话中的一个进程组的id,參数fileds是控制终端文件描写叙述符。 tcgetsid(*)函数获取当前控制终端的会话首进程的会话id。http://pubs.opengroup.org/onlinepubs/009695399/functions/tcgetsid.html 以下是使用上面的函数演示样例: #include<stdio.h> #include<unistd.h> #include<fcntl.h> #include<stdlib.h> int main() { int fd; pid_t pid; pid=fork(); // 创建新进程 if(pid==-1) perror("fork"); else if(pid>0) { wait(NULL); exit(EXIT_FAILURE); } else { if((fd=open("/dev/pts/0",O_RDWR))==-1) // 由于是网络终端,在此打开终端以确认 { perror("open"); } printf("pid=%d,ppid=%d\n",getpid(),getppid()); // 获取进程号& 父进程 printf("sid=%d,tcgetsid=%d\n",getsid(getpid()),tcgetsid(fd)); // 读取会话sid和终端sid printf("tcgetpgrp=%d\n",tcgetpgrp(fd)); // 读取终端前台进程 printf("pigd=%d\n",getpgid(getpid())); // 读取进程组的ID } } 执行结果: 进程用户属性 Linux是权限哟有严格控制的操作系统,某个进程拥有真实的用户号(RUID)、真有用户组号(RGID)、有效用户号(EUID)、有效用户组号(EGID)信息。 在Linux系统中,文件的创建者是文件的拥有者,即文件的真有用户号为文件的拥有者号,使用ls -l 命令查看。 进程真有用户号(RUID) 对于进程而言,创建该进程的用户uid即是此进程的真有用户号。使用getuid(0函数获取当前进程的RUID。函数定义在unistd.h中。 详细參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getuid.html 进程有效用户组号(EUID) 主要用于权限检查。 多数情况下,EUID和UID同样,可是假设可执行文件的setuid位有效,则该文件的拥有者之外的用户在执行程序时,EUID和UID不一样。即当某个可执行文件设置了 setgid位后。不论什么用户(包含root)执行此程序时。其有效用户组EUID为该文件的拥有者。sunch as: 注意setuid位的特殊性,这个以后会专门解说。 进程用户组号(GID) 创建进程的用户所在的组号为该进程的用户组号(GID)。能够调用getgid()函数来获取当前进程的真有用户组号。 详细參见:http://pubs.opengroup.org/onlinepubs/009695399/functions/getgid.html 以下是读取当前进程的UID/GID/EUID/EGID的演示样例程序: #include<stdio.h> #include<unistd.h> int main(int argc,char *argv[]) { printf("\tuid\tgid\teuid\tegid\n"); printf("parent\t%d\t%d\t%d\t%d\n",getuid(),getgid(),geteuid(),getegid()); if(fork()==0) { printf("child\t%d\t%d\t%d\t%d\n",getuid(),getgid(),geteuid(),getegid()); } return 0; } Next 进程管理及控制 Linux 特殊进程 转载请注明出处。http://blog.csdn.net/suool/article/details/38406211,谢谢! 版权声明:本文博主原创文章。博客,未经同意不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4864771.html,如需转载请自行联系原作者
最近的工作需求client和server使用https协议进行通讯,我负责client编写程序,在操作系统的-depth理解认为一旦前webserver实现,整理代码: #include"apue.h" extern char **environ; void clienterror(int fd,char *cause,char *errnum,char *shortmsg,char *longmsg) { char buf[MAXLINE],body[MAXLINE]; sprintf(body,"<html><title>Tiny Error</title>"); sprintf(body,"%s<body bgcolor=""ffffff"">\r\n",body); sprintf(body,"%s%s:%s\r\n",body,errnum,shortmsg); sprintf(body,"%s<p>%s:%s\r\n",body,longmsg,cause); sprintf(body,"%s<hr><em>The tiny Web server</em?\r\n",body); sprintf(buf,"HTTP/1.0 %s %s\r\n",errnum,shortmsg); rio_writen(fd,buf,strlen(buf)); sprintf(buf,"Content-type:text/html\r\n"); rio_writen(fd,buf,strlen(buf)); sprintf(buf,"Content-length:%d\r\n\r\n",(int)strlen(body)); rio_writen(fd,buf,strlen(buf)); rio_writen(fd,body,strlen(body)); } void read_requesthdrs(rio_t *rp) { char buf[MAXLINE]; rio_readlineb(rp,buf,MAXLINE); while(strcmp(buf,"\r\n")) { rio_readlineb(rp,buf,MAXLINE); printf("%s",buf); } return; } int parse_uri(char *uri,char *filename,char *cgiargs) { char *ptr; printf("parse_uri(uri):%s\n",uri); if(!strstr(uri,"cgi-bin")) { strcpy(cgiargs,""); strcpy(filename,"."); strcat(filename,uri); if(uri[strlen(uri)-1]=='/') strcat(filename,"home.html"); return 1; } else { ptr=index(uri,'?'); if(ptr) { strcpy(cgiargs,ptr+1); *ptr='\0'; } else strcpy(cgiargs,""); strcpy(filename,"."); strcat(filename,uri); return 0; } } void get_filetype(char *filename,char *filetype) { if(strstr(filename,".html")) strcpy(filetype,"text/html"); else if(strstr(filename,".gif")) strcpy(filetype,"image/gif"); else if(strstr(filename,".jpg")) strcpy(filetype,"image/jpeg"); else strcpy(filetype,"text/plain"); } void serve_dynamic(int fd,char *filename,char *caiargs) { char buf[MAXLINE],*emptylist[]={NULL}; sprintf(buf,"HTTP/1.0 200 OK\r\n"); rio_writen(fd,buf,strlen(buf)); sprintf(buf,"Server:Tiny Web Server\r\n"); rio_writen(fd,buf,strlen(buf)); if(fork()==0) { setenv("QUERY_STRING",caiargs,1); dup2(fd,STDOUT_FILENO); execve(filename,emptylist,environ); } wait(NULL); } void serve_static(int fd,char *filename,int filesize) { int srcfd; char *srcp,filetype[MAXLINE],buf[MAXLINE]; get_filetype(filename,filetype); sprintf(buf,"HTTP/1.0 200 OK\r\n"); sprintf(buf,"%sServer:Tiny Web Server\r\n",buf); sprintf(buf,"%sContent-length:%d\r\n",buf,filesize); sprintf(buf,"%sContent-type:%s\r\n\r\n",buf,filetype); rio_writen(fd,buf,strlen(buf)); srcfd=open(filename,O_RDONLY,0); srcp=mmap(0,filesize,PROT_READ,MAP_PRIVATE,srcfd,0); close(srcfd); rio_writen(fd,srcp,filesize); munmap(srcp,filesize); } void doit(int fd) { int is_static; struct stat sbuf; char buf[MAXLINE],method[MAXLINE],uri[MAXLINE],version[MAXLINE]; char filename[MAXLINE],cgiargs[MAXLINE]; rio_t rio; rio_readinitb(&rio,fd); rio_readlineb(&rio,buf,MAXLINE); sscanf(buf,"%s %s %s",method,uri,version); if(strcasecmp(method,"GET")) { clienterror(fd,method,"501","Not implemented","Tiny does not implemented this method"); return; } read_requesthdrs(&rio); is_static=parse_uri(uri,filename,cgiargs); if(stat(filename,&sbuf)<0) { clienterror(fd,filename,"404","Not found","Tiny couldn't find this file"); return; } if(is_static) { if(!(S_ISREG(sbuf.st_mode))||!(S_IRUSR&sbuf.st_mode)) { clienterror(fd,filename,"403","Forbidden","Tiny could't read the file"); return; } serve_static(fd,filename,sbuf.st_size); } else { if(!(S_ISREG(sbuf.st_mode))|!(S_IXUSR&sbuf.st_mode)) { clienterror(fd,filename,"403","Forbidden","Tiny could't run the CGI program"); return; } serve_dynamic(fd,filename,cgiargs); } } int main(int argc,char **argv) { int listenfd,connfd,port,clientlen; struct sockaddr_in clientaddr; if(argc!=2) { fprintf(stderr,"usage:%s <port> \n",argv[0]); exit(0); } port=atoi(argv[1]); listenfd=open_listenfd(port); while(1) { clientlen=sizeof(clientaddr); connfd=accept(listenfd,(SA*)&clientaddr,&clientlen); doit(connfd); close(connfd); } } 我们能够直接使用浏览器測试上面的程序。比方当前server程序的文件夹以下有一个index.html,仅仅要我们在浏览器中输入: localhost:<port>/index.html就能够请求到index.html server端收到的浏览器请求行例如以下: 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4654111.html,如需转载请自行联系原作者
mybatis现在普遍使用的每一个人DAO框架。mybatis generator它可以基于数据库中的表结构,生成自己主动mybatis代码和配置文件,方便使用,当然,实际的使用过程中。generator当然,也有很多不尽人意的地方,幸运的是,他提供了一种机制插头,来帮我们做扩大。 解说的插件开发依赖下面mybatis版本号: <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.2</version> </dependency> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> </dependency> 首先我们的插件类须要扩展PluginAdapter类,例如以下: public class PaginationPlugin extends PluginAdapter { pluginAdapter提供了全部的接口,方便我们在插件进行到某个操作的时候。做自己定义的改动。这里我们主要介绍下面几类方法: public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated( XmlElement element, IntrospectedTable introspectedTable) modelExampleClassGenerated方法顾名思义。就是生产modelExample类时的扩展,了解generator的都知道。他会帮你生产mapper、model、example三类java对象,当中example类是辅助我们用代码的方式来生产sql的,这个modelExampleClassGenerated方法就是在生产example的时候起效果的。 比方。原有的generator1.3.2插件不支持分页,那我们能够首先在modelExampleClassGenerated方法中。对生产的Class加上limit的參数,代码例如以下: CommentGenerator commentGenerator = context.getCommentGenerator(); Field field = new Field(); field.setVisibility(JavaVisibility.PROTECTED); field.setType(FullyQualifiedJavaType.getIntInstance()); field.setName(name); field.setInitializationString("-1"); commentGenerator.addFieldComment(field, introspectedTable); topLevelClass.addField(field); char c = name.charAt(0); String camel = Character.toUpperCase(c) + name.substring(1); Method method = new Method(); method.setVisibility(JavaVisibility.PUBLIC); method.setName("set" + camel); method.addParameter(new Parameter(FullyQualifiedJavaType .getIntInstance(), name)); method.addBodyLine("this." + name + "=" + name + ";"); commentGenerator.addGeneralMethodComment(method, introspectedTable); topLevelClass.addMethod(method); method = new Method(); method.setVisibility(JavaVisibility.PUBLIC); method.setReturnType(FullyQualifiedJavaType.getIntInstance()); method.setName("get" + camel); method.addBodyLine("return " + name + ";"); commentGenerator.addGeneralMethodComment(method, introspectedTable); topLevelClass.addMethod(method); 如代码所看到的,事实上我们就是定义了一个private int limitStart的属性,并加入了get和set方法。 加入完example的属性后,我们须要将这个属性加到生成的mapper xml配置文件里。 这就用到sqlMapSelectByExampleWithBLOBsElementGenerated方法,当然,注意这种方法的名字,我们想改动哪个xml文件里的sql,就须要找到相应的方法来复写。 XmlElement isNotNullElement = new XmlElement("if"); //$NON-NLS-1$ isNotNullElement.addAttribute(new Attribute("test", "limitStart != null and limitStart>-1")); //$NON-NLS-1$ //$NON-NLS-2$ isNotNullElement.addElement(new TextElement( "limit ${limitStart} , ${limitEnd}")); element.addElement(isNotNullElement); 如上述代码,我们在生成的xml文件里。增加一个if条件推断,推断假设当前example类的limitStart和limitEnd不为-1。注意这个-1是我们在example扩展字段时候加上的默认值。假设不是默认值。那么就加上limit ${limitStart}, ${limitEnd}分页条件。 如上所述,就是这么简单。我们能够对生成的mybatis java代码、xml配置做自己的改动。 以下看一下,怎样来使用该插件。 我们首先须要在使用generator的projectpom文件里增加generator插件,并将我们的插件包依赖加进来,这里我们的样例是mybatis-page-plugin。 <build> <defaultGoal>install</defaultGoal> <plugins> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <configuration> <configurationFile>generatorConfig.xml</configurationFile> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>org.duoku.groom</groupId> <artifactId>mybatis-page-plugin</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </plugin> </plugins> </build> 如配置所述,我们的插件配置文件是generatorConfig.xml。我们来看一下这个文件: <generatorConfiguration> <context id="MBG" targetRuntime="MyBatis3" defaultModelType="conditional"> <!--targetRuntime 此属性用于指定生成的代码的执行目标。 --> <plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin" /> <plugin type="org.duoku.groom.mybatis.plugin.PaginationPlugin"></plugin> 如上图所看到的。我们在plugin中,加上我们的插件,PaginationPlugin。 此,我们可以使用这个插件。 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4654298.html,如需转载请自行联系原作者
标题效果: The TV shows such as You Are the One has been very popular. In order to meet the need of boys who are still single, TJUT hold the show itself. The show is hold in the Small hall, so it attract a lot of boys and girls. Now there are n boys enrolling in. At the beginning, the n boys stand in a row and go to the stage one by one. However, the director suddenly knows that very boy has a value of diaosi D, if the boy is k-th one go to the stage, the unhappiness of him will be (k-1)*D, because he has to wait for (k-1) people. Luckily, there is a dark room in the Small hall, so the director can put the boy into the dark room temporarily and let the boys behind his go to stage before him. For the dark room is very narrow, the boy who first get into dark room has to leave last. The director wants to change the order of boys by the dark room, so the summary of unhappiness will be least. Can you help him? 解题思路: 区间DP,dp[i][j]表示从i到j的沮丧值。枚举第i个人的出场顺序。 #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <string> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #define LL long long using namespace std; const int MAXN = 100 + 10; const int inf = 0x3f3f3f3f; int dp[MAXN][MAXN]; int a[MAXN], sum[MAXN]; int N; int main() { int T, kcase = 1; scanf("%d", &T); while(T--) { scanf("%d", &N); memset(sum, 0, sizeof(sum)); memset(dp, 0, sizeof(dp)); for(int i=1;i<=N;i++) { scanf("%d", &a[i]); sum[i] = sum[i-1] + a[i]; } memset(dp, 0, sizeof(dp)); for(int i=1;i<=N;i++) { for(int j=i+1;j<=N;j++) dp[i][j] = inf; } for(int len=1;len<N;len++) { for(int i=1;i+len<=N;i++) { int j = i + len; for(int k=1;k<=j-i+1;k++)//第i个人第K个上场 { dp[i][j] = min(dp[i][j], dp[i+1][i+k-1] + a[i] * (k-1) + dp[i+k][j] + k * (sum[j] - sum[i+k-1])); /*dp[i+1][i+k-1]表示前k-1个人的沮丧值,a[i] * (k-1)表示第i个人的沮丧值。而i+k到j的这些人因为出场位置都添加了K。所以总的沮丧值添加了k * (sum[j] - sum[i+k-1])。*/ } } } printf("Case #%d: %d\n", kcase++, dp[1][N]); } return 0; } 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4659811.html,如需转载请自行联系原作者
S3C2416裸机开发系列19 Fatfs播放录像wav音频文件 国际象棋男孩 1048272975 多媒体资源,一般都是以文件的形式存储在固化存储器中。Fatfs所支持的fat32为windows支持的文件系统,因此在嵌入式系统中採用Fatfs文件系统可极大地扩展系统的应用。 比如,把计算机上图片。音频,视频。文本等资源直接复制到嵌入式系统中的固化存储器中,在系统中就可以直接应用这些资源。 把嵌入式系统中录制的音频、视频直接保存成一定的格式,在计算机上可直接播放处理。把传感器採集的数据保存成txt或dat文件,在计算机上通过处理生成数据曲线分析等。 笔者此处就wav音频文件的播放与录音进行简单的介绍。 1. wav音频格式 Wave是录音时用的标准windows文件格式,文件扩展名为”.wav”,数据本身的格式为PCM或压缩型,它是由微软与IBM联合开发的用于音频数字存储的标准。採用RIFF文件格式结构。 RIFF全称资源互换文件格式。是windows下大部分多媒体文件遵循的一种文件结构,除了本文所说的波形格式数据(.wav),採用RIFF格式结构的文件还有音频视频交错格式(.avi)、位图格式(.rdi)、MIDI格式(.rmi)、调色板格式(.pal)、多媒体电影(.rmn)、动画光标(.ani)。 RIFF结构的基本单元为chunk,它的结构例如以下: struct chunk { unsignedint id; /* 块标志 */ unsignedint size; /* 块大小 */ unsigned chardata[size]; /* 块内容 */ } Id为4个ascii字符组成,用来识别块中所包括的数据,如”RIFF”、”WAV ”、”data”、”fmt ”等;size是存储在data域中数据的长度,不包括id与size域的大小;data[size]为该块保存的数据,以字为单位排列。 wav音频文件作为RIFF结构。其由若干个chunk组成。依照在文件里的位置包括:RIFF chunk。fmt chunk,fact chunk(可选)。data chunk。全部RIFF结构文件均会首先包括RIFF chunk,并指明RIFF类型,此处为”WAVE”。对于wav文件,在fmt chunk中指明音频文件的信息,比如採样位数、採样频率、声道数、编码方式等。 对于压缩型wav音频。还会有一个fact chunk。用以指明解压后音频数据的大小,对于PCM非压缩wav文件,并没有该chunk。音频数据保存在data chunk中,依据fmt chunk中指明的声道数以及採样位数。wav音频数据存放形式有不同的方式。 一个PCM格式的wav结构定义Wav.h例如以下: #ifndef __WAV_H__ #define __WAV_H__ #ifdef __cplusplus extern "C" { #endif //资源互换文件格式RIFF,树状结构,基本单位是chunk。整个文件由chunk构成 typedef struct RIFF_HEADER { char Riff_ID[4]; unsigned int Riff_Size;//记录整个RIFF文件的大小。除ID和Size这两个变量 char Riff_Format[4]; } RIFF_HEADER; typedef struct WAVE_FORMAT { unsigned short FormatTag; //声音的格式代号 unsigned short Channels; //声音通道 unsigned int SamplesPerSec; //採样率 unsigned int AvgBytesPerSec; //=採样率*区块对其单位 unsigned short BlockAlign; //区块对其单位=每一个取样所需位数*声音通道/8 unsigned short BitsPerSample; //每一个取样所需位数 } WAVE_FORMAT; typedef struct FMT_CHUNK { char Fmt_ID[4]; unsigned int Fmt_Size;//记录fmt的大小 WAVE_FORMAT WaveFormat; } FMT_CHUNK; typedef struct DATA_CHUNK { char Data_ID[4]; unsigned int Data_Size;//记录data区的大小 } DATA_CHUNK; typedef struct WAVE_HEADER { RIFF_HEADER RiffHeader; FMT_CHUNK FmtChunk; DATA_CHUNK DataChunk; } WAVE_HEADER; #ifdef __cplusplus } #endif #endif /*__WAV_H__*/ 依据以上的wav结构定义。一个录音文件的wav文件头可例如以下定义: static WAVE_HEADER RecorderWaveHeader = { 'R', 'I', 'F', 'F', sizeof(WAVE_HEADER) - 8,//整个wave文件大小,初始化值 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ', sizeof(FMT_CHUNK) - 8, 1,//编码方式。线性PCM编码 1,//单声道 10000,//採样率为10k 20000,//每一个採样2个字节 2,//每一个採样2个字节 16,//每一个採样需16位 'd', 'a', 't', 'a', 0, //data长度初始化为0 }; 2. wav音频文件的播放或录音 sd卡因为其可插拔、灵活性好,通常应用于设备的扩展存储应用。 计算机上wav音频等文件可轻易地复制到fat32格式的sd卡上。在嵌入式系统中要使用sd卡。首先需实现sd卡驱动。这在前面的章节有具体的介绍。此处不再详述。fat32文件的读写还须要对应文件系统的接口支持,此处选用Fatfs,对于不同的嵌入式系统。这是须要移植的部分。关于s3c2416下Fatfs文件系统的移植在前面章节有具体的介绍,此处不再详述。 从wav文件读出音频数据后(播放),还须要把音频传输数据给声卡,声卡还原出声音模拟信号。就可以听到声音。音频数据的处理须要用到音频编解码器,数据的传输也有一定的音频总线要求,因此还须要音频驱动的实现,这部分在前面的章节有具体的介绍。此处不再详述。 3. 应用实例 project中利用串口对耳机音量进行加大、调小。对Mic录音进行灵敏度的调节,通过串口输入进行播放wav音频或開始录音。播放时实时显示播放进度并可按下’s’后停止播放,录音时实时显示录音wav文件的大小并可按下’s’后停止录音。 main.c的内容例如以下: #include"s3c2416.h" #include"UART0.h" #include"ff.h" #include"diskio.h" #include "RTC.h" #include"Wav.h" #include"IIS.h" #include"IIC.h" #include"WM8960.h" staticWAVE_HEADER RecorderWaveHeader = { 'R', 'I', 'F', 'F', sizeof(WAVE_HEADER) - 8,//整个wave文件大小 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ', sizeof(FMT_CHUNK) - 8, 1,//编码方式,线性PCM编码 1,//单声道 10000,//採样率为10k 20000,//每一个採样2个字节 2,//每一个採样2个字节 16,//每一个採样需16位 'd', 'a', 't', 'a', 0, //data长度初始化为0 }; // 音频数据缓存20KB unsigned charAudioBuffer[20*1024]; int main() { FATFS fs; FIL file; FRESULT Res; unsigned int i; unsigned int BufferLen; unsigned char *pData; WAVE_HEADER WaveHeader; int ByteWrite, ByteRead; unsigned char State; unsigned char VolumeLevel; unsigned short Command; const char Path1[] = "test.wav"; const char Path2[] = "1.wav"; char FilePath[256]; unsigned int Size = 0; unsigned int AudioSize = 0; unsigned int TotalSize = 0; RTC_Time Time = { 2014, 5, 22, 23, 00, 0, 5 }; RTC_Init(&Time); // RTC初始化 Uart0_Init(); // 串口初始化 IIC_Init(); //IIC初始化,音频芯片控制 IIS_Init(); // IIS音频接口初始化 WM8960_Init(); // 音频编解码器初始化 RTC_GetTime(&Time); // 显示RTC时间 Uart0_Printf("Time: %4d/%02d/%02d%02d:%02d:%02d\r\n", Time.Year, Time.Month, Time.Day, Time.Hour,Time.Min, Time.Sec); f_mount(&fs, "" , 0); ByteRead = 0; pData = (unsigned char *)0; for (i=0; i<sizeof(Path1); i++) { FilePath[i] = Path1[i]; } State = 1; // 进入播放test.wav状态 while(1) { switch (State) { case 0: // 操作选择 WM8960_HeadphoneStop(); WM8960_RecorderStop(); IIS_TxPause(); IIS_RxPause(); Uart0_SendString("\r\nSelect:\r\n" "0: Play test.wav\r\n" "1: Play recording file\r\n" "2: Start recorder\r\n" "3: Recorder volume up\r\n" "4: Recorder volume down\r\n" "5: Player volume up\r\n" "6: Player volume down\r\n" ); while(State == 0) { // 等待串口选择操作,堵塞型 Command = Uart0_ReceiveByte(); switch (Command) { case '0': // 播放test.wav for (i=0; i<sizeof(Path1);i++) { FilePath[i] = Path1[i]; } State = 1; // 转到開始播放wav状态 break; case '1': // 播放录音wav for (i=0; i<sizeof(Path2);i++) { FilePath[i] = Path2[i]; } State = 1; // 转到開始播放wav状态 break; case '2': State = 3; // 转到開始录音状态 break; case '3': // Mic灵敏度添加 VolumeLevel = WM8960_RecorderVolume(VolumeUp); Uart0_Printf("Recordervolume %d%%\r\n", VolumeLevel); break; case '4': // Mic灵敏度减小 VolumeLevel =WM8960_RecorderVolume(VolumeDown); Uart0_Printf("Recorder volume%d%%\r\n", VolumeLevel); break; case '5': // 耳机音量添加 VolumeLevel =WM8960_HeadphoneVolume(VolumeUp); Uart0_Printf("Player volume%d%%\r\n", VolumeLevel); break; case '6': // 耳机音量减少 VolumeLevel =WM8960_HeadphoneVolume(VolumeDown); Uart0_Printf("Player volume%d%%\r\n", VolumeLevel); break; default: break; } } Uart0_SendString("\r\n"); break; case 1: // 開始播放音频 // 打开wav音频文件 Res = f_open(&file, FilePath, FA_READ | FA_OPEN_EXISTING); if (Res != RES_OK) { Uart0_Printf("Open %s failed\r\n",FilePath); State = 0; // 进入到操作选择界面 } else { // 读取wav音频文件头,获得音频採样率,位数,声道数信息 Res = f_read(&file, (unsignedchar *)&WaveHeader, sizeof(WAVE_HEADER),(unsigned int *)&ByteRead); if (Res != RES_OK) { f_close(&file); Uart0_Printf("Read wavheader error\r\n"); State = 0; // 进入到操作选择界面 } else { // 读取一小段音频数据到缓存中 Res = f_read(&file,(unsigned int *)AudioBuffer, sizeof(AudioBuffer), (unsignedint *)&ByteRead); if (Res != RES_OK) { Uart0_Printf("Read wavdata error\r\n"); f_close(&file); State = 0; // 进入到操作选择界面 } else { if (ByteRead <sizeof(AudioBuffer)) { // 文件到结尾 // 已播放到文件的结尾,重定位到音频文件的開始 Res = f_lseek(&file,sizeof(WAVE_HEADER)); if (Res != RES_OK) { Uart0_Printf("f_lseek error\r\n"); f_close(&file); State= 0; // 进入到操作选择界面 break; } } // 依据wav文件头的音频信息初始化音频驱动的播放參数 IIS_TxInit(WaveHeader.FmtChunk.WaveFormat.SamplesPerSec, WaveHeader.FmtChunk.WaveFormat.BitsPerSample, WaveHeader.FmtChunk.WaveFormat.Channels); // wav文件的总文件大小,bytes计 TotalSize =WaveHeader.RiffHeader.Riff_Size; pData = AudioBuffer; // 播放指向音频缓存区 // 把pData指向的数据写入音频缓存,最大同意写入 // ByteRead字节,返回实际写入到音频缓存的字节数 BufferLen = IIS_WriteBuffer(pData,ByteRead); ByteRead -= BufferLen; // 数据剩余字节数 pData += BufferLen; // 数据下一次開始写入的位置 Size = BufferLen; // 播放的长度 AudioSize = 0; // 已播放的音频长度 WM8960_HeadphoneStart(); // 打开耳机播放通道 IIS_TxStart(); // IIS開始传输音频播放 State= 2; // 转入正在播放音频状态 Uart0_SendString("PlayingMusic, press 's' to stop" "playing at any time\r\n"); Uart0_SendString("Playbackprogress: 00.0%"); } } } break; case 2:// 正在播放音频 if (ByteRead > 0) { // 返回值的高8位不为0,说明低8位键值有效,查询是否有串口输入,非堵塞 Command = Uart0_Peek(); if (Command & (0xff<<8)) {// 有按键按下 if ((Command & 0xff) == 's'){ // 按下了's' f_close(&file); State = 0; // 返回到操作选择界面 break; } } if (Size > 20*1024) { // 播放了20k大小的音频数据 AudioSize += (Size>>10);// 累计己播放的总音频数据大小(KB) Size = 0; Uart0_SendString("\b\b\b\b\b"); // 显示播放进度的百分比 Uart0_Printf("%02d.%d%%",(AudioSize*100)/(TotalSize>>10), ((AudioSize*100)%(TotalSize>>10))*10/(TotalSize>>10)); } // 连续写入音频数据到音频缓存中,实现连续播放 BufferLen = IIS_WriteBuffer(pData,ByteRead); ByteRead -= BufferLen; // 数据剩余字节数 pData += BufferLen; // 数据下一次開始写入的位置 Size += BufferLen; } else { // 播放完缓存中的音频数据,再从sd卡载入下一段音频数据 // 一段音频数据播放完后,从sd卡中载入下一段数据 Res = f_read(&file, (unsignedchar *)AudioBuffer, sizeof(AudioBuffer),(unsigned int *)&ByteRead); if (Res != RES_OK) { Uart0_Printf("Read wav dataerror\r\n"); f_close(&file); State = 0; // 进入到操作选择界面 } else { pData = AudioBuffer; // 重定位到数据首位置 if (ByteRead <sizeof(AudioBuffer)) { // 到文件结尾,文件重定位到开头,重播放 Uart0_Printf("\r\n"); Uart0_Printf("replay%s\r\n", FilePath); Uart0_SendString("Playbackprogress: 00.0%"); Size = 0; AudioSize = 0; Res = f_lseek(&file,sizeof(WAVE_HEADER)); if (Res != RES_OK) { Uart0_Printf("Replayaudio error\r\n"); f_close(&file); State = 0; // 进入到操作选择界面 } } } } break; case 3: // 開始录音 // 创建录音保存1.wav文件 Res = f_open(&file, "1.wav",FA_WRITE | FA_CREATE_ALWAYS); if (Res != RES_OK) { Uart0_Printf("Create 1.wavfailed\r\n"); State = 0; // 进入到操作选择界面 } else { // 写入wav文件头 Res = f_write(&file, (unsignedchar *)&RecorderWaveHeader, sizeof(WAVE_HEADER), (unsignedint *)&ByteWrite); if (Res != RES_OK) { f_close(&file); Uart0_Printf("Write wavheader error\r\n"); State = 0; // 进入到操作选择界面 } else { // 初始化录音參数,採样率,採样位数,声道数 IIS_RxInit(RecorderWaveHeader.FmtChunk.WaveFormat.SamplesPerSec, RecorderWaveHeader.FmtChunk.WaveFormat.BitsPerSample, RecorderWaveHeader.FmtChunk.WaveFormat.Channels); Size = 0; AudioSize = 0; // 总录音文件大小初始化0 pData = AudioBuffer; // 指向录音缓存区 ByteWrite = sizeof(AudioBuffer);// 一段音频缓存的大小 WM8960_RecorderStart(); //WM8960打开录音通道 IIS_RxStart(); // IIS開始接收录音数据 State = 4; // 转到正在录音状态 Uart0_SendString("Recording,press 's' to stop recording" "at any time\r\n"); Uart0_SendString("Recording(KB): "); } } break; case 4:// 正在录音 if (ByteWrite > 0) { // 返回值的高8位不为0,说明低8位键值有效,查询是否有串口输入,非堵塞 Command = Uart0_Peek(); if (Command & (0xff<<8)) {// 有按键按下 if ((Command & 0xff) == 's'){ // 按下了's' // 停止录音,更改wav文件头文件大小 f_lseek(&file, 0); // 定位到文件头 // 数据大小改为录音的音频大小 RecorderWaveHeader.DataChunk.Data_Size= AudioSize; // RIFF大小改为整个文件文件的大小 RecorderWaveHeader.RiffHeader.Riff_Size= (sizeof(WAVE_HEADER)-8) + AudioSize; // 更改wav文件头信息 f_write(&file, (unsignedchar *)&RecorderWaveHeader, sizeof(WAVE_HEADER),(unsigned int *)&ByteWrite); f_close(&file); State = 0; // 进入到操作选择界面 break; } } if (Size > 20*1024) { // 记录了20k大小的音频数据 AudioSize += Size; // 累计己播放的总音频数据大小 Size = 0; Uart0_SendString("\b\b\b\b\b\b"); // 显示已录音的文件大小 Uart0_Printf("%6d",(AudioSize>>10)); } // 从音频缓存中读取录音数据到pData中,最大同意读取ByteWrite // 字节大小,返回实际从音频缓存中读取的字节数 BufferLen = IIS_ReadBuffer(pData,ByteWrite); ByteWrite -= BufferLen; // 剩余内存空间字节数 pData += BufferLen; // 下一位读開始存入的内存位置 Size += BufferLen; } else { // 缓存已满,写入缓存数据到sd卡中 Res = f_write(&file, (unsignedchar *)&AudioBuffer, sizeof(AudioBuffer),(unsigned int *)&ByteWrite); if (Res != RES_OK) { f_close(&file); Uart0_Printf("Write 1.waverror\r\n"); State = 0; // 进入到操作选择界面 } else { pData = AudioBuffer; ByteWrite = sizeof(AudioBuffer); } } break; default: break; } } } 4. 附录 通过Fatfs的api函数,能够轻易读写windows下常见格式文件,这和windows/Linux下操作文件差异不大。播放对wav音频文件无特殊要求。可随意採样率、採样位数、单/双声道,插上耳机即能听到声音,录制wav音频对採样率、採样位数、声道数、录制长度等均没有不论什么限制。录制好的wav音频文件可直接在计算机上播放。尽管wav格式音频文件较占用存储空间。但其是无损的,音质在同样码率下远好于mp3等有损压缩音频文件。 Wav_GCC.rar,GCC下wav音频文件播放与录制project。可直接make。 http://pan.baidu.com/s/1c05s2cg Wav_MDK.rar,MDK下wav音频文件播放与录制project http://pan.baidu.com/s/1i33guiD test.wav,wav播放測试音频文件,11.025k採样率、16位、单声道音乐。可通过音频格式转换软件生成wav音频文件。 http://pan.baidu.com/s/1eQzOErg 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4661527.html,如需转载请自行联系原作者
给定一个字符串,切割字符串,这样每个子字符串是一个回文字符串。 要找出所有可能的组合。 办法:暴力搜索+回溯 class Solution { public: int *b,n; vector<vector<string> >ans; void dfs(int id,string &s,int len){ if(id>=n){ if(len>0){ vector<string>vt; vt.push_back(s.substr(0,b[0]+1)); for(int i=1;i<len;++i){ vt.push_back(s.substr(b[i-1]+1,b[i]-b[i-1])); } ans.push_back(vt); } return; } int j,k; b[len]=id; dfs(id+1,s,len+1); for(j=id+1;j<n;++j){ for(k=0;id+k<j-k&&s[id+k]==s[j-k];++k); if(id+k>=j-k){ b[len]=j; dfs(j+1,s,len+1); } } } vector<vector<string> > partition(string s) { n=s.size(); if(n==0)return ans; if(n==1){ vector<string>vt; vt.push_back(s); ans.push_back(vt); return ans; } b=new int[n]; dfs(0,s,0); return ans; } }; 版权声明:本文博主原创文章,博客,未经同意不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4886250.html,如需转载请自行联系原作者
atitit.标准时间格式 相互转换 秒数 最佳实践 例如00:01:19 转换为秒数 79,,and互相转换 一个思路是使用div 60 mod...只是麻烦的... 更好的方法是使用stamp ... 前台加入个日期,使用时间戳来计算... 作者:: 老哇的爪子 Attilax 艾龙, EMAIL:1466519819@qq.com 转载请注明来源: http://blog.csdn.net/attilax public static void main(String[] args) throws ParseException { // TODO Auto-generated method stub String s="00:01:09"; int sec=str2secs(s); //69 System.out.println(sec); sec=79; //00:01:19 System.out.println(secs2str(sec)); } private static String secs2str(int sec) throws ParseException { String date="2014-01-01"; Date start= DateUtil.str2date_excpt(date+" 00:00:00", true); long endTimestamp = sec*1000+start.getTime(); Date end=new Date(endTimestamp); String s=DateUtil.date2str(end, true); String[] sa=s.split(" "); return sa[1]; } private static int str2secs(String s) throws ParseException { String date="2014-01-01"; String full=date+" "+s; Date dt= DateUtil.str2date_excpt(full, true); Date dt2= DateUtil.str2date_excpt(date+" 00:00:00", true); int i=DateUtil.getSecondInterval(dt2, dt); return i; } 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5031177.html,如需转载请自行联系原作者
标题效果:给定的长度m数字字符串s。求不包括子s长度n数字串的数目n<=10^9 看这个O(n)它与我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案例如,当s至12312时间 f[i][3]它表示的长度i。123结尾且不包括子串”12312“的方案数a[x][y]为f[i-1][x]转移至f[i][y]的方案数换句话说(可能描写叙述不清楚) a[x][y]为s的长度为x的前缀加上一个数字后 后缀能够与最长长度为y的前缀匹配 这个数字能够有多少种比方说12312 这个数字串生成的a数组为(数组从0開始):9 1 0 0 0 08 1 1 0 0 08 1 0 1 0 09 0 0 0 1 08 1 0 0 0 1a[2][1]=1 表示长度为2的前缀加上一个'1'之后最多与长度为1的前缀匹配a[4][0]=8 表示长度为4的前缀加上'1''2'以外的数就变成了长度为0的前缀可是a[x][5]表示全然匹配,不满足要求的题意,所以我们矩阵乘法时不考虑这一列我们发现f[i-1]乘上这个矩阵就变成了f[i] 这个矩阵怎么求呢?KMP算法,对于每一个长度的前缀枚举下一个字符进行转移 详细写法详见代码f初值是f[0][0]=1,f[0][x]=0 (x>0)于是最后我们仅仅须要取答案矩阵的第一行就可以去网上找了一堆题解才看懂0.0 这里写的略微具体一点吧 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; struct matrix{ int xx[22][22]; int* operator [] (int x) { return xx[x]; } }a,b; int n,m,p,ans; char s[100]; int next[100]; void operator *= (matrix &x,matrix &y) { int i,j,k; matrix z; memset(&z,0,sizeof z); for(i=0;i<m;i++) for(j=0;j<m;j++) for(k=0;k<m;k++) z[i][j]+=x[i][k]*y[k][j],z[i][j]%=p; x=z; } void KMP() { int i,fix=0; char j; for(i=2;i<=m;i++) { while( fix && s[fix+1]!=s[i] ) fix=next[fix]; if( s[fix+1]==s[i] ) ++fix; next[i]=fix; } for(i=0;i<m;i++) for(j='0';j<='9';j++) { fix=i; while( fix && s[fix+1]!=j ) fix=next[fix]; if( j==s[fix+1] ) b[i][fix+1]++; else b[i][0]++; } } void Quick_Power(int x) { while(x) { if(x&1)a*=b; b*=b; x>>=1; } } int main() { int i; cin>>n>>m>>p; scanf("%s",s+1); KMP(); for(i=0;i<m;i++) a[i][i]=1; Quick_Power(n); for(i=0;i<m;i++) ans+=a[0][i],ans%=p; cout<<ans<<endl; } 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4679508.html,如需转载请自行联系原作者
1 准备工作 所有是依照官方操作的:http://wiki.ros.org/groovy/Installation/Source apt-get install python-rosdep python-rosinstall-generator python-wstool build-essential 出现错误,找不到源 ,那个就要进入提示的页面:If you have trouble installing the packages in the command above, make sure you have added the packages.ros.org debian repository to your apt source lists as described starting here: groovy/Installation/Ubuntu#groovy.2BAC8-Installation.2BAC8-Sources.Setup_your_sources.list 依照里面步骤更新源,目的是可以安装ROS的工具。安装下面依赖库 sudo apt-get install build-essential python-yaml cmake subversion wget python-setuptools mercurial git-core python-rosdep python-rospkg python-rosinstall sudo apt-get install python-yaml libapr1-dev libaprutil1-dev libbz2-dev python-dev python-empy python-nose libgtest-dev python-paramiko libboost-all-dev liblog4cxx10-dev pkg-config sudo apt-get install python-wxgtk2.8 python-gtk2 python-matplotlib libwxgtk2.8-dev python-imaging libqt4-dev graphviz qt4-qmake python-numpy ros-fuerte-swig-wx wget http://peak.telecommunity.com/dist/ez_setup.py python ez_setup.py 利用easy_install安装pip:(http://www.ros.org/wiki/ROS/Installation/EasyInstallConfig) sudo easy_install pip 然后安装下面的包:(http://www.ros.org/wiki/fuerte/Installation/Ubuntu/Source) sudo pip install -U rosdep sudo pip install -U rosinstall sudo pip install -U rospkg 安装python-wstool: pip install -U wstool redep初始化: sudo rosdep init rosdep update 2 下载源代码 mkdir ~/ros_catkin_ws cd ~/ros_catkin_ws 3 我晕 搞错了 以上的步骤纯粹是从源代码安装。每必要啊 。能够从官方提供的方法http://wiki.ros.org/groovy/Installation/UbuntuARM ,直接获取编译后的文件就能够用了。何必自己去编译呢,劳民伤財。 本来LINUX基础就不是非常好,还这么脑残的去自己编译。傻叉啊! Configure your Ubuntu repositories 配置你的UBUNTU http://wiki.ros.org/groovy/Installation/UbuntuARM Setup your sources.list Ubuntu 11.10 (Oneiric armel) sudo sh -c 'echo "deb http://packages.ros.org/ahendrix-mirror/ubuntu oneiric main" > /etc/apt/sources.list.d/ros-latest.list' Ubuntu 12.04 (Precise armel) sudo sh -c 'echo "deb http://packages.ros.org/ahendrix-mirror/ubuntu precise main" > /etc/apt/sources.list.d/ros-latest.list' Ubuntu 12.04 (Precise armhf) sudo sh -c 'echo "deb http://packages.namniart.com/repos/ros precise main" > /etc/apt/sources.list.d/ros-latest.list' Ubuntu 12.10 (Quantal armhf) sudo sh -c 'echo "deb http://packages.namniart.com/repos/ros quantal main" > /etc/apt/sources.list.d/ros-latest.list' Set up your keys wget http://packages.ros.org/ros.key -O - | sudo apt-key add - wget http://packages.namniart.com/repos/namniart.key -O - | sudo apt-key add - Installation First, make sure your Debian package index is up-to-date: sudo apt-get update There are many different libraries and tools in ROS. Most of the default configurations do not yet compile fully on ARM. You can also install ROS packages individually. ROS-Base: (Bare Bones) ROS package, build, and communication libraries. No GUI tools. sudo apt-get install ros-groovy-ros-base Individual Package: You can install a specific ROS package (replace underscores with dashes of the package name): sudo apt-get install ros-groovy-PACKAGE e.g. sudo apt-get install ros-groovy-ros To find available packages, use: apt-cache search ros-groovy 这里我选择在zynq上安装的是ROS-Base包,不含GUI Initialize rosdep sudo apt-get install python-rosdepsudo rosdep initrosdep update Environment setup echo "source /opt/ros/groovy/setup.bash" >> ~/.bashrcsource ~/.bashrc source /opt/ros/groovy/setup.bash Getting rosinstall sudo apt-get install python-rosinstall 開始官方的0基础教程 http://wiki.ros.org/ROS/Tutorials 參考: http://wiki.ros.org/groovy/Installation/UbuntuARM -- 很好 http://blog.csdn.net/hcx25909/article/details/8539587 http://www.eefocus.com/hcx196/blog/ http://www.eefocus.com/hcx196/blog/13-01/291235_cea1f.html 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5056624.html,如需转载请自行联系原作者
上一篇聊聊高并发(二十八)解析java.util.concurrent各个组件(十) 理解ReentrantReadWriteLock可重入读-写锁 讲了可重入读写锁的基本情况和基本的方法,显示了怎样实现的锁降级。可是以下几个问题没说清楚,这篇补充一下 1. 释放锁时的优先级问题。是让写锁先获得还是先让读锁先获得 2. 是否同意读线程插队 3. 是否同意写线程插队,由于读写锁一般用在大量读,少量写的情况,假设写线程没有优先级,那么可能造成写线程的饥饿 关于释放锁后是让写锁先获得还是让读锁先获得,这里有两种情况 1. 释放锁后,请求获取写锁的线程不在AQS队列 2. 释放锁后。请求获取写锁的线程已经AQS队列 假设是第一种情况。那么非公平锁的实现下,获取写锁的线程直接尝试竞争锁也不用管AQS里面先来的线程。获取读锁的线程仅仅推断是否已经有线程获得写锁(既Head节点是独占模式的节点),假设没有,那么就不用管AQS里面先来的准备获取读锁的线程。 static final class NonfairSync extends Sync { private static final long serialVersionUID = -8159625535654395037L; final boolean writerShouldBlock() { return false; // writers can always barge } final boolean readerShouldBlock() { return apparentlyFirstQueuedIsExclusive(); } } 在公平锁的情况下。获取读锁和写锁的线程都推断是否已经或先来的线程再等待了。假设有,就进入AQS队列等待。 static final class FairSync extends Sync { private static final long serialVersionUID = -2274990926593161451L; final boolean writerShouldBlock() { return hasQueuedPredecessors(); } final boolean readerShouldBlock() { return hasQueuedPredecessors(); } } 对于另外一种情况,假设准备获取写锁的线程在AQS队列里面等待。那么实际是遵循先来先服务的公平性的,由于AQS的队列是FIFO的队列。所以获取锁的线程的顺序是跟它在AQS同步队列里的位置有关系。 以下这张图模拟了AQS队列中等待的线程节点的情况 1. Head节点始终是当前获得了锁的线程 2. 非Head节点在竞争锁失败后。acquire方法会不断地轮询。于自旋不同的是,AQS轮询过程中的线程是堵塞等待。 所以要理解AQS的release释放动作并非让兴许节点直接获取锁。而是唤醒兴许节点unparkSuccessor()。 真正获取锁的地方还是在acquire方法,被release唤醒的线程继续轮询状态,假设它的前驱是head,而且tryAcquire获取资源成功了,那么它就获得锁 public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return interrupted; } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } 3. 图中Head之后有3个准备获取读锁的线程,最后是1个准备获取写锁的线程。 那么假设是AQS队列中的节点获取锁 情况是第一个读锁节点先获得锁。它获取锁的时候就会尝试释放共享模式下的一个读锁。假设释放成功了,下一个读锁节点就也会被unparkSuccessor唤醒,然后也会获得锁。 假设释放失败了。那就把它的状态标记了PROPAGATE,当它释放的时候。会再次取尝试唤醒下一个读锁节点 假设后继节点是写锁。那么就不唤醒 private void doAcquireShared(int arg) { final Node node = addWaiter(Node.SHARED); boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head) { int r = tryAcquireShared(arg); if (r >= 0) { setHeadAndPropagate(node, r); p.next = null; // help GC if (interrupted) selfInterrupt(); failed = false; return; } } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } private void setHeadAndPropagate(Node node, int propagate) { Node h = head; // Record old head for check below setHead(node); if (propagate > 0 || h == null || h.waitStatus < 0) { Node s = node.next; if (s == null || s.isShared()) doReleaseShared(); } } private void doReleaseShared() { for (;;) { Node h = head; if (h != null && h != tail) { int ws = h.waitStatus; if (ws == Node.SIGNAL) { if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) continue; // loop to recheck cases unparkSuccessor(h); } else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) continue; // loop on failed CAS } if (h == head) // loop if head changed break; } } AQS的FIFO队列保证了在大量读锁和少量写锁的情况下,写锁也不会饥饿。 关于读锁能不能插队的问题,非公平性的Sync提供了插队的可能,可是前提是它在tryAcquire就成功获得了。假设tryAcquire失败了,它就得进入AQS队列排队。也不会出现让写锁饥饿的情况。 关于写锁能不能插队的情况,也是和读锁一样,非公平的Sync提供了插队的可能,假设tryAcquire获取失败,就得进入AQS等待。 最后说说为什么Semaphore和ReentrantLock在tryAcquireXX方法就实现了非公平性和公平性,而ReentrantReadWriteLock却要抽象出readerShouldBlock和writerShouldBlock的方法来单独处理公平性。 abstract boolean readerShouldBlock(); abstract boolean writerShouldBlock(); 原因是Semaphore仅仅支持共享模式,所以它仅仅须要在NonfairSync和FairSync里面实现tryAcquireShared方法就能实现公平性和非公平性。 ReentrantLock仅仅支持独占模式,所以它仅仅须要在NonfairSync和FairSync里面实现tryAcquire方法就能实现公平性和非公平性。 而ReentrantReadWriteLock即要支持共享和独占模式。又要支持公平性和非公平性。所以它在基类的Sync里面用tryAcquire和tryAcquireShared方法来区分独占和共享模式。 在NonfairSync和FairSync的readerShouldBlock和writerShouldBlock里面实现非公平性和公平性。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5058166.html,如需转载请自行联系原作者
题目描写叙述 小瑜3岁了。非常喜欢玩皮球。看来今后喜欢打篮球的^_^。近期她发现球从手中落下时,每次落地后反跳回原高度的一半,再落下,每次球落地时数球跳了几次,数到n次时爸爸在边上喊停,问小瑜如今球究竟总共走了多少距离,小瑜故作沉思状。爸爸又问接下来小球能跳多高啊,小瑜摇摇头。心想还没跳我怎么知道啊。难道爸爸是神啊!这时的你在边上出主意想给小瑜写个程序计算一下,因此任务就交给你啦!如果球的初始高度为h。计算第n次落地时球经过的距离。以及落地后反弹能有多高。 输入 输入数据有多组,第一行为数据的组数t,以下t行为t组数据,每行有两个数h和n,分别用空格分隔。 输出 输出第n次反弹时球经过的距离和球最后的高度。保留小数点后2位。 例子输入 2 100 1 100.0 2 例子输出 100.00 50.00 200.00 25.00 代码 #include<iostream> #include <cstdio> #include <cstring> #include <iomanip> using namespace std; int main() { int m,i; double h,n,sum,ne; cin>>m; while(m--) { cin>>h>>n; sum=h; ne=h/2; for(i=1;i<n;++i) { h/=2.0; sum+=2*h; ne/=2; } cout<<setiosflags(ios::fixed)<<setprecision(2); cout<<sum<<" "<<ne<<endl; } return 0; } 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5058607.html,如需转载请自行联系原作者
首先是在安装cmake的过程中遇到的问题: 1.開始使用yum命令安装时,不知道为什么一直不行,然后就准备wget 来先下载压缩包,再手动编译。 因为网络限制,wget不能下载外网的东西一直显示connection timed out 起初我还一直以为环境有问题。一直解决这个连接超时的问题。后面我開始从本地下载后上传到linuxserver上,由于是在secureCRT上ssh的,所以就须要用到了rz和sz命令。 关于secyureCRT的默认环境的设置,在opetion-》session opetion以下,能够选择默认文件夹,然后是rz的命令,从本地上传到linuxserver上,開始没有加參数-be 就一直传乱码 和出错,然后就又一次运行 rz -be 。 在这个过程中还顺道查了下怎么删除文件夹下乱码名字的文件的过程: 是我们知道每一个文件都有一个i节点号。我们能够考虑通过i节点号来管理文件。首先,我们要取得文件的 i节点号。 这个能够通过ls命令的-i选项获得得。 -bash-3.00$ ls -i 41697812 a 32983551 di 32983554 ethnet.c 32983543 hard_link 32983542 de.c 32983544 ethnet 32983541 ethnet.h 32983543 kstat 每一个文件名称前面的数字就是文件的i节点号。有了文件的i节点号,我们就能够利用find命令的-inum选项配合 经常使用的文件管理命令进行文件管理了。比如,假设要删除di文件,命令例如以下:-bash-3.00$ find . -inum 32983551 -exec rm {} \; -bash-3.00$ ls a de.c ethnet ethnet.c ethnet.h hard_link kstat 2。将相应的压缩包上传到linuxserver相应文件夹下后,运行解压安装就能够了 http://www.cnblogs.com/mophee/archive/2013/03/19/2969456.html 3.有了这个Cmake,然后就能够运行mysql的安装脚本文件了。 这就是为什么之前一直是cmake不通过的原因。这个可能须要一定的安装时间,不要着急。 以下就是在安装完毕后的一些使用了。以下会有专门的I帖子进行说明。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5058961.html,如需转载请自行联系原作者
运用贝塞尔曲线的光滑性来穿过这些点。 大致思路就是 先算出相邻原始点的中点,在把相邻中点连成的线段平移到相应的原始点,以平移后的中点作为控制点。相邻原始点为起始点画贝塞尔曲线。这样就保证了连接处的光滑。而贝塞尔曲线本身是光滑的,所以就把这些原始点用光滑曲线连起来了。 我封装了一个函数,留着以后用。 (c++版。其他语言仅仅要把数组和可变数组略微变一下就能用) [cpp] view plaincopy void createCurve(CvPoint *originPoint,int originCount,vector<CvPoint> &curvePoint){ //控制点收缩系数 。经调试0.6较好,CvPoint是opencv的,可自行定义结构体(x,y) float scale = 0.6; CvPoint midpoints[originCount]; //生成中点 for(int i = 0 ;i < originCount ; i++){ int nexti = (i + 1) % originCount; midpoints[i].x = (originPoint[i].x + originPoint[nexti].x)/2.0; midpoints[i].y = (originPoint[i].y + originPoint[nexti].y)/2.0; } //平移中点 CvPoint extrapoints[2 * originCount]; for(int i = 0 ;i < originCount ; i++){ int nexti = (i + 1) % originCount; int backi = (i + originCount - 1) % originCount; CvPoint midinmid; midinmid.x = (midpoints[i].x + midpoints[backi].x)/2.0; midinmid.y = (midpoints[i].y + midpoints[backi].y)/2.0; int offsetx = originPoint[i].x - midinmid.x; int offsety = originPoint[i].y - midinmid.y; int extraindex = 2 * i; extrapoints[extraindex].x = midpoints[backi].x + offsetx; extrapoints[extraindex].y = midpoints[backi].y + offsety; //朝 originPoint[i]方向收缩 int addx = (extrapoints[extraindex].x - originPoint[i].x) * scale; int addy = (extrapoints[extraindex].y - originPoint[i].y) * scale; extrapoints[extraindex].x = originPoint[i].x + addx; extrapoints[extraindex].y = originPoint[i].y + addy; int extranexti = (extraindex + 1)%(2 * originCount); extrapoints[extranexti].x = midpoints[i].x + offsetx; extrapoints[extranexti].y = midpoints[i].y + offsety; //朝 originPoint[i]方向收缩 addx = (extrapoints[extranexti].x - originPoint[i].x) * scale; addy = (extrapoints[extranexti].y - originPoint[i].y) * scale; extrapoints[extranexti].x = originPoint[i].x + addx; extrapoints[extranexti].y = originPoint[i].y + addy; } CvPoint controlPoint[4]; //生成4控制点。产生贝塞尔曲线 for(int i = 0 ;i < originCount ; i++){ controlPoint[0] = originPoint[i]; int extraindex = 2 * i; controlPoint[1] = extrapoints[extraindex + 1]; int extranexti = (extraindex + 2) % (2 * originCount); controlPoint[2] = extrapoints[extranexti]; int nexti = (i + 1) % originCount; controlPoint[3] = originPoint[nexti]; float u = 1; while(u >= 0){ int px = bezier3funcX(u,controlPoint); int py = bezier3funcY(u,controlPoint); //u的步长决定曲线的疏密 u -= 0.005; CvPoint tempP = cvPoint(px,py); //存入曲线点 curvePoint.push_back(tempP); } } } //三次贝塞尔曲线 float bezier3funcX(float uu,CvPoint *controlP){ float part0 = controlP[0].x * uu * uu * uu; float part1 = 3 * controlP[1].x * uu * uu * (1 - uu); float part2 = 3 * controlP[2].x * uu * (1 - uu) * (1 - uu); float part3 = controlP[3].x * (1 - uu) * (1 - uu) * (1 - uu); return part0 + part1 + part2 + part3; } float bezier3funcY(float uu,CvPoint *controlP){ float part0 = controlP[0].y * uu * uu * uu; float part1 = 3 * controlP[1].y * uu * uu * (1 - uu); float part2 = 3 * controlP[2].y * uu * (1 - uu) * (1 - uu); float part3 = controlP[3].y * (1 - uu) * (1 - uu) * (1 - uu); return part0 + part1 + part2 + part3; } 翻译] AGG 之贝塞尔插值 文章分类:综合技术 原文地址:http://www.antigrain.com/research/ bezier_interpolation/index.html#PAGE_BEZIER_INTERPOLATION Interpolation with Bezier Curves 贝塞尔插值 A very simple method of smoothing polygons 一种很easy的多边形平滑方法 翻译:唐风 之前 comp.graphic.algorithms 上有一个讨论,是关于怎么样使用曲线对多边形进行插值处理,使得终于产生的曲线是光滑的并且能通过全部的顶点。 Gernot Hoffmann 建议说使用著名的 B-Spline 来进行插值。这里有他当时的文章 。B-Spline 在这里效果非常好,它看起来就像是一个固定在多边形顶点上的橡皮尺(elastic ruler)。 但我有个大胆的猜測,我认为肯定还存在更简单的方法。比方,使用三次贝塞曲线(cubic Bezier)进行近似。贝塞尔曲线有两个固定点(起点和终点)。另加两个决定曲线形状的控制点(CP)。关于贝塞尔曲线的很多其它知识能够在搜索引擎中找到,比方,你能够參考Paul Bourke 的网站 。 如今给贝塞尔曲线的锚点(固定点),也就是多边形的某一对顶点。那么问题是,我们怎么计算控制点的位置?我执行 Xara X 然后画出了右边这个图形,这非常easy,所以我决定尝试下计算出它们的坐标。非常显然,多边形两条相邻边的两个控制点与这两个控制点之间的顶点应该在一条直线 上。仅仅有这样,两条相邻的插值曲线才干平滑地连接在一起。所以。这两个控制点应该是相对于顶点是对称的,只是,也不全是……。由于真正的对称就要求它们与 中心点的距离应该是相等的,但对于我们的情况中并不全然是这种。一開始。我试着先算出多边形两条边的角平分线。然后把控制点放在这条角平分线的垂直线 上。但从图上能够看到。控制点的连线并不会总是垂直于角平分线的。 终于,我找到一个很easy的办法,不须要不论什么复杂的数学计算。首先。我们计算出多边形全部边线的中点,Ai。 然后连接起相邻边中点,得到非常多线段,记为 Ci 。并用图记的方法计算出 Bi 点。 最后一步,仅仅须要简单地将 Ci 进行平移,平移的路径就是每条线段上 Bi 到相应顶点的路径。 就这样,我们计算出了贝塞尔曲线的控制点。平滑的结果看起来也非常棒。 这里还能够做一点小小的改进。由于我们已经得到了一条决定控制点的直线,所以,我们能够依据须要。使控制点在这条直线上移动,这样能够改变插值曲线 的状态。我使用了一个与控制点和顶点初始距离相关的系数 K ,用来沿直线移动控制点。 控制点离顶点越远,图形看起来就越锐利。 以下是用原始形状和系统K=1.0的贝塞尔插值两种方法来描画的 SVG 的狮子。 以下是放大图 不积跬步无以至千里,闲来无事。搞一个属于自己的小站,假设看到这篇文章感觉对你有帮助的话,就支持关注一下我的小站:我的小站 这种方法仅仅是探索和经验式的。假设从严格的数学模型的角度看它可能是错误的。但在实际使用中的效果已经足够好了,而 且这种方法仅仅须要最小的计算量。以下的代码就是用来画出上面狮子图像的。这些代码并没有进行优化。仅仅是用来演示的。里面有些变量计算了两次,在实际程序 中,假设连续的步骤中都用到同一个变量值,我们能够先缓存变量值进行复用(以避免反复的计算)。 你能够下载一个能执行的画狮子的样例,对它进行旋转和缩放。也能够生成一些随机的多边形。点左键并拖动它能够环绕中 心点旋转和缩放图像。点右键并从左向右拖动。能够改变系统数K。 K=1时大约是距窗体左边100像素处。每次双击会产生一个随机的多边形。对于这些多边形。也能够进行旋转、缩放以及改变K值的操作 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5062590.html,如需转载请自行联系原作者
有时,我们会遇到将是一个TR以下任务task发布,然后想改变,或不想转移TR。 或想删除已释放TR. 研究发现后面,TR(任务)存储在数据库表汇的相应数据:E070(变化 & 交通系统: 求/任务的抬头)中 故想到直接操作数据表E070的请求/任务状态字段(TRSTATUS),改动其内容值,达到还原处理。 状态一览: D 可改动 L 可改动,受保护 O 已启动公布 R 已公布 N 已公布(含对已修复对象的导入保护) 发现操作方法有下面几种: 1.coding(在开发机端可操作) TABLES: e070. PARAMETERS : p_trkorr LIKE e070-trkorr OBLIGATORY. UPDATE e070 SET trstatus = 'D' "将状态还原成‘可改动’ WHERE trkorr = p_trkorr. "输入的须要处理的TR IF sy-subrc = 0. COMMIT WORK. MESSAGE 'OK' TYPE 'S'. ELSE. ROLLBACK WORK. MESSAGE 'ERROR!' TYPE 'E'. ENDIF. 2.硬操作-直接改动表中的值(要求账户有一点的操作权限) 2-1.找到须要处理的TR 2-2.进入到表中E070中,找到对应的TR,点击显示button,到行项目明细显示 2-3.命令行中输入:/H,敲入回车,进入到debug模式 2-4.将操作模式CODE,从显示模式改为编辑模式:EDIT。直接运行 2-5.改动数据,直接保存 结果图 兴许操作 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4681371.html,如需转载请自行联系原作者
背景:单位成立了技术领先的基础部门。专注于产品规划的技术解决方案部门、产品的发展规划方向、批准的项目和各部门的其他工作方案。工作内容是在这一领域没有问题。毕竟,从过去企业发展的一个部门模型现在是一个功能性的领导模式类型功能,值我称赞。但是,我们的工作非常值我称赞。工作方式是:不定期的公布一些工作通告,要求其它各部门上报本月/本季度/本年度的工作内容、产品技术方案、产品所属领域的技术行情等信息,这样的工作方式是否得当,值得认真思考? 正文:而关于这种工作方式,早在若干年前,公司对于改变工作作风就已经做了严格说明:杜绝等、靠、要的工作作风。对于以上的工作方式,事实上全然能够用“等、靠、要的工作作风”来评论。用国家经济体制的专有名词来比喻,则是计划经济体制模式的工作作风:下属单位上报工作内容,上级单位仅仅负责审核允许与否。这种工作作风有下面不好的地方: (1)抬高自己地位。不利于建立友好型部门间关系。本身技术领导型部门与其它职能型、项目型部门可能是平行单位。而经过一则通告后。让其它部门感觉到是在驾驭自己部门的工作,显得自己把自己驾驭在领导者的位置上。 (2)添加其它部门的大量工作,不能促进其它部门的工作积极性。以一则通告来要求其它部门配合工作,这些部门必然会以完毕任务的心态来交付工作内容。难以形成积极性; (3)不利于调动其它部门成员的工作创造性。 依照计划经济体制变革为市场经济体制的发展模式。笔者觉得,这个技术领导型部门应该转变工作作风,主动到其它部门基层去调研走訪,积极引导其它部门成员配合工作,以自身的调研努力来驱动、调动企业其它部门成员的工作积极性。同一时候将自己的工作成果服务于公司及其它部门的工作,让其它部门也享受到你的部门的工作福利,这样方可营造良好的互动型企业工作氛围。达到公司当初成立技术领导型部门的初衷。 结尾:望企业中的每个人都能转变工作作风,踏实做事,真正杜绝等靠要的计划经济模式,进入市场经济模式。 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4682269.html,如需转载请自行联系原作者
这可能是一个小问题。但其他人也应该得到满足。在Notesclient使用LotusScript的Print当该语句是输出到状态栏,假设实际参数传递多次调用相同,状态栏将显示只有一次的信息。 例如: Print "a" Print "a" Print "a" 不会输出三行a,而仅仅有一行。 假设作为參数的变量内容同样,多次调用也仅仅会输出一次。 比如: Print view.Toplevelentrycount Print view.Toplevelentrycount Print view.Toplevelentrycount 你也许会问,即使这有些不正常,也没什么妨碍,反复输出有什么意义呢?原因例如以下。在client应用程序中。这些对Print的调用都是为了在程序执行时给用户(不论是普通用户还是开发人员人员)信息和反馈。Print反复的静态信息的用例会出如今报告事件和处理进度时,比如在批量审批流程、处理附件、查找特定记录等等时,能够在发生或处理完一个事件后,调用这样的语句:Print"A purchase workflow is reviewed.",Print "A XXX record is found."。以上情况还能够通过在输出的信息中加入序列号来解决。 而受这样的输出丢失影响更大的则是Print的參数为变量的情况。尤其是在调试程序时。往往会在代码的不同处Print同一变量,以理解某些语句的效果或弄清错误的原因。 这时应该的多行输出变为一行,令人困扰。 当然能够人为加入一些凝视使得每次输出都有区别。但非常麻烦。 Print仅仅在client执行的代码中,也就是输出到client状态栏时,有这样的行为。包括它的代码执行在server端时,按触发方式或者输出到server控制台,或者返回给浏览器。都没有这个问题。所以这是Print语句的特性。抑或是Notes客户机状态栏的问题。似乎更有可能是后者。 这样的行为是不是bug?或者是出于某些限制或考量有意设计如此?非计算机科班出身的我,想不出来。在网上也没有查到。 只是我印象中Firefox的Firebug插件的控制台也曾有同样行为,用console.log()方法输出反复信息时。仅仅会显示一条。后来有了改进,在输出信息的左边会在括号中标注反复输出的次数,比如(5)Show me again. 剩下的就是怎样应对,即workaround。 首先easy想到的就是写一个函数包装Print。在实际要输出的信息前附上当前时间。 除却我们的目的。显示输出信息的时间本身也是故意的。 遗憾的是LotusScript里的日期时间类型Variant仅仅精确到秒,假设反复信息的输出是在同一秒内。问题依然。LotusScript可获得的最精确的当前时间是Timer函数的返回值。精确到百分之中的一个秒。于是我们能够写出例如以下函数: Public Function PrintMsg(msg As Variant) Dim strTime As String strTime=Format(Now, "hh:mm:ss") Dim hs As Long hs=Timer Mod 100 strTime=strTime & ":" & hs Print(strTime & " - " & msg) End Function 但在应用时会发现,百分之中的一个秒对于计算机和LotusScript仍然是非常漫长的(这是件好事),所以在相似以下的代码中,输出的信息对于Print语句仍然是同样的,也就会发生丢失。 call PrintMsg(view.Toplevelentrycount) Call CreateDoc(db) call PrintMsg(view.Toplevelentrycount) LotusScript里的时间仅仅精确到百分之中的一个秒,是由于Notes和Domino是跨平台的,不同操作系统支持的时间精度不等,但最少都在十毫秒数量级。 利用GetThreadInfo函数凭藉操作系统的clocktick概念实际能获得时间段的更高精度。 以下是网上曾有人对不同系统的測试结果 (http://searchdomino.techtarget.com/tip/Accurate-LotusScript-timing-technique): Ticks per second: Win2000 Domino 6.0 (ticks per second1000) Win2000 Domino 5.0.9a (ticks per second1000) AIX 4.3.3 ML 9 with Domino 5.0.11 (ticks per second = 1,000,000) Solaris 8 with Domino 5.0.11 (ticks per second = 1,000,000) SuSE Linux 8.1 with Domino 6.0.1 (ticks per second 1000) SunOS 5.8 Generic_108528-18 with Domino Release 6.0.1; (ticks per second 1000) 因此以下的代码演示了怎样获得一段时间小于一秒的部分,并将它转化到毫秒单位。 dim tick1 as Long, tick2 as Long, tps as Long tps=GetThreadInfo(7) tick1=GetThreadInfo(6) 'do something tick2=GetThreadInfo(6) dim dif as Long 'The difference of the part of milliseconds dif=((tick2-tick1) Mod tps)/tps*1000 可是由于clock tick表示的是系统时钟自开机以来的时钟周期数。并不能由它直接确定当前时间,所以不能用在我们上面的函数以获得更高的时间精度。 为了彻底解决本文所说的问题,仅仅有在每次输出前附上一个序列号。 为此须要将PrintMsg函数包装在一个对象里,从而能够操作作为对象字段的序列号。 Private printNum As Integer 'Used for distinguish printing same contents Public Function PrintMsg(msg As Variant) Dim strTime As String strTime=Format(Now, "hh:mm:ss") Dim hs As Long hs=Timer Mod 100 strTime=strTime & ":" & hs printNum=printNum+1 Print("[" & printNum & "]" & strTime & " - " & msg) End Function 调用它输出反复内容的效果例如以下: [1]16:52:36:24 – 81 [2]16:52:36:24 - 81 [3]16:52:36:24 - 81 我把这种方法加入到曾经曾介绍过的Log4Dom类里,当然诸位也能够单独为它创建一个更精简的类。 Class Log4Dom public logLevel As Integer public module As String 'module 'the Log Destination, set as a variant then depending on the log type, 'set as either a LogDB, logNotesFile, logStatus or logPrompt Private logFile As Variant Private s As NotesSession Private db As NotesDatabase 'current database Private profile As NotesDocument 'Log4Dom profile document public logName As String 'log name from the profile Private printNum As Integer 'Used for distinguish printing same contents Sub New () Set s=New NotesSession logLevel = LEVEL_DEBUG End Sub %REM Add a log destination. As the de facto only used log destination is Notes DB, I didn't handle the case of multiple log destinations of different types. %END REM Public Function AddLogFile(file As Variant) Set logFile = file If TypeName(file)="LOGDB" then 'read parameter from Log4Dom profile by starrow Set db=s.CurrentDatabase Set profile=db.GetProfileDocument("Log4DomProfile") If Not profile Is Nothing Then If profile.GetItemValue("LogLevel")(0)><"" then logLevel=profile.GetItemValue("LogLevel")(0) End if logName=profile.GetItemValue("LogName")(0) End If 'if no parameter provided, try the agent name If logName="" Then If Not s.CurrentAgent Is Nothing Then logName=s.CurrentAgent.Name End If End If logFile.LogName=logName End if End Function 'logging at the different levels, INFO, WARN etc Public Function Info(message As String) As Integer Info = WriteLog(LEVEL_INFO, message) End Function Public Function Warn(message As String) As Integer Warn = WriteLog(LEVEL_WARN, message) End Function Public Function Debug(message As String) As Integer Debug = WriteLog(LEVEL_DEBUG, message) End Function 'Can't use error as the function name because it's a reserved word. 'If used for logging a runtime error, leave the argument as an empty string. Public Function LogError(message As String) As Integer If message="" Then 'Generate the message for a runtime error. 'The GetThreadInfo(LSI_THREAD_CALLPROC) must be called here instead of 'calling an universal function to get the error message because that would 'always return LogError as the function raising the error. 'LSI_THREAD_CALLMODULE=11, LSI_THREAD_CALLPROC=10 message = GetThreadInfo(11) & ">" & GetThreadInfo(10) & ": " & _ "Error(" & Err() & "): " & Error() & " at line "& Erl() End If LogError = WriteLog(LEVEL_ERROR, message) End Function Public Function Fatal(message As String) As Integer Fatal = WriteLog(LEVEL_FATAL, message) End Function 'user level logging, for specific level logging '@param level integer - the level 10 is the most detail, 1 the lowest level 'message - a string to be logged. Number, boolean and date values would be 'automatically converted to strings by LotusScript. Other types should be manually converted. Public Function WriteLog(level As Integer, message As String) As Integer Dim theDate As String Dim theLevel As String Dim theMessage As String theDate = Cstr(Now) theLevel = "["+GetLevelString(level)+"] " theMessage = theDate+" "+theLevel+" "+module+" - "+message ' check that logging is turned on for this level ' otherwise there is no need to log If level <= logLevel Then Call logFile.writelog(theMessage) End If End Function 'closes the log, saves notes doc or closes file Public Function Close logFile.close End Function 'convert from level numbers into string Private Function GetLevelString(level As Integer) As String Select Case level Case LEVEL_INFO : GetLevelString = LEVEL_INFO_STRING Case LEVEL_DEBUG : GetLevelString = LEVEL_DEBUG_STRING Case LEVEL_WARN : GetLevelString = LEVEL_WARN_STRING Case LEVEL_ERROR : GetLevelString = LEVEL_ERROR_STRING Case LEVEL_FATAL : GetLevelString = LEVEL_FATAL_STRING Case Else : GetLevelString = "LEVEL "+Cstr(level) End Select End Function %REM If the argument is the same, multiple calls to Print are executed only once. This function appends the current time before the message to be printed. The time is rounded to the nearest hundredth of second. However, for some circumstances, this is still not enough to avoid the same content to be printed. Thus, a serial number is appended. %END REM Public Function PrintMsg(msg As Variant) Dim strTime As String strTime=Format(Now, "hh:mm:ss") Dim hs As Long hs=Timer Mod 100 strTime=strTime & ":" & hs printNum=printNum+1 Print("[" & printNum & "]" & strTime & " - " & msg) End Function End Class 'Get a logger instance that writes to the specified db. Public Function GetLogger(db As NotesDatabase) As log4Dom Dim logger As log4dom Set logger = New log4dom() Dim logFile As New LogDB(db) Call logger.AddLogFile(logFile) Set GetLogger=logger End Function Dim logger As Log4Dom Set logger=GetLogger(Nothing) call logger.PrintMsg(81) call logger.PrintMsg(81) call logger.PrintMsg(81) 版权声明:本文博客原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4669900.html,如需转载请自行联系原作者
atitit.无损传输二进制数据串传输网络 1. gbk的网络传输问题,为什么gbk不能使用来传输二进制数据 1 2. base64 2 3. iso-8859-1 (推荐) 2 4. utf-8 (不能使用) 2 1. gbk的网络传输问题,为什么gbk不能使用来传输二进制数据 gbk会造成信息丢失 因为有些字符在gbk字符集中找不到相应的字符。所以默认使用编码63取代,也就是?(问号)。 。。gbk只能兼容低位asc编码(英文字母),高位编码要使用来编码汉字了... 作者::老哇的爪子Attilax艾龙,EMAIL:1466519819@qq.com 转载请注明来源: http://blog.csdn.net/attilax s="我ab哈"; gbked [-50, -46, 97, 98, -71, -2] winhex CED26162B9FE ,, ce(206),d2(210) zip [120, -100, 59, 119, 41, 49, 105, -25, 63, 0, 14, 14, 4, 27] 》》》gbk str zipstr>>byteArr [120, 63, 119, 41, 49, 105, 63, 0, 14, 14, 4, 27] gbk整体编码范围为8140-FEFE,首字节在81-FE 之间,尾字节在40-FE 之间。gbk 81(129),40(64)------fe(254) 2. base64 base64最大的问题是大小新增30%... 3. iso-8859-1 (推荐) iso-8859-1 是非常好的解决...,使用它进行转码一般也没有问题。 iso-8859-1是JAVA网络传输使用的标准字符集 。当我们要把一个“字节串”转化成“字符串”,而又不知道它是哪一种 ANSI 编码时。先临时地把“每个字节”作为“一个字符”进行转化。不会造成信息丢失。 iso8859能够完美的转换0-256区间的字符。。。 不会丢失。。 ISO-8859-1 字符集的编码范围是 0000-00FF,正好和一个字节的编码范围相相应。这样的特性保证了使用 ISO-8859-1 进行编码和解码能够保持编码数值“不变”。 这样的特性保证了使用 ISO-8859-1 进行编码和解码能够保持编码数值“不变” 4. utf-8 (不能使用) s="我ab哈"; utf8 bytes [-26, -120, -111, 97, 98, -27, -109, -120] kmprs bytes [120, -100, 123, -42, 49, 49, 49, -23, -23, -28, 14, 0, 22, 32, 4, -61] >>>>utf8 str utf8str2bytes(len27) [120, -17, -65, -67, 123, -17, -65, -67, 49, 49, 49, -17, -65, -67, -17, -65, -67, -17, -65, -67, 14, 0, 22, 32, 4, -17, -65, -67] 5. 參考: 字符编码笔记:ASCII。Unicode和UTF-8 - 阮一峰的网络日志.htm 版权声明:本文博客原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4670547.html,如需转载请自行联系原作者
在Windows操作系统可以容易地创建\举\空删除的目录名格目录, 在linux我们需要一些特殊的处理能力实现上述功能. (1)创建一个目录 mkdir my\ first 此命令创建一个目录"my first",目录名中my和first之间有一个空格,在命令行中须要 加入一个"\"符号和一个空格的组合 mkdir my\ \ tow 这条命令创建了目录"my tow",目录名中my和tow之间有两个空格,在命令行中须要 加入两个"\"与空格的组合 (2)移动目录 mv my\ first /tmp 这条命令将目录"my first"移动到目录tmp下 mv my\ \ tow /tmp 这条命令将目录"my tow"移动到目录tmp下 (3)删除目录 rm -r my\ first 这条命令将目录"my\ first"删除 rm -r my\ \ tow 这条命令将目录"my\ \ tow"删除 (4)进入目录 cd my\ first 这条命令能够进入目录"my first" cd my\ \ tow 这条命令能够进入目录"my tow" (5)创建压缩文件 tar czf my\ first.tar.gz my\ first 创建压缩文件"my first.tar.gz" tar czf my\ \ tow.tar.gz my\ \ tow 创建压缩文件"my tow.tar.gz" tar cjf my\ first.tar.bz2 my\ first 创建压缩文件"my first.tar.bz2" tar cjf my\ \ tow.tar.bz2 my\ \ tow 创建压缩文件"my\ \ tow" (6)解压压缩文件 tar xzf my\ first.tar.gz 解压压缩文件"my first.tar.gz" tar xzf my\ \ tow.tar.gz 解压压缩文件"my tow.tar.gz" tar xjf my\ first.tar.bz2 解压压缩文件"my first.tar.bz2" tar xjf my\ \ tow.tar.bz2 解压压缩文件"my tow.tar.bz2" 总结:本文实现了对目录名中有空格的文件进行创建\移动\删除\进入\压缩\解压 等操作,相对于目录名中有空格的目录来说,在输入命令时须要在目录名之间 插入"\"而空格组合,有几个空的目录名格我们需要添加一些组合. 版权声明:本文博客原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4690392.html,如需转载请自行联系原作者
plan cache非常大。将仅仅使用一次的缓存计划清除,而不用清除整个cache. declare @sid varbinary(64) declare cur01 cursor for select plan_handle from ( SELECT plan_handle FROM sys.dm_exec_cached_plans AS cp CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st WHERE cp.cacheobjtype = N'Compiled Plan' AND cp.objtype IN (N'Adhoc', N'Prepared') AND cp.usecounts =1 and text like 'select%' ) c open cur01 fetch next from cur01 into @sid while @@fetch_status=0 begin DBCC FREEPROCCACHE(@sid) fetch next from cur01 into @sid end close cur01 deallocate cur01 go 版权声明:本文博客原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4713077.html,如需转载请自行联系原作者
的值的函数value按format_spec的格式来格式化,然而函数解释format_spec是依据value的类型来决定的。不同的类型有不同的格式化解释。 当參数format_spec为空时,本函数等同于函数str(value)的方式。 事实上本函数调用时,是把format(value, format_spec)的方式转换为type(value).__format__(format_spec)方式来调用。因此在value类型里就查找方法__format__(),假设找不到此方法,就会返回异常TypeError。 当中format_spec的编写方式例如以下形式: format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type] fill ::= <any character> align ::= "<" | ">" | "=" | "^" sign ::= "+" | "-" | " " width ::= integer precision ::= integer type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%" fill是表示能够填写不论什么字符。 align是对齐方式,<是左对齐, >是右对齐。^是居中对齐。 sign是符号, +表示正号, -表示负号。 width是数字宽度,表示总共输出多少位数字。 precision是小数保留位数。 type是输出数字值是的表示方式,比方b是二进制表示;比方E是指数表示。比方X是十六进制表示。 样例: #format() print(format(2918)) print(format(0x500, 'X')) print(format(3.14, '0=10')) print(format(3.14159, '05.3')) print(format(3.14159, 'E')) print(format('test', '<20')) print(format('test', '>20')) print(format('test', '^20')) 结果输出例如以下: 2918 500 0000003.14 03.14 3.141590E+00 test test test 蔡俊生 QQ:9073204 深圳 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4635450.html,如需转载请自行联系原作者
一 光流 光流的概念是Gibson在1950年首先提出来的。 它是空间运动物体在观察成像平面上的像素运动的瞬时速度。是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的相应关系。从而计算出相邻帧之间物体的运动信息的一种方法。一般而言,光流是因为场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。 其计算方法能够分为三类: (1)基于区域或者基于特征的匹配方法; (2)基于频域的方法; (3)基于梯度的方法; 简单来说,光流是空间运动物体在观測成像平面上的像素运动的“瞬时速度”。 光流的研究是利用图像序列中的像素强度数据的时域变化和相关性来确定各自像素位置的“运动”。研究光流场的目的就是为了从图片序列中近似得到不能直接得到的运动场。 光流法的前提如果: (1)相邻帧之间的亮度恒定。 (2)相邻视频帧的取帧时间连续,或者,相邻帧之间物体的运动比較“微小”; (3)保持空间一致性;即,同一子图像的像素点具有同样的运动 这里有两个概念须要解释: 运动场,事实上就是物体在三维真实世界中的运动。 光流场,是运动场在二维图像平面上的投影。 如上图所看到的,H中的像素点(x,y)在I中的移动到了(x+u,y+v)的位置,偏移量为(u,v)。 光流法用于目标检測的原理:给图像中的每一个像素点赋予一个速度矢量。这样就形成了一个运动矢量场。在某一特定时刻,图像上的点与三维物体上的点一一相应,这样的相应关系能够通过投影来计算得到。 依据各个像素点的速度矢量特征。能够对图像进行动态分析。假设图像中没有运动目标,则光流矢量在整个图像区域是连续变化的。当图像中有运动物体时。目标和背景存在着相对运动。运动物体所形成的速度矢量必定和背景的速度矢量有所不同,如此便能够计算出运动物体的位置。须要提醒的是,利用光流法进行运动物体检測时,计算量较大,无法保证实时性和有用性。 光流法用于目标跟踪的原理: (1)对一个连续的视频帧序列进行处理。 (2)针对每个视频序列。利用一定的目标检測方法,检測可能出现的前景目标; (3)假设某一帧出现了前景目标。找到其具有代表性的关键特征点(能够随机产生。也能够利用角点来做特征点); (4)对之后的随意两个相邻视频帧而言。寻找上一帧中出现的关键特征点在当前帧中的最佳位置,从而得到前景目标在当前帧中的位置坐标; (5)如此迭代进行,便可实现目标的跟踪。 IxVx+IyVy+It=0; 对于二维的运动场。单靠一个像素无法确定其运动矢量(Vx,Vy)依据如果三, 我们能够使用当前像素的邻域像素加入很多其它约束条件;如经典的Horn-Schunck光流法所加的运动平滑约束。 同一时候。对于二维运动场。仅仅需包括两条或以上边缘则能够解系统方程,因此在进行光流法时,先选择好跟踪的特征点。如harris角点。 二 KLT KLT属于光流法的一种。其前提如果与上一致 1)亮度恒定 2)时间连续或者是运动是“小运动” 3)空间一致,临近点有相似运动,保持相邻 非常直观的讲,如果推断一个视频的相邻两帧I、J在某局部窗体w上是一样的。则在窗体w内有:I(x, y, t) = J(x', y', t+τ),亮度恒定的如果(如果1)即为了保证其等号成立不受亮度的影响,如果2是为了保证KLT可以找到点,如果3则为下面原因如果(即对于同一个窗体中。全部点的偏移量都相等): 在窗体w上,全部(x, y)都往一个方向移动了(dx, dy),从而得到(x', y'),即t时刻的(x, y)点在t+τ时刻为(x+dx, y+dy)。所以寻求匹配的问题可化为对下面的式子寻求最小值,或叫做最小化下面式子: 用积分来表示上述式子。以上式子可等效为: 这个式子的含义。即找到两副图像中,在W窗体中。I、J的差异,当中I以x-d/2为中心,J以x+d/2为中心,w/2为半径的一个矩形窗体间的差异,好吧。结合我们微积分的知识。函数ε(d)要取得最小值,这个极值点的导数一定为0,即 的值为0,由泰勒展开的性质: 能够得到: 于是。问题转化为: 当中: 从而,问题即为: => 即其等式可看作为: 当中。Z为一个2*2的矩阵,e为一个2*1的向量。 为了要使d可以得到解,则Z须要满足条件,即Z*Z'矩阵可逆。当中Z'为Z矩阵的转置(ZT),在普通情况下,角点具有这种特点。 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4643101.html,如需转载请自行联系原作者
(1)案例介绍 ——我们首先导入plist文件做项目,模拟的观看效果。 ——删除plist,更换一个新的plist,CMD+R模拟执行,或者找到该程序界面上显示最后一个数据。 (2)原因 是由于第一次模拟执行时,已经生成了一个“沙盒”。全部资源也都保存在这个沙盒中了(假设在用户手机中。相当于数据已经下载到用户手机里了)。 这个时候,我们虽然替换了。可是沙盒中得数据仍然是上一次的数据。 (3)解决思路:清除上一次留下的数据,然后又一次载入新的数据plist。(建议2步走) ——先在模拟器中删除应用 ——运行清除数据操作 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4753199.html,如需转载请自行联系原作者
我没有在自然语言处理完成。但基于Deep Learning 关注,自然知道一些Word2vec强大。 Word2vec 是google 在2013年提供的一款将词表征为实数值向量的高效工具。而Word2vec输出的词向量可用于做NLP 相关的工作。比方聚类、找同义词、词性分析等。Word2vec 大受欢迎的一个原因是其高效性。 Tomas Mikolov 在[1] 中指出一个优化的单机版本号一天能够训练上千亿词(汗! )。 关于词的概念。这里的词能够并不一定真的就是单词,全然能够是具有一定意义的单元块,比方国外音乐站点就用word2vec来训练用户的听歌记录。这里的单元块就是歌曲编号。假设用户对音乐类型的喜好是一致的,那么训练后就能找到与某个歌曲相似的歌曲,这样就能给用户进行推荐了。相信类似这种样例还有非常多。 (关于这点思考:词能够使一个标号或者理解为一个类的对象! ) 先上图: 个人感觉这个解说的非常具体~ 注意:1。 输入为一个窗体的待预測上下文 2. 输入层Wj 是维度为K的列向量,(syn0 编码?)如有 N个输入词。则输入大小为k*N 3. 隐层 Tk 是输入层Wj 的加权,隐层大小为N*k 4. 输出层的叶节点是语料里的词,如红楼梦分词后的独立词 5. 叶节点有唯一的编码。从根节点開始算第一层(二叉树构建算法 Huffman树) 理解非常浅显~ 以后持续更新~ 參考: [1]Distributed Representations of Words and Phrases and their Compositionality (经典论文) [2] Felven----再谈word2vec (Felven word2vec 系列非常实践) [3] Felven----关键词聚类 [4] Felven-----红楼梦人物关系 [5] word2vec傻瓜剖析 (个人认为还是先看看Felven的实验后。再看这个比較有感觉点!) [6] 有道的word2vec 解说 (非常具体。几个DL大牛的关系图非常有意思! ) [7] word2vec 代码解说,英文的! [8]深度学习Word2vec 笔记之算法具体解释! [9] word2vec 的Windows 编译的版本号 [10] word2vec使用指导 (zhoubl668的博客,有好几篇是介绍Word2vec的,值得推荐。) [11] Deep Learning in NLP (一)词向量和语言模型 (非常具体! ) 如转载,请标明转自:http://write.blog.csdn.net/postedit/41078835 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4645727.html,如需转载请自行联系原作者
编程练习答案第八章 8.1写输出字符串的函数,存在默认参数表示输出频率,莫感觉1.(原标题太扯了,的问题的细微变化的基础上,含义) //8.1编写一个输出字符串的函数。有一个默认參数表示输出次数,默觉得1.(原题太扯啦,题意基础上小修改) #include <iostream> using namespace std; void show (const char* str, int time=1) { unsigned n=(time>0)? time:-time; for (unsigned i = 0; i < n; ++i) cout << str << endl; cout << "-----------------" << endl; } int main () { const char* str = "hello word!"; show(str); show(str,0); show(str,1); show(str,-1); } 8.2CandyBar结构体有品牌,重量和热量3个成员,编写一个含有默认值的函数为成员赋值和一个显示内容函数 //8.2CandyBar结构体有品牌。重量和热量3个成员。编写一个含有默认值的函数为成员赋值和一个显示内容函数 //CandyBar& candbar, const char* strBrand = "Millennium Munch", double weight = 2.85, int calories = 350 #include <iostream> #include <string> using namespace std; struct CandyBar { string Brand; double weight; int calories; }; void input (CandyBar& candbar, const char* Brand = "Millennium Munch", double weight = 2.85, int calories = 350) { candbar.Brand = Brand; candbar.weight = weight; candbar.calories = calories; } void show (const CandyBar& candbar) { cout << candbar.Brand << '\t' << candbar.weight << '\t' << candbar.calories << endl; } int main () { CandyBar candbar1, candbar2; input(candbar1); show(candbar1); input(candbar2, "world", 2,3 ); show(candbar2); } 8.3编写一个函数。接受string引用。并把string内容变大写,之后利用循环測试 //8.3编写一个函数,接受string引用,并把string内容变大写,之后利用循环測试 #include <iostream> #include <cctype> using namespace std; string& upper (string& str) { for (char& e : str) e = (char)toupper(e); return (str); } int main () { while (true) { cout << "Enter a string (q to quit): "; string str; getline(cin, str); if (!cin || "q" == str || "Q" == str) break; cout << upper(str) << endl; } } 8.4按下面程序框架,完毕函数 //8.4按下面程序框架,完毕函数 #include <iostream> #include <cstring> using namespace std; struct stringy { char * str; int ct; }; void set (stringy& stry, const char* szTxt) { stry.ct = (int)strlen(szTxt); stry.str = new char [stry.ct + 1]; strcpy(stry.str, szTxt); } void show (const char* szTxt, unsigned times = 1) { for (unsigned i = 0; i < times; ++i) cout << szTxt << endl; } void show (const stringy& stry, unsigned times = 1) { for (unsigned i = 0; i < times; ++i) cout << stry.str << endl; } void destroy (stringy& stry) { delete [] stry.str; stry.str = NULL; } int main() { stringy beany; char testing[] = "Reality isn't what it used to be."; set(beany, testing); show(beany); show(beany, 2); destroy(beany); testing[0] = 'D'; testing[1] = 'u'; show(testing); show(testing, 3); show("Done!"); } 8.5利用一个模板函数max5()。返回给予的5个数的最大值(应用c++11的array) //8.5利用一个模板函数max5()。返回给予的5个数的最大值(应用c++11的array) #include <iostream> #include <array> using namespace std; template<typename T> const T& max5 (const array<T, 5>& arr) { unsigned max = 0; for (unsigned i = 0; i < 5; ++i) if (arr[i] > arr[max]) max = i; return (arr[max]); } int main () { array<int, 5> iarray = {32, 20, 99, 256, 9}; for (const auto& e : iarray) cout << e << ' '; cout << " max: " << max5(iarray) << endl; array<double,5> darray = {1.2,2.3,4.5,32.3,4.3}; for (const auto& e : darray) cout << e << ' '; cout << "max: " << max5(darray) << endl; } 8.6编写模板函数maxn(),參数为一个数组和元素数目。返回数组最大值,然后详细化一个字符串为元素的字符串,返回最长字符串 //8.6编写模板函数maxn(),參数为一个数组和元素数目,返回数组最大值, //然后详细化一个字符串为元素的字符串,返回最长字符串 #include <iostream> #include <cstring> using namespace std; template <typename T> const T& maxn (const T arr[], unsigned n) { unsigned max = 0; for (unsigned i = 0; i < n; ++i) if (arr[i] > arr[max]) max = i; return (arr[max]); } char* maxn ( char* arr[], unsigned n) { unsigned max = 0; for (unsigned i = 0; i < n; ++i) if (strlen(arr[i]) > strlen(arr[max])) max = i; return (arr[max]); } int main () { int iArray[] = {32, -1, 99, 0, 256, 9}; for (const auto& e : iArray) cout << e << ' '; cout << " ----max: " << maxn(iArray, sizeof(iArray)/sizeof(iArray[0])) << endl; double dArray[] = {-3.2, 221.22, 9.9, 0, 1}; for (const auto& e : dArray) cout << e << ' '; cout << " ----max: " << maxn(dArray, sizeof(dArray)/sizeof(dArray[0])) << endl; const char* szArray[] = {"aaaa","bbbbbb","cc","fffffffffff","kkkk"}; for (const auto& e : szArray) cout << '\"' << e << '\"' << ' '; cout << " ----max: " << '\"' << maxn(szArray, sizeof(szArray)/sizeof(szArray[0])) << '\"' << endl; } 8.7对程序清单8.14,使用两个SumArray()模板返回数组元素总和。 程序返回thing以及debt的总和 //8.7对程序清单8.14,使用两个SumArray()模板返回数组元素总和。程序返回thing以及debt的总和 #include <iostream> using namespace std; struct debts { char name[50]; double amount; }; template <typename T> double SumArray(T arr[], int n) { cout << "template A\n"; double sum = 0; for (int i = 0; i < n; i++) sum += arr[i]; return (sum); } template <typename T> double SumArray(T * arr[], int n) { cout << "template B\n"; double sum = 0; for (int i = 0; i < n; i++) sum += *arr[i]; return (sum); } int main() { int things[6] = {13, 31, 103, 301, 310, 130}; struct debts mr_E[3] = { {"Ima Wolfe", 2400.0},{"Ura Foxe", 1300.0},{"Iby Stout", 1800.0} }; double * pd[3]; for (int i = 0; i < 3; i++) pd[i] = &mr_E[i].amount; cout << "the total number of Mr. E's things: " << SumArray(things, 6) << endl; cout << "the sum of Mr. E's all debts: " << SumArray(pd, 3) << endl; } 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4646607.html,如需转载请自行联系原作者
这些天大厦10g DG Windows 2008 R2测试环境,主要明天去给客户端,再建一个生产资源库DG,其中一些发现的问题。特此记录下来 因为将要部署到生产环境。所以考虑在线搭建DG的方案,即不停库的情况下。而问题主要就是出在不停库时,用RAMN创建STANDBY的时候 通常在线搭建DG。主要是以下几个步骤: 1. 确保主库开启归档(生产库基本都是开启的),并开启force logging模式 SQL> select database_role,log_mode,force_logging from v$database; SQL> alter database force logging; --force_logging能够在线改动,而不像开启归档必须在mount状态改动 2. 主库在线改动spifle,alter system set .... scope=both;并创建pfile 首先要确保所需改动的參支持在线改动,能够查看视图v$parameter SQL> select distinct issys_modifiable from v$parameter; ISSYS_MODIFIABLE --------------------------- DEFERRED FALSE IMMEDIATE 说明: DFERRED:动态參数,改动后对当前活跃的session无效FALSE:静态參数。改动后需重新启动数据库 IMMEDIATE:动态參数。改动后马上对全部session生效 SQL> select name,issys_modifiable,value from v$parameter where name='xxxx'; xxxx为要改动的參数名 在须要改的几个參数中,仅仅有db_unique_name不支持在线改动 SQL> alter system set LOG_ARCHIVE_CONFIG='DG_CONFIG=(ora10gpd,ora10gst)' scope=both; SQL> alter system set LOG_ARCHIVE_DEST_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=ora10gpd' scope=both; SQL> alter system set LOG_ARCHIVE_DEST_2='SERVICE=ora10gst LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=ora10gst' scope=both; SQL> alter system set LOG_ARCHIVE_DEST_STATE_1=ENABLE scope=both; SQL> alter system set LOG_ARCHIVE_DEST_STATE_2=ENABLE scope=both; SQL> alter system set FAL_SERVER=ora10gst scope=both; SQL> alter system set FAL_CLIENT=ora10gpd scope=both; SQL> alter system set STANDBY_FILE_MANAGEMENT='AUTO' scope=both; 所以假设生产库想不停库搭建DG的话。那么就要使用原有的db_unique_name。通常和db_name是同一个名字 改动完spfile以后,用它创建一个pfile,供备库使用。create pfile from spfile; 3. 主库创建standby redo logfile,alter database add standby logfile group # datafile ('xxxx') size 50M; xxxx指定路径和文件名称 4.创建listener.ora和tnsnames.ora,把生成的文件拷贝到备库对应位置并改动 5. 主库创建备库控制文件、数据文件、归档日志文件备份集 rman target / RMAN> backup full database format 'c:\backup\full_%d_%I_%U' include current controlfile for standby plus archivelogformat 'c:\backup\arc_%d_%I_%U'; 或者: run { allocate channel d1 type disk; backup format 'C:\backup\df_%d_%I_%U' database; sql 'alter system archive log current'; backup format 'C:\backup\al_%d_%I_%U' archivelog all; backup current controlfile for standby format 'C:\backup\cf_%d_%I_%U'; release channel d1; } 6. 把pfile參数文件,password文件。复制到备库%ORACLE_HOME%\database\下 7. 创建备库实例(ora10g)及相关文件夹 C:\Users\Administrator>oradim -new -sid ora10gC:\oracle\product\10.2.0\fast_recovery_area C:\oracle\product\10.2.0\admin\ora10g\adump C:\oracle\product\10.2.0\admin\ora10g\bdump C:\oracle\product\10.2.0\admin\ora10g\cdump C:\oracle\product\10.2.0\admin\ora10g\dpdump C:\oracle\product\10.2.0\admin\ora10g\pfileC:\oracle\product\10.2.0\admin\ora10g\udump 红色部分必须写,由于已经在pfile中指定了详细的路径 8. 把主库备份集复制到备库并进行恢复,主要是3个步骤 ① nomount状态下恢复备库控制文件。 RMAN> restore controlfile from 'C:\backup\xxxx'; xxxx为含有备库控制文件的备份片名称 ② mount状态下恢复数据库,RMAN> restore database; ③ 恢复备库归档日志文件,RMAN> restore archivelog all; 或在做完第①步后,在主库open,备库nomount状态下连接到RMAN运行: rman target sys/oracle@ora10gpd auxiliary / run { allocate channel C1 device type disk; allocate auxiliary channel C2 device type disk; duplicate target database for standby nofilenamecheck; release channel C1; release channel C2; } 9. 备库创建standby redo logfile,大小位置需和主库一致 10. 完毕恢复并启动mpr0进程,即启用redo apply,alter database recover managed standby database disconnect from session; 假设一切顺利,那么此时备库就会開始逐一应用主库传过来的归档日志文件 但,事实没有这么简单,在我实际做下来的结果是,主库的redo log日志文件无法传递到备库,备库的alert log日志会报 ORA-19527 和 ORA-00312 错误,例如以下: ORA-19527: 必须重命名物理备用重做日志 ORA-00312: 联机日志 1 线程 1: 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO01.LOG' 这是由于10g以后,oracle为了加快swtichover的速度,在can become a primary之前就去clear the online logfiles了,而假设没有设置log_file_name_convert,这个时候oracle可能就不能识别哪怕是冷备copy过来的路径文件名称都一模一样的redo logfile。解决方式就是在主备库參数中加入log_file_name_convert,原来没实用这个參数,是由于主备库的log日志文件路径都一样(由于用了同一个数据库实例名ora10g)。就以为能够不设置了 引用一段官方的解释: CauseThis is in fact an enhancement to the Dataguard product in 10gR2 ..The goal here is to improve speed of switchover. Before this a switchover would require to clear the online logfiles before we can become a primary. In this release we attempt to clear the online logfiles when starting Managed Recovery.If the files exist then they will be cleared, but if they do not exist we report the error and the MRP does not fail.As an extra enhancementif the online redo logs do exist you must specify the log_file_name_convert parameter even if there is no difference in the name. This has been implemented to reduce the chances that the primary online redo logs are cleared when MRP starts. It is the equivalent of asking - Are you sure you want the logs to be called this....If the log_file_name_convert parameter is not set then the ORA-19527 is reported and the log file is not cleared at this time..SolutionSolution to stop both of these errors is to create the online redo logs andensure log_file_name_convert is set. SQL> alter system set log_file_name_convert='C:\oracle\product\10.2.0\oradata\ora10g','C:\oracle\product\10.2.0\oradata\ora10g' scope=spfile; log_file_name_convert 这个參数非在线可改动。必须重新启动后才干生效: 这就有点尴尬,生产库就必须重新启动一下。也就是说必须停一下库,哪怕仅仅是几分钟,只是当设置完毕,重新启动standby,apply日志以后。看到alert log日志中果然能够看到clear online logfiles了,问题得到解决 备库alert log日志会提示下面内容: Thu Jul 17 10:49:21 2014alter database recover managed standby database disconnect from sessionMRP0 started with pid=16, OS id=2548Managed Standby Recovery not using Real Time Apply parallel recovery started with 2 processesThu Jul 17 10:49:26 2014Waiting for all non-current ORLs to be archived...Thu Jul 17 10:49:26 2014Errors in file c:\oracle\product\10.2.0\admin\ora10g\bdump\ora10g_mrp0_2548.trc:ORA-00313: 无法打开日志组 1 (用于线程 1) 的成员ORA-00312: 联机日志 1 线程 1: 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO01.LOG'ORA-27041: 无法打开文件OSD-04002: 无法打开文件O/S-Error: (OS 2) 系统找不到指定的文件。Thu Jul 17 10:49:26 2014Errors in file c:\oracle\product\10.2.0\admin\ora10g\bdump\ora10g_mrp0_2548.trc:ORA-00313: 无法打开日志组 1 (用于线程 1) 的成员ORA-00312: 联机日志 1 线程 1: 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO01.LOG'ORA-27041: 无法打开文件OSD-04002: 无法打开文件O/S-Error: (OS 2) 系统找不到指定的文件。Clearing online redo logfile 1 C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO01.LOG--開始清除REDO01.LOG Clearing online log 1 of thread 1 sequence number 64Thu Jul 17 10:49:26 2014Errors in file c:\oracle\product\10.2.0\admin\ora10g\bdump\ora10g_mrp0_2548.trc:ORA-00313: 无法打开日志组 1 (用于线程 1) 的成员ORA-00312: 联机日志 1 线程 1: 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO01.LOG'ORA-27041: 无法打开文件OSD-04002: 无法打开文件O/S-Error: (OS 2) 系统找不到指定的文件。Thu Jul 17 10:49:27 2014Completed: alter database recover managed standby database disconnect from sessionThu Jul 17 10:49:27 2014Clearing online redo logfile 1 complete --清除online redo logfile 'REDO01.LOG' 完成,此时会在oradata文件夹生成一个REDO01.LOG文件Thu Jul 17 10:49:27 2014Errors in file c:\oracle\product\10.2.0\admin\ora10g\bdump\ora10g_mrp0_2548.trc:ORA-00313: 无法打开日志组 2 (用于线程 1) 的成员ORA-00312: 联机日志 2 线程 1: 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO02.LOG'ORA-27041: 无法打开文件OSD-04002: 无法打开文件O/S-Error: (OS 2) 系统找不到指定的文件。Thu Jul 17 10:49:27 2014Errors in file c:\oracle\product\10.2.0\admin\ora10g\bdump\ora10g_mrp0_2548.trc:ORA-00313: 无法打开日志组 2 (用于线程 1) 的成员ORA-00312: 联机日志 2 线程 1: 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO02.LOG'ORA-27041: 无法打开文件OSD-04002: 无法打开文件O/S-Error: (OS 2) 系统找不到指定的文件。Clearing online redo logfile 2 C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO02.LOG --開始清除REDO02.LOG Clearing online log 2 of thread 1 sequence number 65Thu Jul 17 10:49:27 2014Errors in file c:\oracle\product\10.2.0\admin\ora10g\bdump\ora10g_mrp0_2548.trc:ORA-00313: 无法打开日志组 2 (用于线程 1) 的成员ORA-00312: 联机日志 2 线程 1: 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO02.LOG'ORA-27041: 无法打开文件OSD-04002: 无法打开文件O/S-Error: (OS 2) 系统找不到指定的文件。 Clearing online redo logfile 2 complete --清除online redo logfile 'REDO02.LOG' 完成。此时会在oradata文件夹生成一个REDO02.LOG文件 Thu Jul 17 10:49:28 2014 Errors in file c:\oracle\product\10.2.0\admin\ora10g\bdump\ora10g_mrp0_2548.trc: ORA-00313: 无法打开日志组 3 (用于线程 1) 的成员 ORA-00312: 联机日志 3 线程 1: 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO03.LOG' ORA-27041: 无法打开文件 OSD-04002: 无法打开文件 O/S-Error: (OS 2) 系统找不到指定的文件。 Thu Jul 17 10:49:28 2014 Errors in file c:\oracle\product\10.2.0\admin\ora10g\bdump\ora10g_mrp0_2548.trc: ORA-00313: 无法打开日志组 3 (用于线程 1) 的成员 ORA-00312: 联机日志 3 线程 1: 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO03.LOG' ORA-27041: 无法打开文件 OSD-04002: 无法打开文件 O/S-Error: (OS 2) 系统找不到指定的文件。Clearing online redo logfile 3 C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO03.LOG--開始清除REDO03.LOG Clearing online log 3 of thread 1 sequence number 66 Thu Jul 17 10:49:28 2014 Errors in file c:\oracle\product\10.2.0\admin\ora10g\bdump\ora10g_mrp0_2548.trc: ORA-00313: 无法打开日志组 3 (用于线程 1) 的成员 ORA-00312: 联机日志 3 线程 1: 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\REDO03.LOG' ORA-27041: 无法打开文件 OSD-04002: 无法打开文件 O/S-Error: (OS 2) 系统找不到指定的文件。 Clearing online redo logfile 3 complete --清除online redo logfile 'REDO03.LOG' 完成,此时会在oradata文件夹生成一个REDO03.LOG文件 Media Recovery Waiting for thread 1 sequence 66 Thu Jul 17 10:51:25 2014 注意看备库告警日志中提示的開始清除redo logfile的时间和下图window文件夹中这几个文件创建的时间,就是在清除在线日志文件的你那一刻,在备库生成了对应的文件。 也就是说,当启用redo apply 的时候,备库先会提示无法读取參数中配置的在线日志文件。那后就会去清除该日志,并自己主动生成该文件。就是这么个过程 当然,alert log还会继续提示也不存在sandby redo logfile,例如以下: Media Recovery Waiting for thread 1 sequence 66 Thu Jul 17 10:51:25 2014 Redo Shipping Client Connected as PUBLIC -- Connected User is Valid RFS[2]: Assigned to RFS process 2100 RFS[2]: Identified database type as 'physical standby' Primary database is in MAXIMUM PERFORMANCE mode Primary database is in MAXIMUM PERFORMANCE mode Thu Jul 17 10:51:25 2014 Errors in file c:\oracle\product\10.2.0\admin\ora10g\udump\ora10g_rfs_2100.trc: ORA-00313: 无法打开日志组 4 (用于线程 1) 的成员ORA-00312: 联机日志 4 线程 1: 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\ORA10G\STDREDO04.LOG' ORA-27041: 无法打开文件 OSD-04002: 无法打开文件 O/S-Error: (OS 2) 系统找不到指定的文件。 这个standby redo logfile和online redo logfile又有些不同。假设碰到无法打开。数据库不会去清除并自己主动创建,而是须要我们手动去创建 但能够从v$log视图中发现,该文件是已经存在于备库控制文件里的(由于主库在创建备库控制文件备份的时候。就已经创建好了嘛),那就无法用语句再创建一次。会提示该文件已存在(而实际上物理并不存在),能够先drop掉。再又一次创建。假设加入或删除主库online redo logfile。那么须要先把standby_file_management參数的值改为manual。之后再改回auto 假设standby redo logfile配置有问题,那么当切换保护模式到maximize availability或maximize protection时。会报: ORA-16072: a minimum of one standby database destination is required 此时即使已经配置了LOG_ARCHIVE_DEST_2中已经配置了LGWR SYNC AFFIRM。open数据库时会报: ORA-03113: end-of-file on communication channel 这是由于。最高可用和最大保护这两种模式必须使用LGWR进程来写到standby redo logfile,假设这个条件不能保证,那么就无法打开数据库,强制断开与数据库的链接,以提供对数据库的最大范围的安全保护 等这些日志都顺利在备库建立后,备库就能够開始同步应用主库归档日志了: Thu Jul 17 10:51:25 2014 RFS[1]: Archived Log: 'C:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\ORA10GST\ARCHIVELOG\2014_07_17\O1_MF_1_66_9WGGKFWB_.ARC' Thu Jul 17 10:51:30 2014 Media Recovery Log C:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\ORA10GST\ARCHIVELOG\2014_07_17\O1_MF_1_66_9WGGKFWB_.ARC Thu Jul 17 10:51:50 2014 RFS[2]: Archived Log: 'C:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\ORA10GST\ARCHIVELOG\2014_07_17\O1_MF_1_67_9WGGKFVT_.ARC' Primary database is in MAXIMUM PERFORMANCE mode Thu Jul 17 10:52:16 2014 Media Recovery Log C:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\ORA10GST\ARCHIVELOG\2014_07_17\O1_MF_1_67_9WGGKFVT_.ARC Media Recovery Waiting for thread 1 sequence 68 (in transit) Thu Jul 17 10:57:20 2014 RFS[2]: Archived Log: 'C:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\ORA10GST\ARCHIVELOG\2014_07_17\O1_MF_1_68_9WGGL635_.ARC' Primary database is in MAXIMUM PERFORMANCE mode Thu Jul 17 10:57:22 2014 Media Recovery Log C:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\ORA10GST\ARCHIVELOG\2014_07_17\O1_MF_1_68_9WGGL635_.ARC Media Recovery Waiting for thread 1 sequence 69 (in transit) Thu Jul 17 10:57:35 2014 RFS[2]: Archived Log: 'C:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\ORA10GST\ARCHIVELOG\2014_07_17\O1_MF_1_69_9WGGWJCK_.ARC' Primary database is in MAXIMUM PERFORMANCE mode Thu Jul 17 10:57:38 2014 Media Recovery Log C:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\ORA10GST\ARCHIVELOG\2014_07_17\O1_MF_1_69_9WGGWJCK_.ARC Media Recovery Waiting for thread 1 sequence 70 (in transit) Thu Jul 17 10:57:51 2014 RFS[2]: Archived Log: 'C:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\ORA10GST\ARCHIVELOG\2014_07_17\O1_MF_1_70_9WGGWZ9C_.ARC' Primary database is in MAXIMUM PERFORMANCE mode Thu Jul 17 10:57:53 2014 Media Recovery Log C:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\ORA10GST\ARCHIVELOG\2014_07_17\O1_MF_1_70_9WGGWZ9C_.ARC Media Recovery Waiting for thread 1 sequence 71 (in transit) 能够看到。此时 sequence 70已经在备库上应用。在等待主库传sequence 71日志 版权声明:本文博客原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4757076.html,如需转载请自行联系原作者
单例模式: 为什么使用单例,单例模式的用途是什么?以下我们举一个样例来诠释一下 举个大家都熟知的样例——Windows任务管理器,如图,我们能够做一个这种尝试,在Windows的“任务栏”的右键弹出菜单上多次点击“启动任务管理器”。看是否能打开多个任务管理器窗体?通常情况下,不管我们启动任务管理多少次。Windows系统始终仅仅能弹出一个任务管理器窗体。也就是说在一个Windows系统中。任务管理器存在唯一性。为什么要这样设计呢?我们能够从下面两个方面来分析:其一,假设能弹出多个窗体,且这些窗体的内容全然一致,所有是反复对象,这势必会浪费系统资源。任务管理器须要获取系统执行时的诸多信息。这些信息的获取须要消耗一定的系统资源。包含CPU资源及内存资源等,浪费是可耻的。并且根本没有必要显示多个内容全然同样的窗体;其二,假设弹出的多个窗体内容不一致,问题就更加严重了,这意味着在某一瞬间系统资源使用情况和进程、服务等信息存在多个状态。比如任务管理器窗体A显示“CPU使用率”为10%,窗体B显示“CPU使用率”为15%,究竟哪个才是真实的呢?这纯属“调戏”用户,给用户带来误解,更不可取。由此可见,确保Windows任务管理器在系统中有且仅有一个很重要。 回到实际开发中,我们也常常遇到类似的情况,为了节约系统资源,有时须要确保系统中某个类仅仅有唯一一个实例,当这个唯一实例创建成功之后,我们无法再创建一个同类型的其它对象,全部的操作都仅仅能基于这个唯一实例。为了确保对象的唯一性,我们能够通过单例模式来实现。这就是单例模式的动机所在。 以下单例模式的几种写法: 在这里创建了一个Person类继承与NSObject .h文件 // Person.h // 单例模式 Singleton // Copyright (c) 2014年 summer2014mht@sina.com. All rights reserved. #import<Foundation/Foundation.h> @interface Person :NSObject //单例:一个类仅仅有一个实例, 在外部创建对象时,不能用alloc.(仅仅要alloc.就会在堆区开辟空间,就意味着有多个对象). //所以我们要提供一个创建对象的方法.并且是一个+号方法 //default, standard, main, shared开头的都是单例 + (Person *)sharedPerson; @end .m文件 // Person.m // 单例模式 Singleton // Copyright (c) 2014年 summer2014mht@sina.com. All rights reserved. #import"Person.h" @implementation Person /* //写法一 + (Person *)sharedPerson { //声明为static ,保证该变量在程序执行期间空间都不会回收.并且保证仅仅初始化一次 //单例的空间在程序执行期间都不会回收,所以要慎重使用单例,否则会造成内存堆积 static Person *person = nil; @synchronized(self){ if (person == nil) { person = [[Person alloc] init]; } } return person; } */ //写法二(推荐使用) + (Person *)sharedPerson { static Person *person = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ person = [[Personalloc] init]; }); return person; } @end 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4757322.html,如需转载请自行联系原作者
做web发展还是新手我,为了之前获得Gridview中间值,它是通过服务器端控件通过第一Gridview将数据保存到服务器,当一个服务器,然后绑定的隐藏字段,在通过的js阅读隐藏字段值,如今,这种方法感觉很愚蠢;虽然获得的数据easy但是,什么是穿越Gridview,可是考虑的性能,我还是想用js来读取。 如今可以得到我想要的数据了,为了方便以后和我一样的新手。如今简单记下,希望可以抛砖引玉,有待找到更好的解决的方法。 假设您有更好的想法请联系qq:643166601,我会及时记录更新。 1.准备数据库,我的数据库名字叫做LionDB,以下有一个表叫做User,例如以下: User表的定义,例如以下: User表中的数据。例如以下: 2.页面上放两个控件 a) GridView,绑定数据源,加入checkbox列。其它列自己主动绑定 b) Input(Button) 。加入事件(为以后得详细哪一行或那几行数据做准备) 之后,页面效果例如以下: 4.js关键代码 <script language="javascript" type="text/javascript"> // <![CDATA[ function btnChecked_onclick() { var tb = document.getElementById("<%=GridView1.ClientID %>"); var sLine = ""; if (tb) { var rows = tb.rows; for (var i = 1; i < rows.length; i++) { var cbx = rows[i].cells[0].childNodes[0].nextElementSibling; if (cbx.type == 'checkbox' && cbx.checked == true) { var sUserId = rows[i].cells[1].innerHTML; var sUserName = rows[i].cells[2].innerHTML; sLine += "userId:" + sUserId + "userName:" + sUserName + " "; } } alert(sLine); } } // ]]> </script> 5.执行效果 6.得到想要的结果 源代码包: 点击打开链接 版权声明:本文博主原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4760026.html,如需转载请自行联系原作者
oracle从备份集中抓出归档日志方法 在大连医院遇到这个问题,数据库为归档状态,但归档完成后rman通过crontab自己主动备走归档日志并删除存在系统上的归档日志文件。在RealSync程序停止一段时间后,须要应用归档日志来解决日志丢失问题。 问题是: 数据库中的控制文件里关于备份的元数据已经丢失,但备份集存在。这时候我们開始调用oracle的一个内部非公开的函数包:dbms_backup_restore 来从备份集中抽取归档日志到指定的系统文件夹。以满足我们的需求。 语句例如以下: declare devtype varchar2(256); done boolean; begin devtype:=sys.dbms_backup_restore.deviceAllocate(type=>'',ident=>'t2'); sys.dbms_backup_restore.restoreSetArchivedLog(destination=>'/archivelog02'); sys.dbms_backup_restore.restoreArchivedLog(thread=>2,sequence=>51500); sys.dbms_backup_restore.restoreBackupPiece(done=>done,handle=>'/backup/zlhis/rman/AL_ZLHIS_20141030_862336902_23768_1',params=>null); sys.dbms_backup_restore.deviceDeallocate; end; 注意我们改动的地方是:destination=>'/archivelog02指定恢复出来归档日志的存放系统文件夹位置。thread表示rac的thread号,sequence为须要恢复的那个归档日志序列号。handle表示备份集的绝对路径。 改动完成后。直接在sqlplus命令窗口中运行就可以了。 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4653531.html,如需转载请自行联系原作者
Tutor Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 1981 Accepted Submission(s): 552Problem Description Lilin was a student of Tonghua Normal University. She is studying at University of Chicago now. Besides studying, she worked as a tutor teaching Chinese to Americans. So, she can earn some money per month. At the end of the year, Lilin wants to know his average monthly money to decide whether continue or not. But she is not good at calculation, so she ask for your help. Please write a program to help Lilin to calculate the average money her earned per month. Input The first line contain one integer T, means the total number of cases. Every case will be twelve lines. Each line will contain the money she earned per month. Each number will be positive and displayed to the penny. No dollar sign will be included. Output The output will be a single number, the average of money she earned for the twelve months. It will be rounded to the nearest penny, preceded immediately by a dollar sign without tail zero. There will be no other spaces or characters in the output. Sample Input 2 100.00 489.12 12454.12 1234.10 823.05 109.20 5.27 1542.25 839.18 83.99 1295.01 1.75 100.00 100.00 100.00 100.00 100.00 100.00 100.00 100.00 100.00 100.00 100.00 100.00 Sample Output $1581.42 $100 精度问题 题目要求精确到分,即小数点后2位,故应该看小数点第三位的值,然后四舍五入。 把平均值+上0.005,则能够使第三位满5进一。 #include"stdio.h" #define N 12 int main() { int n,i; double a,s; scanf("%d",&n); while(n--) { s=0; for(i=0;i<N;i++) { scanf("%lf",&a); s+=a; } s/=12; int m=(s+0.005)*100; //小数点后第三位四舍五入 if(m%100==0) printf("$%.0f\n",s); else if(m%10==0) printf("$%.1f\n",s); else printf("$%.2f\n",s); } return 0; } 版权声明:本文博客原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4679271.html,如需转载请自行联系原作者
Best Time to Buy and Sell Stock Total Accepted: 14044 Total Submissions: 45572My Submissions Say you have an array for which the ith element is the price of a given stock on day i. If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit. Have you been asked this question in an interview? 解题思路: 贪心法: 分别找到价格最低和最高的一天。低进高出,注意最低的一天要在最高的一天之前。 把原始价格序列变成差分序列,也就是对于元素j,在该点卖出的价格等于prices[j] 减去它前面元素中最小的值。这样遍历一遍数组就OK了。 本题也能够做是最大m 子段和,m = 1 。 动态规划法: 首先用prices[i] - prices[i-1] 将数组转化为 差分序列,那么问题就转化为在这个差分序列中找出一个最大( maximum )的连续的子序列和的问题,能够用 LeetCode--Maximum Subarray 最大连续子序列和 (动态规划)类似方法求解。 备注:若採用暴利破解法,时间复杂度是O(n^2)。会超出时间限制。 程序源码: 贪心算法Java代码 public int maxProfit(int[] prices) { if(prices.length ==0) return 0; int i=0; int profit=0; int begMin= prices[0]; for(i=1; i<prices.length; ++i){ profit=Math.max(profit, prices[i]-begMin); begMin=Math.min(begMin, prices[i]); } return profit; } 动态规划:java代码 public int maxProfit(int[] prices) { int profit=0; int temp=0; for(int i=1; i<prices.length; ++i){ int diff=prices[i] - prices[i-1]; temp=Math.max(temp+diff, diff); profit=Math.max(profit, temp); } return profit; } 暴利破解法: /** * 暴利枚举法,超出时间限制 * @param prices * @return */ public static int maxProfit2(int[] prices) { int profit= 0; for( int i=0; i<prices.length-1; ++i){ for (int j=i+1; j<prices.length; ++j){ profit = Math.max(prices[j]-prices[i], profit); } } return profit; } 附录: 相关题目: LeetCode -- Best Time to Buy and Sell Stock II (贪心策略,差分序列) LeetCode--Best Time to Buy and Sell Stock III (动态规划) 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5047737.html,如需转载请自行联系原作者
通过sql case when对商品表自己定义属性进行查询。实现行专列效果。 declare @sql varchar(8000) set @sql='select StyleNo' select @sql=@sql+','+[A_GoodsAttr].AttrName+'=isnull(max(case AttrName when '''+[A_GoodsAttr].AttrName+''' then AttrValue end),0)' from A_GoodsAttr order by AttrId set @sql=@sql+' from A_ProAttrList where 1=1 and StyleNo=''100010'' group by StyleNo order by StyleNo' print @sql exec(@sql) 1、所有商品自己定义属性 2、单货号自己定义属性 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5058905.html,如需转载请自行联系原作者
(原版的:http://www.libgdx.cn/topic/46/4-4-libgdx%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%E6%9F%A5%E8%AF%A2%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83%E7%9B%B8%E5%85%B3%E5%B1%9E%E6%80%A7) Application接口提供了多种方法查询执行环境的属性。 获取当前应用类型 有时候须要依据特定平台进行特别的操作。Application.getType()用来返回当前正在执行的平台,示比例如以下: switch (Gdx.app.getType()) { case Android: // android specific code break; case Desktop: // desktop specific code break; case WebGl: // HTML5 specific code break; default: // Other platforms specific code } 在Android中,还能够查询当前Android的版本号: int androidVersion = Gdx.app.getVersion(); 这将返回当前使用的SDK版本号。比方3相应Android1.5。 (www.libgdx.cn版权所有所有。如需转载。注明出处) 版权声明:本文博客原创文章。博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4681095.html,如需转载请自行联系原作者
标题效果:给定一列数X(i+1)=(a*Xi+b)%p 最低要求i>0。所以Xi=t 0.0 这个问题可以1A那很棒 首先讨论特殊情况 如果X1=t ans=1 如果a=0 ans=b==t? 2:-1 若a=1 X1+b*(ans-1)==t (%p) 扩展欧几里得 令 temp=b/(a-1) 则有 (X(i+1)+temp)=a*(Xi+temp) Xans=(X1+temp)*a^(ans-1)-temp 当中Xans%p=t 则有 (X1+temp)*a^(ans-1)-temp == t (%p) 两側同乘a-1得 (a*X1-X1+b)*a^(ans-1) == (a-1)*t+b (%p) 令 Y=a*X1-X1+b Z=a*t-t+b Y*a^(ans-1) == Z(%p) 将Y和p约分 若Z%gcd(Y,p)!=0 return -1 令 A=a B=Z*Y^-1 C=p x=ans-1 A^x==B(%C) 然后就是EXBSGS的模板了0.0 这个模板我再也不想打第二遍了0.0 代码没法看了,诸位理解算法思想就好了0.0 #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 1001001 using namespace std; typedef long long ll; typedef pair<ll,ll> abcd; ll X,Y,Z,a,b,c,p,t,A,B,C,D; ll hash_table[M],val[M],tim[M],tot; int Hash(ll x) { int pos=x%M; while(1) { if(tim[pos]!=tot) tim[pos]=tot,hash_table[pos]=-1,val[pos]=0x3f3f3f3f; if(hash_table[pos]==-1||hash_table[pos]==x) return hash_table[pos]=x,pos; else ++pos,pos%=M; } } int Get_Hash(ll x) { int pos=x%M; while(1) { if(tim[pos]!=tot) tim[pos]=tot,hash_table[pos]=-1; if(hash_table[pos]==-1) return -1; if(hash_table[pos]==x) return pos; else ++pos,pos%=M; } } ll GCD(ll x,ll y) { return y?GCD(y,x%y):x; } abcd EXGCD(ll x,ll y) { if(!y) return abcd(1,0); abcd temp=EXGCD(y,x%y); return abcd(temp.second,temp.first-x/y*temp.second); } ll Inverse(ll x) { ll temp=EXGCD(x,C).first; return (temp%C+C)%C; } ll Extended_Big_Step_Giant_Step() { ll i,m,cnt=0,temp,base=1; int pos; if(B>=C) return -1; for(i=0,temp=1%C;i<=50;i++,temp*=A,temp%=C) if(temp==B) return i; D=1; while(temp=GCD(A,C),temp!=1) { if(B%temp) return -1; ++cnt; B/=temp; C/=temp; D*=A/temp; D%=C; } B*=Inverse(D);B%=C; m=(ll)ceil(sqrt(C)+1e-5); ++tot; for(i=0,temp=1%C;i<m;i++,temp*=A,temp%=C) pos=Hash(temp),val[pos]=min(val[pos],i); for(i=1,base=1%C;i<=m;i++,base*=A,base%=C); for(i=0,D=1%C;i<m;i++,D*=base,D%=C) { temp=EXGCD(D,C).first*B; temp=(temp%C+C)%C; pos=Get_Hash(temp); if(~pos) return i*m+val[pos]+cnt; } return -1; } ll Deal() { ll temp; cin>>p>>a>>b>>X>>t; if(X==t) return 1; if(!a) return b==t? 2:-1; if(a==1) { t+=p-X;t%=p; //b*(ans-1)==t (%p) temp=GCD(b,p); if(t%temp) return -1; b/=temp;t/=temp;p/=temp; temp=(EXGCD(b,p).first*t%p+p)%p; return temp+1; } Y=(a*X-X+b)%p; Z=(a*t-t+b)%p; temp=GCD(Y,p); if(Z%temp) return -1; Y/=temp;Z/=temp;p/=temp; C=p; B=Z*Inverse(Y)%p; A=a; temp=Extended_Big_Step_Giant_Step(); if(temp==-1) return -1; return temp+1; } int main() { int T; for(cin>>T;T;T--) cout<<Deal()<<endl; } 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4681224.html,如需转载请自行联系原作者
称号 Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. 方法 有序链表。合并成一个有序链表。 public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if (l1 == null) { return l2; } if (l2 == null) { return l1; } ListNode head = null; ListNode end = null; ListNode first = l1; ListNode second = l2; while (first != null && second != null) { int temp1 = first.val; int temp2 = second.val; if (temp1 <= temp2) { if (head == null) { head = first; end = head; } else { end.next = first; end = first; } first = first.next; } else { if (head == null) { head = second; end = head; } else { end.next = second; end = second; } second = second.next; } } if (first != null) { end.next = first; } if (second != null) { end.next = second; } return head; } 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4681824.html,如需转载请自行联系原作者
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! Android L: Google已经确认Android L就是Android Lollipop(5.0)。 前几天发现Android5.0正式版的sdk已经能够下载了。并且首次搭载Android L系统的Nexus 6和 Nexus 9也即将上市。 所以是时候開始学习Android L了。 关于Android L怎样配置模拟器和创建项目,假设大家有兴趣的话能够看看我之前的一篇文章: Android L——模拟器配置及创建项目 Material Design: Material Design是Google推出的一个全新的设计语言,它的特点就是拟物扁平化。 Material Design包括了非常多内容,我大致把它分为四部分: 主题和布局——ANDROID L——Material Design具体解释(主题和布局) 视图和阴影——ANDROID L——Material Design具体解释(视图和阴影) UI控件——ANDROID L——Material Design具体解释(UI控件) 动画——ANDROID L——Material Design具体解释(动画篇) 今天就先来说说第三部分——Material新增的UI控件 UI控件 在Android L中新增了两个控件各自是RecyclerView,CardView: RecyclerView: RecyclerView是ListView的升级版,它提供了更好的性能并且更easy使用。 RecyclerView这个控件是一个能够装载大量的视图集合,而且能够很效率的进行回收和滚动。当你list中的元素常常动态改变时能够使用RecyclerView控件。 RecyclerView很easy使用,它提供了例如以下两个功能: 为每一个条目位置提供了layout管理器(RecyclerView.setLayoutManager) 为每一个条目设置了操作动画(RecyclerView.setItemAnimator) 以下的样例介绍了怎样定义和使用一个RecyclerView: 1.在布局文件里加入一个RecyclerView <!-- A RecyclerView with some commonly used attributes --> <android.support.v7.widget.RecyclerView android:id="@+id/my_recycler_view" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="match_parent"/> 2.初始化RecyclerView參数。设置layoutManager和adapter public class MyActivity extends Activity { private RecyclerView mRecyclerView; private RecyclerView.Adapter mAdapter; private RecyclerView.LayoutManager mLayoutManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_activity); mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); // improve performance if you know that changes in content // do not change the size of the RecyclerView mRecyclerView.setHasFixedSize(true); // use a linear layout manager mLayoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mLayoutManager); // specify an adapter (see also next example) mAdapter = new MyAdapter(myDataset); mRecyclerView.setAdapter(mAdapter); } ... } 3.创建一个adapter public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { private String[] mDataset; // Provide a reference to the type of views that you are using // (custom viewholder) public static class ViewHolder extends RecyclerView.ViewHolder { public TextView mTextView; public ViewHolder(TextView v) { super(v); mTextView = v; } } // Provide a suitable constructor (depends on the kind of dataset) public MyAdapter(String[] myDataset) { mDataset = myDataset; } // Create new views (invoked by the layout manager) @Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // create a new view View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.my_text_view, parent, false); // set the view's size, margins, paddings and layout parameters ... ViewHolder vh = new ViewHolder(v); return vh; } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element holder.mTextView.setText(mDataset[position]); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return mDataset.length; } } CardView: CardView继承自FrameLayout。同意你在card视图中显示信息. CardView也能够设置阴影和圆角。(事实上如今非常多应用都自己定义了Card视图,Google这回将card视图作为基本控件,能够拿来直接使用了) Layout中为CardView设置圆角使用card_view:cardCornerRadius属性 代码中为CardView设置圆角使用CardView.setRadius方法 为CardView设置背景颜色使用card_view:cardBackgroundColor属性 在布局中包括一个CardView,例如以下: <!-- A CardView that contains a TextView --> <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/card_view" android:layout_gravity="center" android:layout_width="200dp" android:layout_height="200dp" card_view:cardCornerRadius="4dp"> <TextView android:id="@+id/info_text" android:layout_width="match_parent" android:layout_height="match_parent" /> </android.support.v7.widget.CardView> 兼容性: RecyclerView,CardView都包括在Android L Developer Preview Support Library中。所以他们能够在之前的版本号中使用,仅仅会有一些限制。 总结: 我将Material Design分为例如以下四部分: 主题和布局——ANDROID L——Material Design具体解释(主题和布局) 视图和阴影——ANDROID L——Material Design具体解释(视图和阴影) UI控件——ANDROID L——Material Design具体解释(UI控件) 动画——ANDROID L——Material Design具体解释(动画篇) 本文所介绍的两个控件(RecyclerView,CardView)很重要,由于在以后Android L的开发中会经经常使用到。 这篇文章介绍的内容都是从官方文档翻译过来的,大家看着可能有点迷糊。只是没关系。过几天我会更新一个介绍RecyclerView,CardView在Android Studio和Eclipse中是怎样导包。和两个控件结合使用的小Demo。 Android L——RecyclerView,CardView导入和使用(Demo) Material Desgin的介绍仅仅剩下动画部分了。我会尽快更新,敬请期待。。。 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4681969.html,如需转载请自行联系原作者