测试环境:
虚拟机: VMWARE WorkStation 8.0.4
OS: CentOS 6.3
OS 镜像:CentOS-6.3-i386-bin-DVD1.iso
启动虚拟机
挂载CentOS 6.3镜像 如下图:注意一定要
看一下是否挂载成功
[root@Smallhorse yum.repos.d]# mount /dev/sda2 on / type ext4 (rw) proc on /proc type proc (rw) sysfs on /sys type sysfs (rw) devpts on /dev/pts type devpts (rw,gid=5,mode=620) tmpfs on /dev/shm type tmpfs (rw,rootcontext="system_u:object_r:tmpfs_t:s0") /dev/md0 on /MyRAID type ext4 (rw) /dev/sda1 on /boot type ext4 (rw) /dev/sda5 on /home type ext4 (rw) /dev/sda3 on /usr type ext4 (rw) none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw) none on /sys/kernel/config type configfs (rw) sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw) gvfs-fuse-daemon on /root/.gvfs type fuse.gvfs-fuse-daemon (rw,nosuid,nodev) /dev/sr0 on /media/CentOS_6.3_Final type iso9660 (ro,nosuid,nodev,uhelper=udisks,uid=0,gid=0,iocharset=utf8,mode=0400,dmode=0500)
/dev/sr0 on /media/CentOS_6.3_Final这个就是我刚刚挂载的设备
cp -r /media/CentOS_6.3_Final/Packages /mnt 将镜像中的软件包文件夹复制到目标文件夹 cd /mnt/Packages 进入刚复制的文件夹 find -name "*createrepo*" 找到createrepo文件 rpm -ivh createrepo-0.9.8-5.el6.noarch.rpm 安装文件(安装提示需要先安装deltarpm,python-deltarpm) find -name "*delta*" 同样的方法找到这两个文件,安装 rpm -ivh deltarpm-3.5-0.5.20090913git.el6.i686.rpm rpm -ivh python-deltarpm-3.5-0.5.20090913git.el6.i686.rpm find -name "*create*" rpm -ivh createrepo-0.9.8-5.el6.noarch.rpm 安装createrepo createrepo /mnt 重建目标文件夹仓库信息配置文件 cd /etc/yum.repos.d 新增配置文件yumcentos.repo touch yumcentos.repo vim yumcentos.repo
在打开的文件中添加如下配置信息
[centos6] name=CentOS6 baseurl=file:///mnt enabled=1 gpgcheck=0 gpgfile=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
测试YUM本地源
yum list yum clear all
注:本文的主要目的是为了记录自己的学习过程,也方便与大家做交流。转载请注明来自:
http://blog.csdn.net/ab198604
另:本文需要单向链表的知识,如果不了解单向链表,可以访问:http://blog.csdn.net/ab198604/article/details/8253405学习
只要受过教育的人相信对集合的概念并不陌生,集合是标记着具有某些相关联或相互依赖的一系列离散数据。集合有两个重要的特点:
第一,集合中的数据成员是无序的,如果{1,3},{3,1}都表示同一集合;
第二,每个数据成员在集合中不能重复,仅且只出现一次,如{1,3,1}则不能称之为集合。
虽然我们都了解集合,也知道集合的一些基本概念及数学运算,但是在计算学科中,对集合的数据结构表示还是比较困难的,特别是C语言,因为C语言本身没有集合的这种特性,但是某些其它高级语言应该是有集合特性的,如python,perl等。本文的主要目的就是用C语言来实现“集合”这种数据结构,然后完成集合的一些操作。在进入主题之前,先复习一下集合的一些基本操作:
1 并操作:
2 交操作:
3 差操作:
注:德摩根定律:
s1-(s2并s3) = (s1-s2)交(s1-s3)
s1-(s2交s3) = (s1-s2)并(s1-s3)
有了这些基本概念之后,就不难理解集合的操作方式了。前面说道,集合是一种数据结构,也是一种组织数据的方式,把一些相关联的数据组织在一起,从这个意义上来说,集合结构的数据存储方式也可以是链表,可以用一个链表来表示某一个集合,这么理解来看,集合也是在链表的基础上进行了概念的延伸与扩展。并且,用链表的方式来表示集合这种数据结构也并有多态的特性,因为除了集合本身的一些基本操作外,有某些情况下,我们也可以使用链表的一些基本操作,比如当需要对集合中的数据进行遍历的时候,就可以用链表的方式进行遍历操作了。
一、集合的数据结构及接口定义(set.h)集合的数据结构的定义也建立在链表的基础上,实际上就是链表的数据结构定义,只不过用typedef语句重新命名而已。如下:
/* * filename: set.h * author: zhm * date: 2013-01-06 */ #ifndef SET_H #define SET_H #include <stdlib.h> #include "list.h" typedef List Set; //将链表经typedef重命名为Set集合类型下面是集合的相关操作接口,如下:
/* public interface */ void set_init(Set *set, int (*match)(const void *key1, const void *key2), void (*destroy)(void *data)); //集合初始化操作 #define set_destroy list_destroy //集合销毁,重命名链表的销毁操作 int set_insert(Set *set, const void *data); //将某一数据插入至集合中 int set_remove(Set *set, void **data); //从集合中移除某一数据 int set_union(Set *setu, const Set *set1, const Set *set2); //集合的并操作,即setu = set1 并 set2 int set_difference(Set *setd, const Set *set1, const Set *set2); //集合的差操作, 即setd = set1-set2 int set_intersection(Set *seti, const Set *set1, const Set *set2); //集合的交操作:即seti = set1 交 set2 int set_is_member(const Set *set, const void *data); //判断某一数据是否在集合中 int set_is_subset(const Set *set1, const Set *set2); //集合set1是否为set2的子集,是则返1,否则0 int set_is_equal(const Set *set1, const Set *set2); //set1是否等于set2,是否返1,否则0 #define set_size(set) ((set)->size) //返回集合中元数据大小 #endif上述接口声明后面的注释已经非常清楚,所以不再累述,但是需要注意set_init()中的第二个参数,即函数指针match, 此函数由用户自己定义,用于匹配两个元素是否相同,如果key1 = key2,则返回1,如果key1 != key2,则返回0, 如果错误则返回-1。
二、集合的接口实现细节(set.c)
(1) set_init
此函数在链表的初始化基础上,对match域进行初始化。代码如下所示:
/* * filename: set.c * author: zhm * date: 2013-01-06 */ #include <stdlib.h> #include <string.h> #include "list.h" #include "set.h" /* set_init */ void set_init(Set *set, int (*match)(const void *key1, const void *key2), void (*destroy)(void *data)) { /* init the list */ list_init(set, destroy); set->match = match; return; }(2) set_destroy
集合的销毁操作同链表操作,只不过换了个马甲。。。
(3) set_insert
集合的插入操作,在插入到集合之前,需要判断被插入的数据是否在集合中已经存在,根据集合的特性,集合中的元素是不能重复的。
/* set_insert */ int set_insert(Set *set, const void *data) { /* Do not allow the insertion of duplicates. */ if( set_is_member(set, data) ) return 1; return list_ins_next(set, list_tail(set), data); //调用链表的插入元素操作 }(4) set_remove
从集合中删除某一元素操作接口,逻辑思路也很简单,在执行删除操作之前需要判断元素为集合中的成员,如果是则删除,不是则返回相应错误信息。
/* set_remove */ int set_remove(Set *set, void **data) { ListElmt *member, *prev; //注意prev,用于记录被删除元素前面的那一元素位置,为后续删除作好准备 /* Find the member to remove */ prev = NULL; for( member = list_head(set); member != NULL; member = list_next(member) ) { if( set->match(list_data(member), *data) ) { break; } prev = member; } /* Return if the member was not found */ if( member == NULL ) return -1; /* remove the member */ return list_rem_next(set, prev, data); }(5) set_union
集合的并操作,它实现的思想是,首先先将集合set1的元素全部拷贝至集合setu中,按照集合特性,以及并操作的特点,集合set2中的元素也应存至setu中,但是需要注意元素的重复性问题,所以在拷贝set2中的元素之前需要做个判断,即判断set2中的元素是否已经存在于set1中,如果存在则不添加,否则需要添加,具体过程参见如下代码:
/* set_union */ int set_union(Set *setu, const Set *set1, const Set *set2) { void *data; ListElmt *member; /* initialize the set for the union */ set_init( setu, set1->match, NULL ); /* Insert the members of the first set */ for( member = list_head(set1); member != NULL; member = list_next(member) ) { data = list_data(member); if( list_ins_next(setu, list_tail(setu), data) != 0 ) { set_destroy(setu); return -1; } } /* Insert the members of the second set. */ for( member = list_head(set2); member != NULL; member = list_next(member) ) { if( set_is_member(set1, list_data(member)) ) { continue; } else { data = list_data(member); if( list_ins_next(setu, list_tail(setu), data) != 0 ) { set_destroy(setu); return -1; } } } return 0; }(6) set_difference
集合的差操作,它实现的思路是,集合setd保存的是差操作的结果,即set1-set2,所以根据差的定义,setd中要保存的是集合set1中的元素,并且set1中的这些元素必须是非集合set2的成员。具体代码如下:
/* set_difference */ int set_difference(Set *setd, const Set *set1, const Set *set2) { ListElmt *member; void *data; /* Initialize the set for the difference *
先看一下思路:
解决Gson混淆之后无法解析Json的问题
1、 是不要混淆Google Gson jar包中的类
2、 实现 java.io.Serializable的实体类中所有的属性名称也不能被混淆。
3、以及为了序列化和反序列化,writeObject(); readObject(); writeReplace(); readResolve();亦不可被混淆
所以,在proguard中添加
-keep class com.google.**{*;}
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }
##---------------End: proguard configuration for Gson ----------
以上代码直接粘进去就可以了。