背景技术
在C语言以及C++语言中,字符串被用作其它对象的索引或对象本身,传统的字符串是由各引用字符串的功能单元根据自身使用需要生成并独立保存,然后使用的,而且在引用过程中需要进行字符串比较时,则采取将待比较字符串的所有组成字符逐一比较的方式来确定待比较的字符串是否相同,当该功能单元引用完字符串后,则将自身保存的字符串删除。
这种传统的字符串引用方法一方面由于需要各功能单元独立保存字符串,因此有可能造成相同字符串在多个功能单元进行存储而冗余占用系统存储空间的状况。另一方面,由于各功能单元所使用字符串的长度通常比较长,也就意味着字符串的组成字符个数比较多,这时的字符串比较就成为一项非常繁琐的操作。
现有的微软软件框架库(MFC)中的CmapStringToPtr类采取将字符串与特定对象相关联,从而实现索引特定对象的目的。而如果利用该类来管理字符串,则需要将字符串与字符串关联。该方法流程如图1所示,具体包括如下步骤:
步骤101:在CmapStringToPtr类中设置一定数目的哈希(Hash)分组,每个哈希分组分别用于存储一系列与字符串相对应的哈希值。
其中,哈希值是根据CmapStringToPtr类中的一种设定算法得到的用于表现相应字符串特征的值,一个哈希值既可能对应一个字符串,也可能对应多个不同的字符串,但一个哈希值只能归属于一个哈希分组。
步骤102:当外部功能单元需要使用字符串时,则向CmapStringToPtr类输入字符串以及该字符串的关联字符串,并在自身保存关联串。以下将前者称为母串,后者称为关联串。其中,母串是外部功能单元要使用的字符串,而关联串则只是母串的索引。
步骤103:当CmapStringToPtr类接收到母串和关联串后,根据自身的一种设定算法计算关联串的哈希值,然后将得到的哈希值除以设置的哈希分组的数目,并根据计算结果确定出每个哈希值归属的哈希分组,最后将哈希值、关联串以及母串一并放入相应的哈希分组中;而如果发现不存在相应的哈希分组,则创建新的哈希分组,然后将哈希值、关联串以及母串存入新建的哈希分组中。
步骤104:当外部功能单元使用母串时,则通过向相应的CmapStringToPtr类提交自身保存的关联串获取相应的母串。
步骤105:CmapStringToPtr类根据申请首先计算出关联串的哈希值,然后根据计算所得的哈希值确定该哈希值所归属的哈希分组,最后从相应的哈希分组中索引出母串,并将其输出至外部功能单元。
从上述字符串管理过程可以看出,该现有技术通过哈希值索引相应的字符串,由于哈希值的长度通常比字符串小得多,而且哈希值长度固定,因此通过哈希值查找字符串的速度要比传统的字符串查找速度快得多。然而,该方法却存在着系统内存消耗大的弊病,主要原因是:不同的CmapStringToPtr类相互独立,各自管理内部的字符串,如果一个相同的字符串提交到两个CmapStringToPtr类中,则定会在系统内存中留下两个备份,导致系统内存的冗佘消耗。
发明内容
有鉴于此,本发明的目的在于提供一种字符串引用方法,解决现有的字符串引用方法所存在的内存消耗大的问题。
为了达到上述目的,本发明提供的字符串引用方法包括:预先设置用于保存字符串哈希值的字符串管理单元,该方法包括如下步骤:
a、外部功能单元向字符串管理单元发送携带相应字符串的字符串引用申请;
b、字符串管理单元接收到字符串引用申请后,计算申请中所携带字符串的哈希值,然后从自身保存的哈希值中查找该计算所得的哈希值,接着从保存的与该计算所得哈希值相对应的字符串中查找该申请中所携带的字符串,并输出该字符串的引用信息;
c、外部功能单元根据输出的引用信息引用字符串。
在上述方法中,所述字符串哈希值是按照由小到大或由大到小的顺序保存的;
步骤b中,所述从保存的哈希值中查找该计算所得的哈希值的方式为:二分法。
在上述方法中,所述引用信息为字符串指针。
在上述方法中,所述步骤b进一步包括:当字符串管理单元判定自身保存的哈希值中不存在该计算所得的哈希值时,在自身保存该哈希值,然后执行步骤b0;
且所述步骤b进一步包括:当字符串管理单元判定保存的与该计算所得哈希值相对应的字符串中不存在该申请中所携带的字符串时,执行步骤b0;
b0、为该申请中所携带的字符串分配存储地址,并将该字符串保存于分配的存储地址中,接着执行步骤b中输出该字符串的字符串指针的步骤。
在上述方法中,进一步包括:为保存的字符串设置标识其引用状态的引用计数;
所述步骤b进一步包括:将字符串的引用计数加1;
所述步骤b0进一步包括:为该字符串设置引用计数,并将该引用计数的值设置为1。
在上述方法中,所述步骤c之后进一步包括步骤:d、当外部功能单元引用完字符串时,通过向字符串管理单元发送字符串指针注销自身对相应字符串的引用;字符串管理单元接收到字符串指针后,根据该字符串指针从保存的字符串中查找相应的字符串,并将字符串的引用计数减1。
在上述方法中,所述步骤d之后进一步包括:
e、字符串管理单元判断该字符串的引用计数是否为0,如果是,则结束本流程;否则,删除保存的该字符串,结束本流程。
在上述方法中,所述步骤d进一步包括:当字符串管理单元接收到字符串指针后,判定该字符串指针是否合法,如果是,则继续执行步骤d中根据该字符串指针查找相应的字符串的步骤;否则,直接结束本流程。
在上述方法中,所述步骤d进一步包括:当字符串管理单元根据字符串指针查找到字符串后,计算该字符串的哈希值,并查找自身保存的哈希值中是否存在该计算所得的哈希值,如果不存在该计算所得的哈希值,则直接结束本流程;如果存在该计算所得的哈希值,则进一步查找保存的与该哈希值对应的字符串中是否存在与上述查找到的字符串相同的字符串,如果存在,则继续执行步骤d中将字符串的引用计数减1的步骤;如果不存在,则直接结束本流程。
在上述方法中,步骤c中,所述根据输出的引用信息引用字符串包括:通过引用信息从字符串的存储地址引用字符串或者通过比较引用信息实现对相应字符串的比较操作。
综上所述,本发明方法采取预先设置用于存储字符串哈希值的字符串管理单元;当外部功能单元需要使用字符串时,向字符串管理单元发送携带相应字符串的字符串引用申请;字符串管理单元接收到字符串引用申请后,计算申请中所携带字符串的哈希值,然后从自身保存的哈希值中查找该计算所得的哈希值,接着从保存的与该计算所得哈希值相对应的字符串中查找该申请中所携带的字符串,并输出该字符串的引用信息;外部功能单元根据输出的引用信息引用字符串。
由于字符串索引和存贮皆由字符串管理单元负责,因此外部功能单元在使用字符串时,只须向字符串管理单元申请引用相应的字符串,而当外部功能单元引用完该字符串时,则向字符串管理单元申请注销对该字符串的引用,这样相同的字符串在系统内存中只保存一份,从而实现了合并字符串占用空间的目的。而且在字符串管理单元内部采取排序的方式保存哈希值,从而可以通过二分法查找哈希值,加快了哈希值的查找速度,进而提高了利用哈希值查找字符串的速度,最终保证了字符串的引用速度。而在字符串管理单元外部,当涉及比较字符串的操作时,由于相同的字符串只有一个字符串指针,因此只需比较相应的字符串指针就可实现字符串比较的目的,从而实现在保证字符串引用速度的同时,优化字符串存贮,节约系统内存,优化字符串比较操作,降低对系统CPU占用的目的。
具体实施方式
为使本发明的目的、技术方案和优点更加清楚,下面结合附图对本发明作进一步的详细描述。
本发明方法的核心思想是:预先设置用于存储字符串哈希值的字符串管理单元;当外部功能单元需要引用字符串时,向字符串管理单元发送携带相应字符串的字符串引用申请;字符串管理单元接收到字符串引用申请后,计算申请中所携带字符串的哈希值,然后从自身保存的哈希值中查找该计算所得的哈希值,接着从系统内存中保存的与该计算所得哈希值相对应的字符串中查找该申请中所携带的字符串,并输出该字符串的引用信息;外部功能单元根据输出的引用信息引用字符串。从而实现在保证字符串引用速度的同时,优化字符串存贮,节约系统内存,优化字符串比较,降低CPU占用的目的。
下面通过具体实施例详细说明本发明方法,实现该方法的前提条件是:预先设置一个字符串管理单元,并在该字符串管理单元中保存一个用于存放与字符串相关数据项的数据库表;其中,与字符串相关的数据项具体包括:哈希值和字符串表,哈希值与字符串表一一对应,而字符串表则用于存储与该哈希值对应的字符串指针,并且保存的哈希值是按照由小到大或者由大到小的顺序排列的,数据库表最初是一个空表。该方法流程如图2所示,具体包括如下步骤:
步骤201:当外部功能单元需要引用字符串时,向字符串管理单元发送携带相应字符串的字符串引用申请。
其中,外部功能单元向字符串管理单元申请字符串的具体步骤包括:外部功能单元根据所需字符串的内容生成相应的字符串,然后将该字符串作为参数向字符串管理单元申请字符串对象。
步骤202:字符串管理单元接收到该字符串引用申请后,计算申请中所携带字符串的哈希值,然后从自身保存的哈希值中查找该计算所得的哈希值,接着从系统内存中保存的与该计算所得哈希值相对应的字符串中查找该申请中所携带的字符串,并输出该字符串的引用信息,即字符串指针。该步骤的具体执行过程请参见后续步骤301至306。
此处,由于字符串指针就是字符串在内存中的地址,因此输出字符串指针实质上是将保存字符串的地址输出至外部功能单元。
步骤203:外部功能单元接收到字符串管理单元输出的字符串指针后,保存相应的字符串指针,并根据保存的字符串指针进行相应的字符引用操作,如字符串比较等。
其中,由于相同的字符串只会保存于一个地址中,因此字符串与字符串指针实质上是一一对应的关系,当外部功能单元需要进行字符串比较操作时,只需间接比较相应的字符串指针是否相同,如果字符串指针相同,则表明待比较字符串是相同的;否则,表明为不同的字符串。然而当直接涉及字符串内容的操作时,则需首先通过字符串指针从内存中调用相应的字符串,然后才能引用该字符串。
而且,由于一般的字符串长度通常为十几个字节,而字符串指针的长度仅为4个字节,因此相对于字符串来讲,字符串指针占用的内存空间要小得多。从而当外部功能单元在引用字符串的过程中,保存字符串指针要比保存相应的字符串节省很大的内存空间。相对于现有技术中,在外部功能单元保存关联串,而在CmapStringToPtr类中保存母串和关联串来讲,本发明只需在外部功能单元保存相应的字符串指针无疑大大节约了系统内存空间。
步骤204:当外部功能单元引用完字符串时,通过向字符串管理单元发送字符串指针注销自身对相应字符串的引用;字符串管理单元根据该申请注销对该字符串的引用。该步骤的具体执行过程请参见后续步骤401至407。
下面说明上述步骤202,该步骤流程如图3所示,具体包括如下步骤:
步骤301:当字符串管理单元接收到外部功能单元的字符串引用申请后,计算申请中所携带字符串的哈希值。
其中,字符串的哈希值是通过对字符串包含的所有字符进行数学变换得到。举例来说:一个字符串包括:字符a和字符b,而在系统内部,a用97表示,b用98表示,如果通过加法进行数学变换,则该字符串的哈希值为:97+98=195,如果通过乘法进行数学变换,则该字符串的哈希值为:97*98=9506。由于数学变换的方式不止一种,相应地,字符串的哈希值也就有多种计算方法,然而在一个固定的程序中,只能采取一种固定算法,从而保证相同的字符串只可能有一个哈希值。
步骤302:通过二分法查找自身保存的哈希值中是否存在该计算所得的哈希值,如果是,则执行步骤303;否则,执行步骤304。
其中,由于保存的所有哈希值是按照由小到大或由大到小的顺序排列的,所以可以采用二分法查找哈希值,而具体查找方法为:首先将待查找字符串的哈希值与保存的最大哈希值和最小哈希值分别进行比较,判断该哈希值是否大于最小值且小于最大值,如果是,则进一步将待比较的哈希值同保存的所有哈希值的中间值进行比较,逐步缩小该哈希值的查找范围,从而最终确定保存的哈希值中是否存在待比较的哈希值。本发明中,对哈希值排序并采用二分法查找哈希值的方法相对于现有技术中对哈希值进行分组的方法具有两个优点,第一,查找速度更快;第二,占用的内存空间少。
步骤303:根据该哈希值查找相应的字符串表,然后查找字符串表中的所有字符串指针指示的存储地址中是否保存有相应的字符串,如果是,则执行步骤306;否则,执行步骤305。
在上述步骤中,由于不同字符串的哈希值可能相同,因此查找到的哈希值可能对应多个字符串,但在大多数情况下,它们是一一对应的。
而查找字符串的具体方式为:将申请的字符串与相应的每个存储地址中保存的字符串逐一进行比较,并逐一比较每个字符串的组成字符。需要注意的是:尽管此处仍然采用最原始的逐一比较每个字符串的组成字符的方法查找字符串,但由于预先已经根据哈希值进行过筛选,因此查找字符串所需比较的次数会大大减少,而且在大多数情况下,由于一个哈希值只对应一个字符串,往往只需比较一次。
步骤304:保存该哈希值,为该申请中所携带的字符串在系统内存中分配存储地址,然后将该字符串保存于分配的存储地址中,并创建一个与该哈希值对应的空字符串表,然后将指示该字符串存储地址的字符串指针添加至该空字符串表中,为该字符串指针设置标识外部引用状态的引用计数,并将该引用计数的值设置为1,最后输出该字符串指针,结束本流程。
步骤305:为该字符串在系统内存中分配存储地址,然后将相应的字符串保存于该存储地址中,并将指示该存储地址的字符串指针添加至保存的与该哈希值对应的字符串表中,然后为该字符串指针设置标识外部引用状态的引用计数,并将该引用计数的值设置为1,最后输出该字符串指针,结束本流程。
其中,哈希值与字符串表可以通过数据结构体的方式进行关联,如字符串表可以紧跟在哈希值的后边或者位于哈希值前边。
步骤306:将设置的标识该字符串引用状态的引用计数加1,然后输出该字符串指针。
下面说明上述步骤204,该步骤流程如图4所示,具体包括如下步骤:
步骤401:当外部功能单元引用完字符串后,则通过向字符串管理单元发送字符串指针申请注销自身对相应字符串的引用。
步骤402:字符串管理单元接收到该字符串指针后,查找该字符串指针所指示的存储地址中是否保存有字符串,如果是,则执行步骤403;否则,执行步骤407;
步骤403:计算查找到的字符串的哈希值,然后通过二分法从自身保存的所有哈希值中查找是否存在该计算所得的哈希值,如果是,则执行步骤404;否则,执行步骤407。
步骤404:查找自身保存的与该哈希值对应的字符串表,判断该字符串表中所有字符串指针所指示的存储地址中是否保存有该查找到的字符串,如果是,则执行步骤405;否则,执行步骤407。
步骤405:将该字符串的引用计数减去1,表示该字符串的外部引用又减少一个,然后判断该字符串的引用计数是否为0,如果是,则执行步骤406;否则,执行步骤407。
步骤406:删除系统内存中保存的该字符串,结束本流程。
步骤407:直接结束本流程。
在上述字符串注销流程中,采取通过字符串指针查找相应字符串,接着根据查找到的字符串计算相应的哈希值,然后根据该计算所得的哈希值查找相应字符串,最后注销对查找到字符串的引用的过程,是为了对该字符串指针的合法性进行验证,从而保证字符串不被误删掉。原因是:外部功能单元输入字符串管理单元的指针并不一定是合法的指针,这样当出现字符串管理单元接收到一个错误的指针,而又恰好根据该指针查找到了与该指针对应的一个字符串的情况时,字符串管理单元并不会因为查找到了与该字符串指针对应的字符串,就直接将该字符串注销,而是会通过后续的一系列诸如计算哈希值,查找哈希值,以及通过哈希值查找字符串的步骤来进一步验证该字符串指针是否为真实的字符串指针,从而大大降低字符串管理单元根据外部输入的假指针删除其它功能单元申请的字符串的概率,提高了字符串管理的可靠性。
当然,上述通过该字符串指针查找相应字符串的过程只是本发明的一个较佳实施例而已,本发明也可采用字符串管理单元根据接收到的字符串指针直接查找是否存在与该指针对应的字符串,如果是,则删除该字符串;否则,直接结束本流程的方式。
总之,以上所述仅为本发明的较佳实施例而已,并非用于限定本发明的保护范围。