关键字: symbian c++ 动态数组
Symbian OS 中的动态数组CArrayX的存储方式分为连续存储(Flat)和分段存储(Segmented buffer)两种。
对于Flat方式,多用于查找比较频繁的地方。对于Segmented方式,多用于存储空间大小经常发生变化的时候。
由于存在连续存储和分段存储两种不同形式的存储,CArray可根据存储形式和存储内容的不同分为4种。
(1)Fix类型,每个元素都拥有相同的长度。
(2)Var类型,各元素拥有不同的长度,每给对象都保存在各自的堆单元中,数组空间中保存着各个元素的指针。
(3)Pak类型,数组中每个元素都有可变的长度,类似于描述符对象,每个元素前面都有其自身的长度信息。
(4)Ptr类型,指针数组。
在选择存储形式时,要考虑如下问题:
(1)是否需要经常的重新分配
(2)数据元素插入和删除的频率
(3)访问数据成员的速度
下表中列出了可以使用的CArray类型:
名称 | 元素大小 | 缓冲器类型 | 用法 |
---|---|---|---|
CArrayFixFlat | 固定大小 | 平面 | 很少进行分配时,用于存储固定大小的T类和R类对象 |
CArrayVarFlat | 可变大小 | 平面 | 很少进行分配时,用于存储可变大小的T类和R类对象 |
CArrayPtrFlat | 指针 | 平面 | 很少进行分配时,用于对象指针 |
CArrayPakFlat | 大小可变(压缩) | 平面 | 很少进行分配时,用于在一个堆单元中存储可变大小的T类或R类对象 |
CArrayFixSeg | 固定大小 | 片断 | 频繁进行分配时,用于存储固定大小的T类和R类对象 |
CArrayVarSeg | 可变大小 | 片断 | 频繁进行分配时,用于存储可变大小的T类和R类对象 |
CArrayPtrSeg | 指针 | 片断 | 频繁进行分配时,用于存储对象指针 |
从上表中,我们知道了CArray提供了多个版本的类用来提供给用户更多的选择。通常我们常用的有4种:
CArrayVarFlat :存储可变长度元素,存储方式为Flat。
CArrayVarSeg:存储可变长度元素,存储方式为Segment。
CArrayPakFlat:存储固定的或者可变长度的元素,而且每个元素都保留自己的长度信息。
CArrayPtrFlat:存储数组指针,存储方式为Segment。
◎ 下面,我们将使用CArrayFixFlat和CArrayFixSeg来写一个例子,实际上,在下面的那个例子里,两个数组是完全可以互换的,因此,我只需要写一个就足够了。
在给出例子之前,我们还要再讲一下CArray的排序与查找,由于CArrayX不同于RArray类,因此,在查找与排序方面也是有很大区别的。
对于排序,我们首先要构造一个适当的键,这个键将是你排序的根本,在声明键时要指明排序的类型、字段偏移量和文本长度。其次,将键传入Sort()方法中进行排序。
下表为CArray类不同类型时,所要用到的键类型:
名称 | 键类型 | 说明 |
---|---|---|
CArrayFixFlat | TKeyArrayFix | |
CArrayVarFlat | TKeyArrayVar | |
CArrayPtrFlat | TKeyArrayFix派生类 | 需要特殊实现 |
CArrayPkgFlat | TKeyArrayVar | |
CArrayFixSeg | TKeyArrayFix | |
CArrayVarSeg | TKeyArrayVar | |
CArrayPtrSeg | TKeyArrayFix派生类 | 需要特殊实现 |
由于下面的例子中,我们使用了CArrayFixFlat,因此我们的键就是TKeyArrayFix(依照上表)
- TKeyArrayFix(TInt anOffset, TKeyCmpText aType)
TKeyArrayFix(TInt anOffset, TKeyCmpText aType)
这两个参数是:
TInt anOffset —类中字段的偏移量
TKeyCmpText aType — 对应字段的类型
对于第一个参数,Symbian中提供了一个_FOFF(c,f)宏来取得类中字段的偏移量,其中,c为类命,f为字段命。如:_FOFF(TStudent,iSName);
对于第二个参数,我们通常是可以有据可循的,请见下表:
字段类型 | 键类型 |
---|---|
数据 | ECmpTInt8、ECmpTInt16、ECmpTInt32、ECmpTInt、ECmpTUint8、ECmpTUint16、ECmpTUint32、ECmpTUint、ECmpTInt64 |
文本 | ECmpNormal、ECmpNormal8、ECmpNormal16、ECmpFolded、ECmpFolded8、ECmpFolded16、ECmpCollated、ECmpCollated8、ECmpCollated16、 |
- class TStudent
- {
- public :
- TStudent(const TDesC& aSName,TUint aSNo,TReal aScore);
- public :
- TUint iSNo;
- TReal iScore;
- TBuf<10> iSName;
- };
- TStudent::TStudent(const TDesC& aSName,TUint aSNo,TReal aScore)
- {
- iSNo = aSNo;
- iScore = aScore;
- iSName = aSName;
- }
- void ManageStu()
- {
- //使用CArrayFixFlat,很少进行分配时,用于存储固定大小的T类和R类对象
- CArrayFixFlat<TStudent>* StuArrayFlat;
- //这里也可以改成CArrayFixSeg<TStudent>* StuArraySeg;
- StuArrayFlat = new (ELeave)CArrayFixFlat<TStudent>(5);
- CleanupStack::PushL(StuArrayFlat);
- //分配空间存储两个学生的信息
- _LIT(KSTUDENT1,"GuanYabei" );
- _LIT(KSTUDENT2,"WuMingshi" );
- _LIT(KRETURN,"/n" );
- TBuf<10> StuName1 = KSTUDENT1;
- TBuf<10> StuName2 = KSTUDENT2;
- //初始化两个学生的信息(姓名,学号,分数)
- TStudent stu1(StuName1,1,100.0);
- TStudent stu2(StuName2,2,99.5);
- //添加到数组中,请注意,用到的是AppendL()方法,它是可能引起异常的
- StuArrayFlat->AppendL(stu1);
- StuArrayFlat->AppendL(stu2);
- // 显示所有的学生信息
- _LIT(KFORMAT2,"id is %d" );
- _LIT(KFORMAT3,"score is %f" );
- for (TInt i=0; i<StuArrayFlat->Count(); i++)
- {
- console->Printf(_L("name is " ));
- console->Printf((*StuArrayFlat)[i].iSName);
- // 如果你觉得指针括号太多而不够美观,我们也可以使用另一种方法
- // 即,使用At()函数
- // 如:console->Printf(StuArrayFlat->At(i).iSName);
- console->Printf(KRETURN);
- console->Printf(KFORMAT2,(*StuArrayFlat)[i].iSNo);
- console->Printf(KRETURN);
- console->Printf(KFORMAT3,(*StuArrayFlat)[i].iScore);
- console->Printf(KRETURN);
- }
- console->Printf(_L("Press any key to continue/n" ));
- console->Getch();
- //删除数组中的元素
- console->Printf(_L("Delete first Student/n" ));
- StuArrayFlat->Delete(0);
- for (i=0; i<StuArrayFlat->Count(); i++)
- {
- console->Printf(_L("name is " ));
- console->Printf((*StuArrayFlat)[i].iSName);
- console->Printf(KRETURN);
- console->Printf(KFORMAT2,(*StuArrayFlat)[i].iSNo);
- console->Printf(KRETURN);
- console->Printf(KFORMAT3,(*StuArrayFlat)[i].iScore);
- console->Printf(KRETURN);
- }
- console->Printf(_L("Press any key to continuce/n" ));
- console->Getch();
- //修改第一个学生的姓名
- console->Printf(_L("Modify first student's name/n" ));
- console->Printf(_L("first student old name is " ));
- console->Printf((*StuArrayFlat)[0].iSName);
- console->Printf(KRETURN);
- (*StuArrayFlat)[0].iSName = _L("GuanYabei" );
- console->Printf(_L("first student new name is " ));
- console->Printf((*StuArrayFlat)[0].iSName);
- console->Printf(KRETURN);
- console->Printf(_L("Press any key to continue/n" ));
- console->Getch();
- //以姓名方式查找
- console->Printf(_L("Find student by name/n" ));
- //建立主键,对于不同类型的CArray有不同的主键类型
- //_FOFF(c,f)宏来取得类中字段的偏移量
- TKeyArrayFix nameKey(_FOFF(TStudent,iSName), ECmpNormal);
- TInt findPos;
- TStudent S(StuName1,0,0);
- console->Getch();
- if (StuArrayFlat->Find(S, nameKey, findPos) != KErrNotFound)
- {
- //查找对象是S,按ECmpNormal格式
- console->Printf(_L("findPos is %d " ),findPos);
- console->Printf((*StuArrayFlat)[findPos].iSName);//直接引用findPos的值,有的书上写findPos-1,这是错误的!
- }
- console->Printf(KRETURN);
- console->Printf(_L("Press any key to continue/n" ));
- console->Getch();
- //以成绩方式排序
- TKeyArrayFix scoreKey(_FOFF(TStudent,iScore), ECmpTInt32);
- User::LeaveIfError(StuArrayFlat->Sort(scoreKey));
- for (i=0;i<StuArrayFlat->Count();i++)
- {
- console->Printf(_L("name is " ));
- console->Printf((*StuArrayFlat)[i].iSName);
- console->Printf(KRETURN);
- console->Printf(KFORMAT2,(*StuArrayFlat)[i].iSNo);
- console->Printf(KRETURN);
- console->Printf(KFORMAT3,(*StuArrayFlat)[i].iScore);
- console->Printf(KRETURN);
- }
- CleanupStack::PopAndDestroy();
- }
class TStudent
{
public:
TStudent(const TDesC& aSName,TUint aSNo,TReal aScore);
public:
TUint iSNo;
TReal iScore;
TBuf<10> iSName;
};
TStudent::TStudent(const TDesC& aSName,TUint aSNo,TReal aScore)
{
iSNo = aSNo;
iScore = aScore;
iSName = aSName;
}
void ManageStu()
{
//使用CArrayFixFlat,很少进行分配时,用于存储固定大小的T类和R类对象
CArrayFixFlat<TStudent>* StuArrayFlat;
//这里也可以改成CArrayFixSeg<TStudent>* StuArraySeg;
StuArrayFlat = new(ELeave)CArrayFixFlat<TStudent>(5);
CleanupStack::PushL(StuArrayFlat);
//分配空间存储两个学生的信息
_LIT(KSTUDENT1,"GuanYabei");
_LIT(KSTUDENT2,"WuMingshi");
_LIT(KRETURN,"/n");
TBuf<10> StuName1 = KSTUDENT1;
TBuf<10> StuName2 = KSTUDENT2;
//初始化两个学生的信息(姓名,学号,分数)
TStudent stu1(StuName1,1,100.0);
TStudent stu2(StuName2,2,99.5);
//添加到数组中,请注意,用到的是AppendL()方法,它是可能引起异常的
StuArrayFlat->AppendL(stu1);
StuArrayFlat->AppendL(stu2);
// 显示所有的学生信息
_LIT(KFORMAT2,"id is %d");
_LIT(KFORMAT3,"score is %f");
for(TInt i=0; i<StuArrayFlat->Count(); i++)
{
console->Printf(_L("name is "));
console->Printf((*StuArrayFlat)[i].iSName);
// 如果你觉得指针括号太多而不够美观,我们也可以使用另一种方法
// 即,使用At()函数
// 如:console->Printf(StuArrayFlat->At(i).iSName);
console->Printf(KRETURN);
console->Printf(KFORMAT2,(*StuArrayFlat)[i].iSNo);
console->Printf(KRETURN);
console->Printf(KFORMAT3,(*StuArrayFlat)[i].iScore);
console->Printf(KRETURN);
}
console->Printf(_L("Press any key to continue/n"));
console->Getch();
//删除数组中的元素
console->Printf(_L("Delete first Student/n"));
StuArrayFlat->Delete(0);
for(i=0; i<StuArrayFlat->Count(); i++)
{
console->Printf(_L("name is "));
console->Printf((*StuArrayFlat)[i].iSName);
console->Printf(KRETURN);
console->Printf(KFORMAT2,(*StuArrayFlat)[i].iSNo);
console->Printf(KRETURN);
console->Printf(KFORMAT3,(*StuArrayFlat)[i].iScore);
console->Printf(KRETURN);
}
console->Printf(_L("Press any key to continuce/n"));
console->Getch();
//修改第一个学生的姓名
console->Printf(_L("Modify first student's name/n"));
console->Printf(_L("first student old name is "));
console->Printf((*StuArrayFlat)[0].iSName);
console->Printf(KRETURN);
(*StuArrayFlat)[0].iSName = _L("GuanYabei");
console->Printf(_L("first student new name is "));
console->Printf((*StuArrayFlat)[0].iSName);
console->Printf(KRETURN);
console->Printf(_L("Press any key to continue/n"));
console->Getch();
//以姓名方式查找
console->Printf(_L("Find student by name/n"));
//建立主键,对于不同类型的CArray有不同的主键类型
//_FOFF(c,f)宏来取得类中字段的偏移量
TKeyArrayFix nameKey(_FOFF(TStudent,iSName), ECmpNormal);
TInt findPos;
TStudent S(StuName1,0,0);
console->Getch();
if(StuArrayFlat->Find(S, nameKey, findPos) != KErrNotFound)
{
//查找对象是S,按ECmpNormal格式
console->Printf(_L("findPos is %d "),findPos);
console->Printf((*StuArrayFlat)[findPos].iSName);//直接引用findPos的值,有的书上写findPos-1,这是错误的!
}
console->Printf(KRETURN);
console->Printf(_L("Press any key to continue/n"));
console->Getch();
//以成绩方式排序
TKeyArrayFix scoreKey(_FOFF(TStudent,iScore), ECmpTInt32);
User::LeaveIfError(StuArrayFlat->Sort(scoreKey));
for(i=0;i<StuArrayFlat->Count();i++)
{
console->Printf(_L("name is "));
console->Printf((*StuArrayFlat)[i].iSName);
console->Printf(KRETURN);
console->Printf(KFORMAT2,(*StuArrayFlat)[i].iSNo);
console->Printf(KRETURN);
console->Printf(KFORMAT3,(*StuArrayFlat)[i].iScore);
console->Printf(KRETURN);
}
CleanupStack::PopAndDestroy();
}